11

我有一个应用程序站点 (NodeJS),我想从 Express 迁移到 Hapi,我通常做的是提供静态文件并将其他所有内容路由到包含 angularjs 应用程序和 angular 路由配置的单个页面。

// Express routing, first the static files
app.use( express.static(__dirname + '/public') );

// Second the api routes
app.get('/api', function(req, res){
    res.send( {api: 'response' } )
});

// Finally everything else maps to the single page app:
app.get('*', function(req, res){
    res.sendfile('./public/html/controllers.index.html')
});

在 HapiJS 中,我不知道如何复制相同的代码(不使用 express.static 中间件),因为:

Hapi = require('hapi');
var server =  new Hapi.Server('localhost', 84);

server.route({
    method: 'GET',
    path: '/{p*}',
    handler: function (request, reply) {
        reply.file('public/html/index.html');
    }
});

在上面的代码中,无论什么请求都会映射到我的单个页面('public/html/index.html'),但是如果我这样做,那么 js、css、jpg 和文件将被映射到相同的文件而不是脚本,样式和图像(对'/images/bg.png'的请求将下载单个页面而不是图像文件)。

我知道,如果我将路径 '/' 设置为我的单个页面,然后将 '{p*}' 设置为 '{directory: {path: '/public'}}',那么我将拥有我需要的行为,但是有一个问题,如果某个用户复制并粘贴一个特定的 url(比如说'/account/login')然后按回车,该路由将映射到 HapiJS 并且响应将是“未找到(404)”,角度路由永远无法回应。

有谁知道如何解决这个问题?

问题的关键部分是:

  • 仅使用 HapiJS(不使用 express 或其他中间件)
  • 不要路由每条角度路由(只需将其他所有尚未路由到单页的东西路由到 Angular 可以处理路由)
4

6 回答 6

7

不确定这是否会对您有所帮助,但您的起始代码对于 Hapi.js 来说有点“奇怪”。这就是我用来设置简单 hapi.js SPA 的方法。

如果您希望使用特定的 URL,例如帐户/登录名,则必须将路径指向该特定部分。(路径:'/account/login')

不同之处在于我指向整个目录,包括。不同的文件,您只需回复 index.html 文件。列表参数让您决定是否要在您的 url 中显示目录结构。默认为假。

更多信息在这里:http ://hapijs.com/tutorials/serving-files#directory-handler

var Hapi = require('hapi');
var Path = require('path');

var server = new Hapi.Server(8080, 'localhost');


server.route({
    method: 'GET',
    path: '/{path*}',
    handler: {
 		directory: {
            path: './public',
            listing: false,
            index: true
        }
    }      
});



server.start(function(){
	console.log('server started');
});

于 2014-10-22T16:16:25.383 回答
5

惰性文档的启发,我通过从静态目录中提供所有内容来解决这个问题。然后我添加了一个 onPostHandler 以在即将返回 404 时返回索引文件。然后,您的客户端路由器可以将重定向发送到静态文件目录中的现有 404.html 文件。

// Static Assets
server.route({
  method: 'GET',
  path: '/{param*}',
  handler: {
    directory: {
      path: ['app/static'],
      listing: false,
      index: ['index.html']
    }
  }
});

// return index.html for everything else
server.ext('onPostHandler', (request, reply) => {
  console.log('WORD');
  const response = request.response;
  if (response.isBoom && response.output.statusCode === 404) {
    return reply.file('app/static/index.html');
  }
  return reply.continue();
});
于 2016-09-13T06:11:01.350 回答
2

这个答案是无效的。正如@Al jey 在评论中所说。Hapi 有自己的算法对路线进行排序,请不要遵循此答案。


与 expressJS 类似,Hapi 按顺序处理路由。只需按优先级定义路线顺序:

server.route(
{    // Angular/API Route
    method: 'GET',
    path: '/api',
    handler: function (request, reply) {
         reply( {api: 'response' } )
    }
});

server.route({    // Other assets If you have
    method: 'GET',
    path: '/assets/{param*}',
    handler: {
    directory: {
        path: './assets',
        listing: false,
        index: true
    }
});

server.route({   // Everything else 
    method: 'GET',
    path: '/{p*}',
    handler: function (request, reply) {
        reply.file('public/html/index.html');
    }
});
于 2015-01-23T11:38:52.240 回答
1

我在惰性方面取得了成功,就像这里描述的那样。如果向下滚动,您可以找到“目录处理程序”部分。

我的解决方案如下所示:

var Hapi = require('hapi');
var Path = require('path');

var server = new Hapi.Server();
server.connection({ 
  host: 'localhost',
  port: 8001 
});

server.register(require('inert'), (err) => {

  if (err) {
    throw err;
  }

  server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
      directory: {
        path: 'public'
      }
    }
  });


  server.start((err) => {

    if (err) {
      throw err;
    }

    console.log('Server running at:', server.info.uri);
  });
});
于 2016-03-17T19:03:04.650 回答
1

确保你有惰性作为插件。

在您的 server.js(或您命名的任何名称)中,配置相对路径以提供静态文件,请参见下文

const server = new Hapi.Server({
  connections: {
    routes: {
      cors: true,
      files: {
        relativeTo: Path.join(__dirname, 'public')
      }
    },
    router: {
      stripTrailingSlash: true
    }
  }
})

然后为您的路线注册一个新的路线插件,如下所示。这是假设您输入 index.html(对于 React 或 Angular)在上面配置的公共目录中

exports.register = (server, options, next) => {
  server.route([{
    method: 'GET',
    path: '/{param*}',
    handler: {
      directory: {
        path: '.',
        redirectToSlash: true,
        listing: false,
        index: true
      }
    }
  }])
  server.ext('onPostHandler', (req, res) => {
    const response = req.response
    if (response.isBoom && response.output.statusCode >= 404) {
      return res.file('index.html')
    }
    return res.continue()
  })
  next()
}

exports.register.attributes = {
  name: 'static-route',
  version: '1.0.0'
}

现在每次 HapiJS 抛出 404 错误,它的路由都会被转发到你的 React / Angular App,如果它存在,它可以处理路由。

于 2016-12-11T12:27:06.870 回答
0

对于使用 Hapi@18 和 Inert 的人。

  const server = Hapi.server({
    port: 3000,
    routes: {
      files: {
        relativeTo: Path.join(__dirname, 'build'),
      }
    }
  });

  server.route({
    method: 'GET',
    path: '/static/{param?}',
    handler: {
      directory: {
        path: '.',
        redirectToSlash: true,
      }
    }
  });

  server.route({
    method: 'GET',
    path: '/{any*}',
    handler: {
      file: 'index.html'
    }
  });

这里 my./build包含所有 JS 资产和index.html. index.html请求入口点./build/main.js/static/main.js. 其余的脚本是相对的。

于 2019-11-24T08:21:22.193 回答