使用Node和Express处理静态HTML文件。如何将所有请求路由到index.html?

53
我正在使用Node + Express和Handlebars来制作一个单页Web应用程序,目前从一个相当标准的server.js文件中提供index.html,一切都正常运行。

我正在使用Node + Express和Handlebars来制作一个单页Web应用程序,目前从一个相当标准的server.js文件中提供index.html,一切都正常运行:

var express = require('express');

var server = express();
server.use(express.static(__dirname + '/public'));

var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

当从http://localhost:10001/加载时,这个很完美。我的问题是,我在应用程序中使用了推送状态,所以浏览器可能显示像http://localhost:10001/foo/bar这样的URL,然后如果我刷新页面,就会出现错误Cannot GET /foo/bar,因为没有该路由。

那么我的问题是,抱歉,当涉及到Node时,我的知识非常初级,我能否使所有请求都路由到index.html? 我的应用程序中的JavaScript可以根据页面加载时的URL参数来显示正确的内容。 我不想定义自定义路由,因为它们的数量可能很大,并且它们的路径可以动态更改。

5个回答

60
const express = require('express')
const server = express()

/* route requests for static files to appropriate directory */
server.use('/public', express.static(__dirname + '/static-files-dir'))

/* other routes defined before catch-all */
server.get('/some-route', (req, res) => {
  res.send('ok')
})

/* final catch-all route to index.html defined last */
server.get('/*', (req, res) => {
  res.sendFile(__dirname + '/index.html');
})

const port = 8000;
server.listen(port, function() {
  console.log('server listening on port ' + port)
})

5
需要注意的是,通配符路由应该放在静态中间件和其他get路由之后,正如其他答案所指出的那样。 - Akseli Palén
"server.use('/public', express.static(__dirname + '/public'));" 中的 public 有什么用途?在以后的步骤中,是否可以使用它来为指定的路由名称提供别名 "__dirname + '/public'" 并提供单个文件服务? - IKriKan

11

在处理抓取所有路由的前端应用程序之前,该模式将提供静态资产。要注册其他路由,只需将它们添加到抓取所有路由之上即可。

var express = require('express');
var server = express();

// middleware
server.use(express.static(__dirname + '/public'));

// routes
server.use('*', function (req, res) {
  // serve file
});

var port = 10001;
server.listen(port, function() {
  console.log('server listening on port ' + port);
});

1
嘿,我只是想指出你正在导入“static”,但实际上从未使用它,因为你使用的是“express.static”。 - kemicofa ghost
@kemicofa,发现得好!已修复! - Nick Tomlin

8
var app = express();

var options = {
  dotfiles: 'ignore',
  etag: true,
  extensions: ['htm', 'html'],
  index: 'index.html',
  lastModified: true,
  maxAge: '1d',
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
    res.header('Cache-Control', 'public, max-age=1d');
  }
};

app.use(compression());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());

app.use('/', express.static(__dirname + '/public', options));
app.use('*', express.static(__dirname + '/public', options));

8
这个简短的东西表现良好:
import express from "express";

const app = express(),
      staticServe = express.static(`${ __dirname }/public`);

app.use("/", staticServe);
app.use("*", staticServe);

请确保HTML/JS文件中的所有URL都是绝对路径,因为所有不存在的资源都将返回index.html文件。

Express v 4.15.2


3
var express = require('express');

var server = express();
server.use(express.static(__dirname + '/public'));

server.get('*', function(req, res){
  res.sendFile('index.html');
});

var port = 10001;
server.listen(port, function() {
    console.log('server listening on port ' + port);
});

这个代码可以工作,但是我所做的修改也会影响到我的CSS文件的URL,导致它返回index.html而不是CSS文件。有没有一种方法只针对MIME类型应用此代码(例如,仅在HTML上)? - JPollock
@JPollock 在你的 catch-all 路由之前为公共文件注册中间件。这样,css/js 的请求将在你的 index 路由之前被处理。 - Nick Tomlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接