在使用react开发过程中为了SEO等要进行SSR,那么就要进行客户端和服务端分开打包,且客户端的入口文件打包后(index.js)要在服务端的静态模版里被引用,如下:
const content = renderToString(
<StaticRouter location={req.path} context={context}>
{renderRoutes(routes)}
</StaticRouter>
);
return `
<html>
<head>
<title>Home</title>
</head>
<body>
<div id="root">${content}</div>
<script src="/index.js"></script>
</body>
</html>
`
在单纯打包SPA客户端代码时,我们可以使用html-webpack-plugin插件进行配置静态模版引入文件,即使文件名进行hash也没问题,因为他是根据打包入口文件进行引入打包后的文件;在SSR的时候,需要分开打包,那么这种方式就不再起作用,我们就需要进行另外想办法咯。
因为如果每次客户端代码打包后的文件名会发生变更,所以在服务端的代码引入这个文件的时候也会发生改变,服务端也就需要每次都进行再次打包,既然两端都要进行打包,那么都需要运行打包命令,那么我们就找到了一个解决办法:node命令是可以在代码里通过process.env.HASH获取到HASH参数的,那么我们在打包时可以先配置package.json
"scripts": {
"dev": "npm-run-all --parallel dev:**",
"dev:build": "webpack --config webpack.server.js --watch",
"dev:client": "webpack --config webpack.client.js --watch --$HASH",
"dev:start": "nodemon --watch build --exec node \"./build/bundle.js\""
}
⚠️:这里注意要执行以上组合命令需要如下操作,
npm install npm-run-all -g
安装npm-run-all
npm install nodemon -g
安装nodemon
这样就可以在打包的时候直接运行命令 HASH=20190710_01 yarn dev
or HASH=20190710_01 npm run dev
传参,在客户端打包文件(webpack.client.js)里接收参数,如下:
output: {
filename: "index_"+process.env.HASH+".js", // 接收参数
path: path.resolve(__dirname, "public")
},
服务端代码(webpack.server.js),如下:
import clientConfig from '../../webpack.client.js'
...
...
return `
<html>
<head>
<title>Home</title>
</head>
<body>
...
<!--直接调用客户端打包输出文件名-->
<script src="/${clientConfig.output.filename}"></script>
</body>
</html>
`
以上,就解决了客户端打包文件名变更,且服务端正确引用的问题;
PS:其他同学若有更好方式,尽可以在浏览评论中提出供大家参考,Thx!
网友评论