DLL文件又稱爲動態連接庫文件,它一般做爲應用程序可執行代碼的一部分,供應用程序在運行時進行調用。html
在Webpack中,內置的DllPlugin與DllReferencePlugin插件能夠經過使用DLL來大幅提升構建性能,如下是DLL機制流程圖:
node
爲了便於實驗,咱們經過使用create-react-app
建立項目並eject出webpack配置:react
npx create-react-app react-dll-demo cd react-dll-demo && npm run eject
因爲默認配置隱藏了編譯信息,打開webpackDevServer.config.js
,將quiet: true
改成false,再啓動一下項目,找出咱們須要的信息:webpack
Version: webpack 4.28.3 Time: 6985ms Built at: 2019-02-21 10:46:42 Asset Size Chunks Chunk Names asset-manifest.json 232 bytes [emitted] index.html 1.65 KiB [emitted] static/js/0.chunk.js 4.21 MiB 0 [emitted] static/js/bundle.js 30.9 KiB runtime~main [emitted] runtime~main static/js/main.chunk.js 47.4 KiB main [emitted] main static/media/logo.5d5d9eef.svg 2.61 KiB [emitted]
首先在package.json的scripts字段添加一條腳本:git
{ "build:dll": "webpack --config config/webpack.dll.config.js --mode production" }
而後建立配置文件:github
// config/webpack.dll.config.js const webpack = require('webpack'); const path = require('path'); module.exports = { entry: { react: ['react', 'react-dom'] }, output: { filename: '[name].dll.js', path: path.join(__dirname, '../public/dll'), libraryTarget: 'var', library: '_dll_[name]_[hash]' }, plugins: [ new webpack.DllPlugin({ path: path.join(__dirname, '../public/dll', '[name].manifest.json'), name: '_dll_[name]_[hash]' }) ] };
執行npm run build:dll
,CLI應該會自動提示你安裝webpack-cli
,運行完成後能夠看到如下文件:web
public/dll ├── react.dll.js └── react.manifest.json
打開config/webpack.config.js
,在根對象plugins字段中寫入該插件:npm
{ plugins: [ // ... new webpack.DllReferencePlugin({ manifest: require(path.join( __dirname, '../public/dll/react.manifest.json' )) }), ] }
最後一個步驟,在index.html咱們先手動引入dll依賴:json
... <div id="root"></div> <script src="/dll/react.dll.js"></script> ...
此時從新運行程序,等待項目正常運行,再檢查一下編譯信息:緩存
Version: webpack 4.28.3 Time: 4883ms Built at: 2019-02-21 11:19:11 Asset Size Chunks Chunk Names asset-manifest.json 232 bytes [emitted] index.html 1.69 KiB [emitted] static/js/0.chunk.js 1.82 MiB 0 [emitted] static/js/bundle.js 30.9 KiB runtime~main [emitted] runtime~main static/js/main.chunk.js 52.1 KiB main [emitted] main static/media/logo.5d5d9eef.svg 2.61 KiB [emitted]
很顯然的看到,在development模式下,構建時間下降了2s,打包大小下降了2.4M,相信將DLL運用到項目工程中,你能收穫到更多的驚喜。
以上程序只是爲了快速入手與demo搭建,須要優化的地方還有不少,在此簡單的列舉幾點,供你們參考。
經過安裝html-webpack-include-assets-plugin
插件,能夠自動將相應文件注入到index.html中,就能夠避免手動進行更改了:
// config/webpack.config.js const HtmlIncludeAssetsPlugin = require('html-webpack-include-assets-plugin'); // ... { plugins: [ new HtmlIncludeAssetsPlugin({ assets: ['dll/react.dll.js'], append: false // 在其餘資源前添加 }), ] }
咱們一般不會對html文件作緩存,每次發版本時採用增量發佈,只要html的依賴文件名變了,則會從新去解析靜態資源列表。除此以外,還須要提供一個函數,自動去加載文件夾內的多入口dll文件,如下爲核心代碼:
config/dllHelper.js:
// config/dllHelper.js const webpack = require('webpack'); const path = require('path'); const fs = require('fs'); const dllConfig = require('./webpack.dll.config'); // 根據entry生成DllReferencePlugin列表 function genDllReferences() { return Object.keys(dllConfig.entry).map( name => new webpack.DllReferencePlugin({ manifest: require(path.join( __dirname, '../public/dll', `${name}.manifest.json` )) }) ); } // 生成dll文件的靜態資源路徑 function loadDllAssets() { return fs .readdirSync(path.resolve(__dirname, '../public/dll')) .filter(filename => filename.match(/.dll.js$/)) .map(filename => `dll/${filename}`); } module.exports = { loadDllAssets, genDllReferences };
config/webpack.dll.config.js:
// { ... output: { filename: '[name].[hash:8].dll.js' } }
config/webpack.config.js:
const dllHelper = require('./dllHelper'); ... { plugins: [ ...dllHelper.genDllReferences(), new HtmlIncludeAssetsPlugin({ assets: dllHelper.loadDllAssets(), append: false }) ] }
若DLLPlugiun的entry發生變化,則dll內的文件可能會愈來愈多,所以咱們須要在構建dll前清空文件夾,在這裏推薦這兩個package:
首先安裝相應依賴:yarn add -D rimraf npm-run-all
,而後修改package.json:
scripts: { "make:dll": "npm-run-all clear:dll build:dll", "build:dll": "webpack --config config/webpack.dll.config.js --mode production", "clear:dll": "rimraf public/dll", }
以後在變更DLL時,必定要記得執行:npm run make:dll
。
Demo倉庫地址:GitHub - vv13/react-dll-demo