Webpack代码分割后页面无内容:Chunk未加载问题排查
解决Webpack代码分割后React应用无法加载的问题
我折腾了一整天才搞定这个坑:本来想通过Webpack把单一的bundle.js拆分成多个chunk优化加载速度,结果拆分后React应用完全不显示,控制台只提示index.ejs已经正常加载,但页面就是空白。之前用单个bundle.js的时候一切都好好的,当时index.ejs里直接用<script src="/views/bundle.js"></script>引入脚本就行。
初始的webpack.config.js配置
module.exports = { devServer: { historyApiFallback: true }, entry: { index: ["./src/index.js"], vendor: [ "react", "react-dom", "react-redux", "react-router", "react-router-dom", "redux" ] }, output: { path: __dirname + '/public/views', filename: "[name].js", publicPath: "/views/" }, module: { loaders: [ { test: /\.js$/, loader: "babel-loader", exclude: [/node_modules/, /pdfmake.js$/] }, { test: /\.json$/, loader: "json-loader" } ] }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: "vendor", filename: "vendor.js", minChunks: Infinity }), new webpack.optimize.CommonsChunkPlugin({ name: "meta", chunks: ["vendor"], filename: "meta.js" }), new webpack.NamedModulesPlugin(), new HtmlWebpackPlugin({ title: "Deals", filename: __dirname + "/views/index.ejs", template: __dirname + "/views/template.ejs", inject: false }), new PreloadWebpackPlugin({ rel: "preload", as: "script", include: "all" }), new webpack.optimize.OccurrenceOrderPlugin(), ] };
生成的简化版index.ejs
可以看到,预加载的chunk标签确实生成了,但没有实际的script标签引入这些chunk文件:
<!DOCTYPE html> <html lang="en"> <head> <link href="/pace.css" rel="stylesheet" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes"> <meta charset="utf-8"> <link rel="stylesheet" href="/style.css"> <link rel="canonical" href="http://verygoodprof.fr/" /> <link rel="preload" as="script" href="/views/index.js"> <link rel="preload" as="script" href="/views/vendor.js"> <link rel="preload" as="script" href="/views/meta.js"> </head> <body> <noscript> <a href="http://enable-javascript.com/">Javascript must me enabled to use this site.</a> </noscript> <div class="text-center root" id="root"> </div> </body> </html>
修改后的webpack.config.js配置(已解决问题)
感谢@margaretkru的指点,调整后的配置如下:
module.exports = { devServer: { historyApiFallback: true }, entry: { app:"./src/index.js", vendor: [ "axios", "jquery", "react", "react-dom", "react-redux", "react-router", "react-router-dom", "redux" ] }, output: { path: __dirname + '/public/views', filename: "[name].js", publicPath: "/views/" }, module: { loaders: [ { test: /\.js$/, loader: "babel-loader", exclude: [/node_modules/, /pdfmake.js$/] }, { test: /\.json$/, loader: "json-loader" } ] }, plugins: [ new webpack.NamedModulesPlugin(), new HtmlWebpackPlugin({ filename: __dirname + "/views/index.ejs", template: __dirname + "/views/template.ejs", inject: 'body', chunks: ['vendor', 'app'], chunksSortMode: 'manual' }), new PreloadWebpackPlugin({ rel: "preload", include: ["vendor", "app"] }), new webpack.optimize.OccurrenceOrderPlugin(), new webpack.optimize.CommonsChunkPlugin({ name: "vendor", minChunks: Infinity }) ] };
核心问题分析
一开始我以为是脚本加载顺序的问题,但实际上关键在于:只通过PreloadWebpackPlugin添加了预加载标签,但没有让HtmlWebpackPlugin自动注入实际的script标签。
把HtmlWebpackPlugin的inject参数从false改为'body',同时指定chunks: ['vendor', 'app']和chunksSortMode: 'manual'后,插件会自动在index.ejs的body末尾注入<script src="/views/vendor.js"></script>和<script src="/views/app.js"></script>标签,浏览器才会真正加载并执行这些chunk文件,React应用也就正常显示了。
内容的提问来源于stack exchange,提问作者Louis
相关产品推荐
相关产品推荐

