详解如何webpack使用DllPlugin


举个例子:很多产品都用到螺丝,但是工厂在生产不同产品时,不需要每次连带着把螺丝也生产出来,因为螺丝可以单独生产,并给多种产品使用。在这里螺丝的作用就可以理解为是dll。

为什么要使用Dll

通常来说,我们的代码都可以至少简单区分成业务代码和第三方库。如果不做处理,每次构建时都需要把所有的代码重新构建一次,耗费大量的时间。然后大部分情况下,很多第三方库的代码并不会发生变更(除非是版本升级),这时就可以用到dll:把复用性较高的第三方模块打包到动态链接库中,在不升级这些库的情况下,动态库不需要重新打包,每次构建只重新打包业务代码。

还是上面的例子:把每次构建,当做是生产产品的过程,我们把生产螺丝的过程先提取出来,之后我们不管调整产品的功能或者设计(对应于业务代码变更),都不必重复生产螺丝(第三方模块不需要重复打包);除非是产品要使用新型号的螺丝(第三方模块需要升级),才需要去重新生产新的螺丝,然后接下来又可以专注于调整产品本身。

基本用法

使用dll时,可以把构建过程分成dll构建过程和主构建过程(实质也就是如此),所以需要两个构建配置文件,例如叫做webpack.config.js和webpack.dll.config.js。

1. 使用DLLPlugin打包需要分离到动态库的模块

DllPlugin是webpack内置的插件,不需要额外安装,直接配置webpack.dll.config.js文件:

module.exports = {=
entry: {
// 第三方库
react: ['react', 'react-dom', 'react-redux']
},
output: {
// 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称,
filename: '[name].dll.js',
path: resolve('dist/dll'),
// library必须和后面dllplugin中的name一致 后面会说明
library: '[name]_dll_[hash]'
},
plugins: [
// 接入 DllPlugin
new webpack.DllPlugin({
// 动态链接库的全局变量名称,需要和 output.library 中保持一致
// 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
name: '[name]_dll_[hash]',
// 描述动态链接库的 manifest.json 文件输出时的文件名称
path: path.join(__dirname, 'dist/dll', '[name].manifest.json')
}),
]
}
我们先来看看,这一步到底做了什么。执行:webpack --config webpack.dll.config,然后到指定的输出文件夹查看输出:

react.dll文件里是使用数组保存的模块,索引值就作为id;
react.manifest.json文件里,是用来描述对应的dll文件里保存的模块
里暴露出刚刚构建的所有模块,如下:

{
"name":"react_dll_553e24e2c44987d2578f",
"content":{
"./node_modules/webpack/node_modules/process/browser.js":{"id":0,"meta":{}},"./node_modules/react/node_modules/fbjs/lib/invariant.js":{"id":1,"meta":{}},"./node_modules/react/lib/Object.assign.js":{"id":2,"meta":{}},"./node_modules/react/node_modules/fbjs/lib/warning.js":{"id":3,"meta":{}}
//省略相似代码
}
}
2. 在主构建配置文件使用动态库文件

在webpack.config中使用dll要用到DllReferencePlugin,这个插件通过引用 dll 的 manifest 文件来把依赖的名称映射到模块的 id 上,之后再在需要的时候通过内置的 webpack_require 函数来 require 他们.

new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./dist/dll/react.manifest.json')
}),
第一步产出的manifest文件就用在这里,给主构建流程作为查找dll的依据:DllReferencePlugin去 manifest.json 文件读取 name 字段的值,把值的内容作为在从全局变量中获取动态链接库中内容时的全局变量名,因此:在 webpack_dll.config.js 文件中,DllPlugin 中的 name 参数必须和 output.library 中保持一致。

3. 在入口文件引入dll文件。

生成的dll暴露出的是全局函数,因此还需要在入口文件里面引入对应的dll文件。

<body>
<div id="app"></div>
<!--引用dll文件-->
<script src="../../dist/dll/react.dll.js" ></script>
</body>
作用

首先从前面的介绍,至少可以看出dll的两个作用

分离代码,业务代码和第三方模块可以被打包到不同的文件里,这个有几个好处:

避免打包出单个文件的大小太大,不利于调试
将单个大文件拆成多个小文件之后,一定情况下有利于加载(不超出浏览器一次性请求的文件数情况下,并行下载肯定比串行快)
提升构建速度。第三方库没有变更时,由于我们只构建业务相关代码,相比全部重新构建自然要快的多。

注意事项

从前面可以看到dll带来的优点,但并不意味着我们就应该把除业务代码外的所有代码全部都丢到dll中,举一个例子:
1.对于lodash这种第三方库,正确的用法是只去import所需的函数(用什么引什么),例如:

// 正确用法
import isPlainObject from 'lodash/isPlainObject'
//错误用法
import { isPlainObject } from 'lodash'
这两种写法的差别在于,打包时webpack会根据引用去打包依赖的内容,所以第一种写法,webpack只会打包lodash的isPlainObject库,第二种写法却会打包整个lodash。现在假设在项目中只是用到不同模块对lodash里的某几个函数并且没有对于某个函数重复使用非常多次,那么这时候把lodash添加到dll中,带来的收益就并不明显,反而导致2个问题:

由于打包了整个lodash,而导致打包后的文件总大小(注意是总大小)比原先还要大
在dll打包太多内容也需要耗费时间,虽然我们一般只在第三方模块更新之后才进行重新预编译(就是dll打包的过程),但是如果这个时间太长的话体验也不好、
实践与反思

放一张自己在一个比较大的项目中单纯使用dll之后的收益,提取的内容是 react相关的第三方库,和fish组件,构建时间从120s降低到80s左右(当然这个时间还是有点恐怖),构建前appjs的大小是680kb,拆分业务代码和第三方代码分别是400kb和380kb(这就是拆分后大小大于拆分前大小的例子),从这一点来看,对于常见第三方库是否要放进dll可能比较明确(比如react系列打包一般肯定不亏),但是还有一些就要结合具体的项目内容来进行判断和取舍。(强烈推荐使用webpack-bundle-analyzer插件进行性能分析)








总结

本文介绍了Dllplugin的思想,基本用法和应用场景(关于使用的部分更详细的内容可以看官方文档),结合个人的一些实践经验,对于常见第三方库是否要放进dll可能比较明确(比如react系列打包一般肯定不亏),但是还有一些就要结合具体的项目内容来判断,例如我上面的实践的例子就说明目前的拆分还不够好。这一块也欢迎大家一起探讨。



  • webpack鎬荤粨绡
    绛旓細绗竴绉嶆柟寮忥細閫氳繃wepack鍐呯疆鏂规硶 绗簩绉嶆柟寮忥細閫氳繃ES2015 Loader Spec import()鏂瑰紡杩斿洖涓涓猵romise鍦╥mport涓紶鍏ラ渶瑕佷緷璧栫殑鏄庯紝鍔ㄦ佸姞杞芥ā鍧楋紝灏卞彲浠ュ儚浣跨敤Promise涓鏍蜂娇鐢╥mport().then()浠g爜鍒嗗壊鍦烘櫙 渚嬪瓙 杩愯鎵撳寘杩欐椂loadash鎻愬彇鍒皏endor涓 image.png 杩欐椂鍊欒繕涓嶆槸鎴戜滑鎯宠鐨 image.png image.png im...
  • 濡備綍瑙h webpack 鐨勬瀯寤烘祦绋?
    绛旓細Webpack 鐨勬瀯寤烘祦绋嬪彲浠ュ垎涓轰互涓嬪嚑涓楠わ細 1. 鍒濆鍖栧弬鏁帮細浠庨厤缃枃浠跺拰 Shell 璇彞涓鍙栦笌鍚堝苟鍙傛暟锛屽緱鍑烘渶缁堢殑鍙傛暟銆2. 寮濮嬬紪璇戯細鍒濆鍖 compiler 瀵硅薄锛屾敞鍐屾墍鏈夌殑鎻掍欢銆3. 瑙f瀽妯″潡锛氫粠鍏ュ彛鏂囦欢寮濮嬶紝鎵惧埌鎵鏈変緷璧栫殑妯″潡锛岄掑綊澶勭悊銆4. 缂栬瘧妯″潡锛浣跨敤 loader 瀵规ā鍧楄繘琛岀紪璇戝鐞嗐5. 杈撳嚭璧...
  • 璇﹁В濡備綍浣跨敤webpack鎵撳寘澶氶〉jquery椤圭洰
    绛旓細铏界劧宸茬粡2019骞翠簡涓嶈繃鏈変竴浜涢」鐩繕鏄渶瑕佺敤鍒癹query鐨勪笉杩囪冭檻鍒颁娇鐢╦query鐨勪竴鍫嗗吋瀹规ч棶棰樹篃涓轰簡鍙互椤哄埄鍦颁娇鐢‥S6鏉ユ捀浠g爜鐮旂┒浣跨敤webpack+babel鎵撳寘浠g爜鏉ュ彂甯冨嚑涓噸鐐癸細1.涓轰簡灏嗘ā鍧楀垎鍓插姞杞斤紝涓嶈嚦浜庝竴涓猨s鏂囦欢杩囧ぇ锛屼竴涓〉闈腑浣跨敤澶氫釜js鏂囦欢2.鐢变簬鏄椤甸」鐩紙澶氫釜html锛夛紝姣忎釜椤甸潰浣跨敤鐨刯s鏂囦欢閮戒笉...
  • 浣跨敤webpack濡備綍鎻愬彇绗笁鏂瑰簱
    绛旓細output: { path: __dirname + '/bulid/', // 鏂囦欢鍚嶇О filename: '[name].js' }, plugins: { // 杩欓噷瀹炰緥鍖webpack.optimize.CommonsChunkPlugin鏋勯犲嚱鏁 // 鎵撳寘涔嬪悗灏辩敓鎴恦endor.js鏂囦欢 new
  • 濡備綍浣跨敤webpack杩涜cdn閰嶇疆鍛?
    绛旓細鍦ㄧ嚎椤圭洰鍦板潃 vue-cli2.x 浣跨敤webpack绫诲瀷鍒涘缓涓涓悕涓簑ebpack-cdn-demo鐨剉ue椤圭洰銆傚鏋滃畨瑁呯殑vue-cli鏄3.x鐗堬紝鍛戒护浼氭湁鎵涓嶅悓銆傝鍙傝vue-cli3浜嗚В璇︾粏淇℃伅銆傚畨瑁呬緷璧栨 鍚姩涓涓」鐩 涓嬮潰绠鍗曚粙缁嶄竴涓嬬洰褰曠粨鏋勩俠uild鏂囦欢澶逛腑鐨剋ebpack.prod.conf.js鏄垜浠殑涓绘枃浠讹紝鎴戜滑鍦ㄥ叾涓姩鎬佽缃笉闇瑕佹墦鍖...
  • 濡備綍鐢╳ebpack鎵撳寘涓涓綉绔欏簲鐢
    绛旓細杩欐牱鎴戜滑鐨刪tml閲岀洿鎺ュ紩鐢╟ss鍜宩s锛屽畬鎴愪竴涓綉椤靛簲鐢ㄣ鐢╳ebpack涔熺被浼硷紝鍙槸webpack鎶婂浘鐗囥乧ss鍜宩s閮界紪璇戞墦鍖呮垚涓涓枃浠讹紝鎴戜滑鍙渶瑕佸紩鐢ㄤ竴涓枃浠跺氨鍙互浜嗐1.鎴戜滑闇瑕佸厛瀹夎node鐜銆傛病瀹夎鐨勮鑷瀹夎 2.鍦ㄩ」鐩洰褰曚笅杈撳叆npm init鍒濆鍖栦竴涓猲ode椤圭洰锛岃緭鍏ラ」鐩悕绉扮瓑淇℃伅锛屽畬鎴愬悗鐢熸垚涓涓猵ackage....
  • webpack-鎵撳寘浼樺寲鏂规
    绛旓細椤圭洰閲岄潰浣跨敤 ElementUI 鍜 Echarts 閮芥槸鍏ㄩ儴寮曠敤鎸傚湪 Vue.prototype 涓婏紝鐜伴兘鏀逛负鎸夐渶寮曠敤銆傞澶勭悊鍚勭鏂囦欢鏃舵寚瀹氬尮閰嶇洰褰曞悗锛 webpack 瑙f瀽鏂囦欢鏃跺氨涓嶄細寰幆鏌ユ壘鍏朵粬鐩綍锛屽姞蹇В鏋愰熷害銆倃ebpack 鎵ц棰勫鐞嗘枃浠舵椂鍗曠嚎绋嬬殑锛屾垜浠彲浠ヤ娇鐢 happypack 鏉ュ绾跨▼澶勭悊鏂囦欢銆備慨鏀 webpack.base.js 鏂囦欢 babel-...
  • 璇﹁В濡備綍浣跨敤webpack鍦╲ue椤圭洰涓啓jsx璇硶
    绛旓細鏈枃浠嬬粛浜濡備綍浣跨敤webpack鍦╲ue椤圭洰涓啓jsx璇硶锛屽垎浜粰澶у锛屽叿浣撳涓:鎴戜滑鐭ラ亾Vue 2.0涓铏氭嫙DOM鐨勬敮鎸併傛垜浠彲浠ラ氳繃JavaScript鍔ㄦ佺殑鍒涘缓鍏冪礌锛岃屼笉鐢ㄥ湪template涓啓HTML浠g爜銆傝櫄鎷烡OM鏈缁堝皢琚覆鏌撲负鐪熸鐨凞OM銆俤ata: { msg: 'Hello world'},render (h) { return h( 'div', { attrs: { id...
  • 浠涔堟槸WebPack,涓轰粈涔堣浣跨敤瀹
    绛旓細webpack main.js bundle.js Webpack 姣 Browserify 鏇村己澶, 浣犱竴鑸細鐢 webpack.config.js 鏉ョ粍缁囧悇涓繃绋:// webpack.config.js module.exports = { entry: './main.js',output: { filename: 'bundle.js'} };杩欎粎浠呮槸 JavaScript, 鍙互闅忔剰娣诲姞瑕佽繍琛岀殑浠g爜.3. 鎬庢牱鍚姩 webpack 鍒囨崲鍒版湁...
  • 鎬庝箞浣跨敤webpack鏋勫缓vue.js鍗曢〉搴旂敤
    绛旓細js锛webpack锛実ulp锛岃繕鏈夐タ浜嗕箞寮婧愮殑elementUI锛屽洜涓浣跨敤浜唀s2015锛屾墍浠ヨ繕闇瑕佸紩鍏abel灏唀s6鐨刯s浠g爜杞崲鎴恊s5銆傚繀椤荤敤鍒扮殑渚濊禆濡備笅 "dependencies": { "babel-core": "^6.18.2", "babel-preset-es2015": "^6.18.0", "config": "^1.24.0", "element-ui": "^1.0.0", "...
  • 扩展阅读:怎么强制退出talkback ... webpack打包vue一键 ... webpack基本配置详解 ... webpack进行一些特定配置 ... webpack打包项目怎么使用 ... webpack各个版本配置 ... webpack面试题及答案 ... 谈谈你对webpack的理解 ... 安装webpack详细步骤 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网