webpack打包分离第三方库和业务代码

使用webpack打包工程,通常会需要分离第三方类库和应用本身的代码,因为第三方类库更新频率不高,这样浏览器可以直接从缓存读,不需要项目每次上线再获取一次。

以react为例,正常情况下,最初是这么配置的:

复制代码
 1 module.exports = {
 2     entry: {
 3         app: "./src/App.js",  4 vendor: ["react", "react-dom"]  5  },  6  output: {  7 path: __dirname + "/dist",  8 filename: "[name].[chunkhash:8].js",  9 publicPath: "/dist/" 10  }, 11  ... 12  plugins: [ 13  ... 14 new webpack.optimize.CommonsChunkPlugin({ 15 names: ["vendor"] 16  }) 17  ] 18 };
复制代码

然后我们会发现,一旦应用代码发生变化,重新打包后app.js和vendor.js的hash值都会发生变化,具体原因大致就是由于app.js变了,webpack会生成一段runtime注入vendor.js,导致vendor.js也变了(因为两者有关联)。

解决方法目前我知道二种比较好。

第一种是利用webpack.DllPlugin,具体使用方法网上很多,配置稍微有点复杂,这里不列举了。

第二种方法是利用CommonsChunkPlugin生成一个专门跟踪vendor.js变化的js文件,一般可以取名manifest.js,具体配置如下:

复制代码
 1 module.exports = {
 2     entry: {
 3         app: "./src/App.js",  4 vendor: ["react", "react-dom"]  5  },  6  output: {  7 path: __dirname + "/dist",  8 filename: "[name].[chunkhash:8].js",  9 publicPath: "/dist/" 10  }, 11  ... 12  plugins: [ 13  ... 14 new webpack.optimize.CommonsChunkPlugin({ 15 names: ["vendor", "manifest"] 16  }) 17  ] 18 };
复制代码

其中CommonsChunkPlugin的配置还能这么配:

复制代码
 1 module.exports = {
 2     ...
 3  plugins: [  4  ...  5 new webpack.optimize.CommonsChunkPlugin({  6 names: ["vendor"]  7  }),  8 new webpack.optimize.CommonsChunkPlugin({  9 names: ["manifest"], 10 chunks: ["vendor"] 11  }) 12  ] 13 };
复制代码

完成后我们修改应用代码,再重新打包,结果vendor.js的hash值不再发生变化。

我看过的网上的教程,基本上都到这里就结束了。然而当我运行代码,想查看效果,结果却是空白页,chrome下有报错:

???

当时真是一下就懵了。google、stackoverflow搜了好久都没找到满意的答案(可能是搜商比较低)。

后来我无意中去看生成的index.html,发现里面插入的js顺序是这样的:

然后再打开chrome里的第一行报错:

发现报错是从app.js开始的。正常情况下应该是app.js引用vendor.js中的方法,即app.js的加载顺序应该在vendor.js之后,但现在顺序却颠倒了,会不会是这个原因造成的?

于是我们手动修改index.html,交换一下app.js和vendor.js的加载顺序。再重新运行代码,结果显示正确了。

看来是chunks注入顺序混乱导致的,那有没有方法按照正确的引用顺序注入呢?这就要看html-webpack-plugin插件了。

原本关于html-webpack-plugin插件我们是这么配的:

复制代码
 1 module.exports = {
 2     ...
 3  plugins: [  4  ...  5 new HtmlPlugin({  6 filename: "../index.html",  7 template: __dirname + "/src/templates/index.html"  8  })  9  ] 10 };
复制代码

而html-webpack-plugin中有个配置项叫chunksSortMode,它可以指定chunks注入的顺序,其可以配置为:"none" | "auto" | "dependency" | {function}。默认配置是"auto"。

现在我们加上这个配置项,并配置为"dependency":

复制代码
 1 module.exports = {
 2     ...
 3  plugins: [  4  ...  5 new HtmlPlugin({  6 filename: "../index.html",  7 template: __dirname + "/src/templates/index.html",  8 chunksSortMode: "dependency"  9  }) 10  ] 11 };
复制代码

然后再重新打包,再看index.html,发现这下app.js在vendor.js后面了,最后运行程序也能正常显示了。

使用webpack打包工程,通常会需要分离第三方类库和应用本身的代码,因为第三方类库更新频率不高,这样浏览器可以直接从缓存读,不需要项目每次上线再获取一次。

以react为例,正常情况下,最初是这么配置的:

复制代码
 1 module.exports = {
 2     entry: {
 3         app: "./src/App.js",  4 vendor: ["react", "react-dom"]  5  },  6  output: {  7 path: __dirname + "/dist",  8 filename: "[name].[chunkhash:8].js",  9 publicPath: "/dist/" 10  }, 11  ... 12  plugins: [ 13  ... 14 new webpack.optimize.CommonsChunkPlugin({ 15 names: ["vendor"] 16  }) 17  ] 18 };
复制代码

然后我们会发现,一旦应用代码发生变化,重新打包后app.js和vendor.js的hash值都会发生变化,具体原因大致就是由于app.js变了,webpack会生成一段runtime注入vendor.js,导致vendor.js也变了(因为两者有关联)。

解决方法目前我知道二种比较好。

第一种是利用webpack.DllPlugin,具体使用方法网上很多,配置稍微有点复杂,这里不列举了。

第二种方法是利用CommonsChunkPlugin生成一个专门跟踪vendor.js变化的js文件,一般可以取名manifest.js,具体配置如下:

复制代码
 1 module.exports = {
 2     entry: {
 3         app: "./src/App.js",  4 vendor: ["react", "react-dom"]  5  },  6  output: {  7 path: __dirname + "/dist",  8 filename: "[name].[chunkhash:8].js",  9 publicPath: "/dist/" 10  }, 11  ... 12  plugins: [ 13  ... 14 new webpack.optimize.CommonsChunkPlugin({ 15 names: ["vendor", "manifest"] 16  }) 17  ] 18 };
复制代码

其中CommonsChunkPlugin的配置还能这么配:

复制代码
 1 module.exports = {
 2     ...
 3  plugins: [  4  ...  5 new webpack.optimize.CommonsChunkPlugin({  6 names: ["vendor"]  7  }),  8 new webpack.optimize.CommonsChunkPlugin({  9 names: ["manifest"], 10 chunks: ["vendor"] 11  }) 12  ] 13 };
复制代码

完成后我们修改应用代码,再重新打包,结果vendor.js的hash值不再发生变化。

我看过的网上的教程,基本上都到这里就结束了。然而当我运行代码,想查看效果,结果却是空白页,chrome下有报错:

???

当时真是一下就懵了。google、stackoverflow搜了好久都没找到满意的答案(可能是搜商比较低)。

后来我无意中去看生成的index.html,发现里面插入的js顺序是这样的:

然后再打开chrome里的第一行报错:

发现报错是从app.js开始的。正常情况下应该是app.js引用vendor.js中的方法,即app.js的加载顺序应该在vendor.js之后,但现在顺序却颠倒了,会不会是这个原因造成的?

于是我们手动修改index.html,交换一下app.js和vendor.js的加载顺序。再重新运行代码,结果显示正确了。

看来是chunks注入顺序混乱导致的,那有没有方法按照正确的引用顺序注入呢?这就要看html-webpack-plugin插件了。

原本关于html-webpack-plugin插件我们是这么配的:

复制代码
 1 module.exports = {
 2     ...
 3  plugins: [  4  ...  5 new HtmlPlugin({  6 filename: "../index.html",  7 template: __dirname + "/src/templates/index.html"  8  })  9  ] 10 };
复制代码

而html-webpack-plugin中有个配置项叫chunksSortMode,它可以指定chunks注入的顺序,其可以配置为:"none" | "auto" | "dependency" | {function}。默认配置是"auto"。

现在我们加上这个配置项,并配置为"dependency":

复制代码
 1 module.exports = {
 2     ...
 3  plugins: [  4  ...  5 new HtmlPlugin({  6 filename: "../index.html",  7 template: __dirname + "/src/templates/index.html",  8 chunksSortMode: "dependency"  9  }) 10  ] 11 };
复制代码

然后再重新打包,再看index.html,发现这下app.js在vendor.js后面了,最后运行程序也能正常显示了。

猜你喜欢

转载自www.cnblogs.com/lcosima/p/8909986.html
今日推荐