在404中直接导航到单页节点应用程序中的URL



我有一个连接到ReactJS前端的NodeJS后端(不使用create-react-app(。

我将React前端和Node后端与webpack捆绑在一起。webpack配置的输出在我的应用程序文件夹的根目录中创建了一个"dist"目录。在"dist"目录中,我有一个捆绑的server.js文件和一个"public"目录,其中包含index.html和捆绑的.js/.css文件。

目录结构如下:

dist
- server.js
- public
-- index.html
-- client.{hash}.js
-- client.{hash}.css

(上面的hash替换为Webpack生成的hash(。

我通过运行NODE_ENV='production' node ./dist/server.js来启动服务器。这将在我的终端中记录一个打开的端口(例如:60245(,当我导航到localhost:{port}时,我的应用程序将运行,并加载使用React Router v4构建的默认路由,例如:localhost:{PORT}/pages/dashboard if the user is authenticated

问题是,如果我直接转到一个URL(例如:localhost:{PORT}/pages/dashboard(,我会得到404响应,并在我的终端中看到Error: ENOENT: no such file or directory, stat '/dist/public/index.html'

经过相当多的谷歌搜索,我添加了以下条件:

app.use(express.static('dist/public'));
app.use('/api', routes);
if (process.env.NODE_ENV === 'production') {
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/public/index.html'));
});
} else {
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../../dist/public/index.html'));
});
}

在开发模式下运行应用程序时,我可以毫无问题地直接转到URL。只有在生产中运行应用程序时才会发生这种情况。

整个应用程序的文件结构如下:

config
-- webpack
--- webpack.dev.config.js
--- webpack.prod.config.js
-- tests
dist
- server.js
- public
-- index.html
-- client.{hash}.js
-- client.{hash}.css
node_modules
src
- client
-- {all client stuff}
- server 
-- {all server stuff}
{config files}

在开发过程中,我只捆绑react前端,而不是服务器,我使用Webpack dev服务器来提供react前端,我代理nodemon提供的后端服务器,我在同一位置构建一个内存中的"dist"文件夹,这就是为什么非生产sendFile方法会在几个目录中运行。

你知道我做错了什么吗?

我弄清楚了实际问题是什么,它与webpack有关,而不是与node_env等有关。有关更多信息,请参阅此处:https://github.com/webpack/webpack/issues/1599.

对于子孙后代来说,解决方案是添加

node: {
__dirname: false
}

因为webpack似乎在编译时更改了__dirname的根。

然后,我将静态index.html文件的路径更新为

app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});

突然间,所有的路都通了!

TL;DR添加

node: {
__dirname: false
}

如果您也在编译服务器代码,请将其转换为webpack-config。

只需看看path.join的结果,自己看看它是否是正确的路径。把它放在服务器的代码中:console.log(path.join(__dirname, 'dist/public/index.html'))