nodejs hapi单页

时间:2014-10-16 04:04:42

标签: node.js angularjs routing hapijs

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

// 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'}}',那么我将拥有我的行为需要,但有一个问题,如果一些用户复制并粘贴一个特定的网址(比如'/ account / login'),然后按回车键,那条路线将被映射到HapiJS,响应将是'未找到(404)' ,角度路由永远无法响应。

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

问题的关键部分是:

  • 仅使用HapiJS(无快递或其他中间件)
  • 不要路由每个角度路由(只是路由其他未路由到单页子角的其他路径可以处理路由)

6 个答案:

答案 0 :(得分:7)

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

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

不同之处在于我指向整个目录,包括。不同的文件,您只需回复index.html文件。使用listing参数可以决定是否要在网址中显示目录结构。默认为false。

此处有更多信息: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');
});

答案 1 :(得分:5)

inert documentation的启发,我通过提供静态目录中的所有内容解决了这个问题。然后我添加了一个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();
});

答案 2 :(得分: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');
    }
});

答案 3 :(得分:1)

我在惰性方面取得了成功,如here所述。如果向下滚动,可以找到"目录处理程序"。

部分

我的解决方案看起来像这样:

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);
  });
});

答案 4 :(得分: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,然后它可以处理路径(如果存在)。

答案 5 :(得分: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'
    }
  });

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