简体   繁体   English

如何使用为单个页面应用程序提供服务的ExpressJS管理丢失的静态文件?

[英]How to manage missing static files with ExpressJS that serves a single page application?

In my application all queries from the browser with "/_/*" goes to my static folder: 在我的应用程序中,来自浏览器的所有带有“ / _ / *”的查询都进入我的静态文件夹:

app.use('/_', express.static(path.join(__dirname, '_')));

Then all GETs to / goes to an HTML file (single page application in HTML5 mode ): 然后,所有到/的GET都进入一个HTML文件( HTML5模式下的单页应用程序):

app.get('/*', function(req, res) {
  //some request preprocessing in done here...
  hbs.render(path.join(__dirname + '/apps/home.html')).then(function (data) {
        res.send(data);
    });
});

This works great unless there is a missing static file. 除非缺少静态文件,否​​则此方法效果很好。 If my HTML calls '/_/iDontExist.js', the static middleware from express do not find the file and propagates the event which gets matched by app.get('/*' . 如果我的HTML调用'/_/iDontExist.js',则来自express的静态中间件找不到文件,并传播由app.get('/*'匹配的事件。

This is not correct, I want Angular to respond with a 404 if the URL starts with '/_' and the file is not present instead of trying to match the URL with some other route in my chain. 这是不正确的,如果URL以“ / _”开头并且文件不存在,我希望Angular响应404,而不是尝试将URL与链中的其他路由进行匹配。

Change app.get('/*' so it sends a 404 if the URL doesn't resolve to a real page. 更改app.get('/*'以便在URL无法解析为实际页面时发送404。


Well, that's the simple answer. 好吧,这就是简单的答案。

You're probably writing your SPA using the history API which is designed to let you map URLs in the SPA onto real URLs. 您可能正在使用历史记录API编写SPA,该API旨在使您将SPA中的URL映射到真实URL。

This is a great piece of design because it allows you to generate the same HTML if the page is requested directly or dynamically update the URL when you using JS to modify one page to turn it into another. 这是一个很棒的设计,因为如果您直接请求该页面或使用JS修改一个页面以将其转换为另一个页面时动态地更新URL,它可以使您生成相同的HTML。 (This lets you make dynamic changes and only modify a small part of the DOM for performance). (这使您可以进行动态更改,并且仅修改DOM的一小部分以提高性能)。

You get problems if you don't implement it properly and forget about the server. 如果执行不正确而忘记了服务器,则会遇到问题。

There is a nasty trend (not helped by Angular's documentation telling you to do this!) towards making every single URL onto the same , practically empty HTML document and depending on JS to generate all the content. 有一个讨厌的趋势(Angular的文档告诉您不要这样做!)是将每个URL都制作到相同的 ,实际上是空的HTML文档中,并依靠JS来生成所有内容。

This means you lose the performance benefits of having the initial page load have all the content just there. 这意味着您将失去初始页面加载具有所有内容的性能优势。

You lose the ability of clients which don't support JS to view the page. 您将失去不支持JS的客户端查看页面的能力。

You lose the fallback for when the JS fails for whatever reason . 当JS 由于任何原因失败时,您都将失去后备的能力。

And you end up with a bunch of duplicate URLs all pointing at the same contentless page (probably not great food for search engines). 最后,您得到了一堆重复的URL,它们都指向同一无内容的页面(对于搜索引擎来说可能不是很好的食物)。

If you aren't serving up real pages from the server, you might as well be using hashbangs. 如果您不是从服务器提供真实的页面,则不妨使用hashbangs。 While they have lots of problems , using the history API without the server side part of the system shares those problems and introduces a couple more. 尽管它们有很多问题 ,但使用不带系统服务器端部分的历史记录API会遇到这些问题,并且还会引入更多问题。


So, the good solution to this is to build the server side of the code (you should investigate the term "isomorphic js") and then you can 404 for any pages which aren't found. 因此,对此的一个好的解决方案是构建代码的服务器端(您应该研究术语“同构js”),然后可以对未找到的任何页面进行404处理。


The less good solution would be to switch to using hashbags and change '/*' to '/' 较差的解决方案是切换到使用哈希包,并将'/*'更改为'/'


And the dirty hack which leaves you with the bad use of the history API would be to just check the URL inside your /* handler and 404 if it starts with /_ 肮脏的hack使您对History API的使用不当,它只是检查/*处理程序中的URL和以/_开头的404。

You could create your own small middleware - example: 您可以创建自己的小型中间件-示例:

app.use('/_', express.static(path.join(__dirname, '_')));

var dontAcceptUnderscorePath = function(req, res, next){
 if(req.url.startsWith('/_'))
    res.status(404).send();
  else
    next();
}

app.get('/*', dontAcceptUnderscorePath, function(req, res) {
   //some request preprocessing in done here...
   hbs.render(path.join(__dirname + '/apps/home.html')).then(function (data) {
    res.send(data);
   });
});

Don't match redirect stuff to your index.html which starts with _ . 不要将重定向内容匹配到以_开头的index.html。

app.get(/^[^_].*$/, function(req, res) { // or perhaps /^(?!_).*$/

});

Then handle 404s below. 然后在下面处理404。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM