我有一个连接到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'))