详解webpack性能优化——DLL


Posted in Javascript onOctober 20, 2017

Webpack性能优化的方式有很多种,本文之所以将 dll 单独讲解,是因为 dll 是一种最简单粗暴并且极其有效的优化方式。

在通常的打包过程中,你所引用的诸如:jquery、bootstrap、react、react-router、redux、antd、vue、vue-router、vuex 等等众多库也会被打包进 bundle 文件中。由于这些库的内容基本不会发生改变,每次打包加入它们无疑是一种巨大的性能浪费。

Dll 的技术就是在第一次时将所有引入的库打包成一个 dll.js 的文件,将自己编写的内容打包为 bundle.js 文件,这样之后的打包只用处理 bundle 部分。

以一个 Vue 项目为例,首先创建一个名为 webpack.dll.config.js 的文件

var path = require("path"),
fs = require('fs'),

webpack = require("webpack");

var vendors = [

'vue', 

'vue-router', 

'vuex'
];

module.exports = {

entry: {


vendor: vendors

},

output: {


path: path.join(__dirname, "dist"),


filename: "Dll.js",


library: "[name]_[hash]"

},

plugins: [


new webpack.DllPlugin({



path: path.join(__dirname, "dist", "manifest.json"),



name: "[name]_[hash]",



context: __dirname


})

]
};

这个文件的作用是将 vue、vue-router 以及 vuex 合并打包为一个名为 Dll.js 的静态资源包,同时生成一个 manifest.json 文件方便对 Dll.js 中的模块进行引用。

要注意的是,执行 webpack 命令是默认执行该目录下名为 webpack.config.js 或者 webpackfile.js 的文件。所以需要通过 --config 指令手动指定该文件,最后加入 -p 指令将 Dll.js 压缩。

$ webpack --config webpack.dll.config.js -p

这样,在项目根目录下就会多增加一个 dist 文件夹,其中有压缩之后的 Dll.js 与 manifest.json 文件。

manifest.json 文件内容如下,给各个模块赋予 id 以便引用。

{
 "name": "vendor_2beb750db72b1cda4321",
 "content": {
  "./node_modules/process/browser.js": {
   "id": 0,
   "meta": {}
  },
  "./node_modules/vue-router/dist/vue-router.esm.js": {
   "id": 1,
   "meta": {
    "harmonyModule": true
   },
   "exports": [
    "default"
   ]
  },
  "./node_modules/vue/dist/vue.runtime.esm.js": {
   "id": 2,
   "meta": {
    "harmonyModule": true
   },
   "exports": [
    "default"
   ]
  },
//.......

最后在 webpack.config.js 中添加引用。在 plugins 属性中添加 DllReferencePlugin 插件,并指明 manifest.json 文件的引用路径。

//...
plugins: [
  new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require('./dist/manifest.json')
  })
]

在确保成功执行 webpack.dll.config.js 文件后,执行 webpack -p 进行项目打包。

详解webpack性能优化——DLL

可以看到打包在 Dll 文件中的文件都被 delegated(委派) ,而不是直接打进 bundle 文件中。

这样我们就将所有的资源完成打包,生成的 dist 目录如下:

详解webpack性能优化——DLL

不过 dist 文件夹要想作为一个完整的工程还少一个 html 文件,我创建了一个名为 pack.js 的文件,使用 nodejs 的 fileSystem 对 html 文件进行修改并拷贝。

pack.js

var fs = require('fs');

fs.readFile('./index.html', 'utf8', (err, data) => {
  if (!err) {
    var dataStr = data.toString(),
    timestamp = (new Date()).getTime();
  
    dataStr = dataStr
          .replace('bundle.js', 'bundle.js?v='+timestamp)
          .replace('<!-- dll -->', '<script src="./dist/Dll.js?v='+ timestamp +'"></script>');

    fs.writeFile('./dist/index.html', dataStr, (error) => {
      if (!error) {
        console.log('HTML file copy successfully');
      } else {
        console.log(error);
      }
    });
  } else {
    console.log(err);
  }
});

我们需要在模块的入口 html 中添加 <!-- dll --> 的占位字符,pack.js 的作用就是将 html 文件拷贝一份到 dist 目录下,同时将 <!-- dll --> 替换为引用 Dll.js 的 script 标签,并在引用文件后添加时间戳。

<!-- .... -->
<body>
<div id="demo" class="container"></div>

<!-- dll -->
<script src="./bundle.js"></script>
</body>
</html>

在执行 webpack -p 打包后,输入下面命令运行 pack.js,就会在 dist 目录下生成 html 文件。

$ node pack.js

详解webpack性能优化——DLL

内容如下:

<!-- .... -->
<body>
<div id="demo" class="container"></div>

<script src="./dist/Dll.js?v=1488250309725"></script>
<script src="./bundle.js?v=1488250309725"></script>
</body>
</html>

这样 dist 文件夹就作为一个完整的、不需要任何手动操作、已经压缩混淆后的项目可以直接进行线上的部署。

实际项目模板参考地址如下。由于笔者作为 React 与 Vue 的双持开发者,所以创建了两个模板,以便之后通过 yomen(yo) 之类的进行脚手架工具化。

https://github.com/Darylxyx/generator-yx-react

https://github.com/Darylxyx/generator-yx-vue

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 1.0.2
Oct 11 Javascript
javascipt基础内容--需要注意的细节
Apr 10 Javascript
关于js内存泄露的一个好例子
Dec 09 Javascript
JavaScript获取当前页面上的指定对象示例代码
Feb 28 Javascript
js实现鼠标悬停图片上时滚动文字说明的方法
Feb 17 Javascript
JavaScript简单判断复选框是否选中及取出值的方法
Aug 13 Javascript
javascript实现根据汉字获取简拼
Sep 25 Javascript
Angularjs的Controller间通信机制实例分析
Nov 07 Javascript
js设置文字颜色的方法示例
Dec 30 Javascript
微信小程序wx:for和wx:for-item的用法详解
Apr 01 Javascript
完美解决linux下node.js全局模块找不到的情况
May 16 Javascript
ES7之Async/await的使用详解
Mar 28 Javascript
vue利用better-scroll实现轮播图与页面滚动详解
Oct 20 #Javascript
浅谈如何使用 webpack 优化资源
Oct 20 #Javascript
利用jQuery实现简单的拖曳效果实例代码
Oct 20 #jQuery
Js利用prototype自定义数组方法示例
Oct 20 #Javascript
js 中rewrap-ajax.js插件实例代码
Oct 20 #Javascript
jQuery访问浏览器本地存储cookie、localStorage和sessionStorage的基本用法
Oct 20 #jQuery
JS 中使用Promise 实现红绿灯实例代码(demo)
Oct 20 #Javascript
You might like
用PHP实现ODBC数据分页显示一例
2006/10/09 PHP
php使用filter过滤器验证邮箱 ipv6地址 url验证
2013/12/25 PHP
php数组去重复数据示例
2014/02/25 PHP
PHP网站自动化配置的实现方法(必看)
2017/05/27 PHP
laravel 实现根据字段不同值做不同查询
2019/10/23 PHP
自己的js工具_Form 封装
2009/08/21 Javascript
jValidate 基于jQuery的表单验证插件
2009/12/12 Javascript
用Juery网页选项卡实现代码
2011/06/13 Javascript
jQuery源码分析-03构造jQuery对象-工具函数
2011/11/14 Javascript
JavaScript数组常用方法
2015/03/02 Javascript
jQuery中toggle()函数的使用实例
2015/04/17 Javascript
利用JavaScript的AngularJS库制作电子名片的方法
2015/06/18 Javascript
js获取上传文件的绝对路径实现方法
2016/08/02 Javascript
Nodejs--post的公式详解
2017/04/29 NodeJs
Bootstrap 模态框自定义点击和关闭事件详解
2018/08/10 Javascript
使用JavaScript破解web
2018/09/28 Javascript
vue中将html字符串转换成html后遇到的问题小结
2018/12/10 Javascript
Angular8 简单表单验证的实现示例
2020/06/03 Javascript
jquery实现简单拖拽效果
2020/07/20 jQuery
Javascript柯里化实现原理及作用解析
2020/10/22 Javascript
[57:53]Secret vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python实现将文件夹内的每张图片批量分割成多张
2019/07/22 Python
Python 函数绘图及函数图像微分与积分
2019/11/20 Python
tensorflow 查看梯度方式
2020/02/04 Python
python GUI库图形界面开发之PyQt5选项卡控件QTabWidget详细使用方法与实例
2020/03/01 Python
python实现udp聊天窗口
2020/03/31 Python
idea2020手动安装python插件的实现方法
2020/07/17 Python
Python解析m3u8拼接下载mp4视频文件的示例代码
2021/03/03 Python
HTML5 input新增type属性color颜色拾取器的实例代码
2018/08/27 HTML / CSS
卫校毕业生自我鉴定
2013/10/31 职场文书
大学生职业生涯规划书范文
2014/01/04 职场文书
大学生创业感言
2014/01/25 职场文书
门前三包责任书
2014/04/15 职场文书
大学新学期计划书
2014/04/28 职场文书
运动会拉拉队口号
2014/06/09 职场文书
2015清明节祭奠英烈寄语大全
2015/03/04 职场文书