webpack独立打包和缓存处理详解


Posted in Javascript onApril 03, 2017

前言

先前写了一篇webpack入门的文章《webpack入门必知必会》,简单介绍了webpack拆分、打包、压缩的使用方法。本文将在上篇文章的基础上进一步讲解在使用webpack构建的项目中存在的优化方案与解决方法。

上篇文章中写了一份webpack最基本的配置文件来打包压缩我们的代码:

var path = require('path');

module.exports = {
 entry: './app/index.js',
 output: {
 filename: 'bundle.js',
 path: path.resolve(__dirname, 'dist')
 }
}

在入口文件index.js中我们引入了jQuery:

// index.js
var $ = require('jquery');
var str = require('./hello.js');

function main() {
 $('body').html(str);
}

main();

这样我们虽然能够实现代码的统一打包,将jQuery、index.js、hello.js统统打包到了bundle.js里,但是会存在一个问题:每次打包都会生成一个体积较大的新bundle.js,浏览器无法缓存像jQuery这样的基本不会改动的框架库代码文件,影响加载速度。

发现问题我们就来解决问题,我们最终希望的是将像jQuery这样的框架库代码与项目自身的代码分开打包,生成一个独立的打包文件,缩减单个文件体积,浏览器也不用每次都进行加载。

步骤

1、独立打包

为了解决上述问题,我们需要修改我们的webpack配置文件:

var webpack = require('webpack');
var path = require('path');

module.exports = {
 entry: {
  main: './app/index.js',
  vendor: ['jquery']
 },
 output: {
  filename: '[name].js',
  path: path.resolve(__dirname, 'dist')
 },
 plugins:[
  new webpack.optimize.CommonsChunkPlugin({
   name: 'vendor'
  }),
 ]
}

上方我们将原本的单入口文件改成了多入口文件,并加入了vendor属性。vendor属性用于配置打包第三方类库,写入数组的类库名将统一打包到一个文件里。

同时我们将输出的filename用[name]变量来自动生成文件名,最后我们添加了一个CommonsChunkPlugin的插件,用于提取vendor。

配置完成后我们运行webpack命令:

Hash: ee1daf95c1986768927a
Version: webpack 2.3.2
Time: 573ms
  Asset  Size Chunks     Chunk Names
  main.js 340 bytes  0 [emitted]   main
vendor.js  274 kB  1 [emitted] [big] vendor
 [0] ./~/jquery/dist/jquery.js 267 kB {1} [built]
 [1] ./app/hello.js 53 bytes {0} [built]
 [2] ./app/index.js 114 bytes {0} [built]
 [3] multi jquery 28 bytes {1} [built]

最终发现我们成功将jQuery打包到了vendor.js中,实现了独立打包,但是问题又来了:每次打包后生成的文件名都是一样的,浏览器可能缓存上一次的结果而无法加载最新数据。

2、添加hash

为了解决上述问题,我们需要为打包后的文件名添加hash值,这样每次修改后打包的文件hash值将改变,修改配置文件如下:

module.exports = {
 ...
  output: {
   filename: '[name].[chunkHash:5].js',
   path: path.resolve(__dirname, 'dist')
  },
 ...
}

上方我们在输出文件名中增加了[chunkHash:5]变量,表示打包后的文件中加入保留5位的hash值。我们再次运行打包命令:

Hash: c7d1295f2f9a27c412d2
Version: webpack 2.3.2
Time: 603ms
   Asset  Size Chunks     Chunk Names
 main.2a7ad.js 337 bytes  0 [emitted]   main
vendor.49eb4.js  274 kB  1 [emitted] [big] vendor
 [0] ./~/jquery/dist/jquery.js 267 kB {1} [built]
 [1] ./app/hello.js 50 bytes {0} [built]
 [2] ./app/index.js 114 bytes {0} [built]
 [3] multi jquery 28 bytes {1} [built]

上方我们发现打包后的文件成功加上了hash值,这样每次修改文件后hash值也会跟着变,就不怕浏览器缓存了,但是当我们尝试去修改一个js文件后再次打包,问题又来了:vendor.js的hash值也变了,我们并没有修改jQuery的源码。

3、修改vendor配置

上述问题产生的原因是因为CommonsChunkPlugin插件是用于提取公共代码的,上方我们只是提取了vendor作为公共代码。为了继续解决上述问题,其实方法很简单,我们需要修改CommonsChunkPlugin的配置,如下:

module.exports = {
 ...
  plugins:[
   new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor', 'manifest']
   }),
  ]
 ...
}

如此我们修改一下hello.js中的代码,发现vendor的hash值并未改变,并且多了一个manifest.js的小文件。manifest.js为webpack的启动文件代码,它会直接影响到hash值,用mainfest单独抽出来了,这样vendor的hash就不会变了。

4、生成index.html

通过以上对webpack配置文件的一系列修改,我们成功实现了webpack的独立打包与缓存处理,但是还差最后一步。

因为我们最终打包后生成的文件名中带有hash值,每次都是会变的,所以我们不能像目前这样在index.html中写死路径。

index.html

...
<body>
 <script src="./dist/main.js"></script>
 <script src="./dist/vendor.js"></script>
 <script src="./dist/manifest.js"></script>
</body>
...

以上写法是不对的,因为缺少了可变的hash值,因此我们希望每次打包后index.html中的路径也会自动加上hash值,解决方法如下:

var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
 ...
  plugins:[
   ...
   new HtmlWebpackPlugin({
    title: 'demo',
    template: 'index.html' // 模板路径
   }),
   ...
  ]
 ...
}

上方我们引入了html-webpack-plugin这一个插件,该插件可以帮助我们根据模板生成html文件。在plugins设置中,title配置了生成html中的title部分,template为模板html的路径地址。

我们需要下载html-webpack-plugin:

npm install html-webpack-plugin --save-dev

安装和配置完毕后,运行打包命令:webpack

Hash: 0c4b91e206579b31544d
Version: webpack 2.3.2
Time: 856ms
   Asset  Size Chunks     Chunk Names
 vendor.e1868.js  268 kB  0 [emitted] [big] vendor
 main.44412.js 337 bytes  1 [emitted]   main
manifest.ed186.js 5.81 kB  2 [emitted]   manifest
  index.html 292 bytes   [emitted]
 [0] ./~/jquery/dist/jquery.js 267 kB {0} [built]
 [1] ./app/hello.js 50 bytes {1} [built]
 [2] ./app/index.js 114 bytes {1} [built]
 [3] multi jquery 28 bytes {0} [built]

我们发现在dist目录下生成了一个index.html文件,打开该文件后代码如下:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>demo</title>
</head>
<body>
<script type="text/javascript" src="manifest.ed186.js"></script>
<script type="text/javascript" src="vendor.e1868.js"></script>
<script type="text/javascript" src="main.44412.js"></script>
</body>
</html>

至此我们实现了每次打包后index.html中的路径也会自动加上hash值的功能,因此dist目录下的index.html即为以后的首页文件,最后我们在浏览器中打开该文件成功显示:

webpack独立打包和缓存处理详解

结语

本文在webpack入门的基础上讲解了webpack独立打包与缓存处理的方式

实例代码已上传我的github,地址为:https://github.com/luozhihao/webpack-course/tree/master/vendor, 供参考。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JScript中的&quot;this&quot;关键字使用方式补充材料
Mar 08 Javascript
基于jquery实现的上传图片及图片大小验证、图片预览效果代码
Apr 12 Javascript
ASP.NET jQuery 实例15 通过控件CustomValidator验证CheckBoxList
Feb 03 Javascript
表单验证的完整应用案例探讨
Mar 29 Javascript
node.js中的buffer.toString方法使用说明
Dec 14 Javascript
基于jQuery实现简单的折叠菜单效果
Nov 23 Javascript
bootstrap布局中input输入框右侧图标点击功能
May 16 Javascript
学习使用ExpressJS 4.0中的新Router的用法
Nov 06 Javascript
Three.js实现简单3D房间布局
Dec 30 Javascript
Node.js 多进程处理CPU密集任务的实现
May 26 Javascript
微信小程序 Storage更新详解
Jul 16 Javascript
Vue 实现一个简单的鼠标拖拽滚动效果插件
Dec 10 Vue.js
使用jQuery卸载全部事件的思路详解
Apr 03 #jQuery
jQuery实现分页功能(含ajax请求、后台数据、附完整demo)
Apr 03 #jQuery
基于JQuery和原生JavaScript实现网页定位导航特效
Apr 03 #jQuery
JS异步文件上传(兼容IE8+)
Apr 02 #Javascript
使用canvas及js简单生成验证码方法
Apr 02 #Javascript
jQuery插件FusionCharts绘制的3D环饼图效果示例【附demo源码】
Apr 02 #jQuery
JS中正则表达式全局匹配模式 /g用法详解
Apr 01 #Javascript
You might like
用Socket发送电子邮件(利用需要验证的SMTP服务器)
2006/10/09 PHP
PHP对MongoDB[NoSQL]数据库的操作
2013/03/01 PHP
探讨:parse url解析URL,返回其组成部分
2013/06/14 PHP
比较strtr, str_replace和preg_replace三个函数的效率
2013/06/26 PHP
php 去除html标记--strip_tags与htmlspecialchars的区别详解
2013/06/26 PHP
PHP实现的简单三角形、矩形周长面积计算器分享
2014/11/18 PHP
Json_encode防止汉字转义成unicode的方法
2016/02/25 PHP
PHP基于GD2函数库实现验证码功能示例
2019/01/27 PHP
按给定几率进行随机抽取的js代码
2010/12/28 Javascript
jQuery动态修改超链接地址的方法
2015/02/13 Javascript
基于JavaScript怎么实现让歌词滚动播放
2015/11/03 Javascript
用canvas 实现个图片三角化(LOW POLY)效果
2016/02/18 Javascript
Javascript使用uploadify来实现多文件上传
2016/11/16 Javascript
bootstrap 模态框(modal)实现水平垂直居中显示
2017/01/23 Javascript
详解vue-cli项目中用json-sever搭建mock服务器
2017/11/02 Javascript
javascript显示动态时间的方法汇总
2018/07/06 Javascript
微信小程序遍历Echarts图表实现多个饼图
2019/04/25 Javascript
一文读懂ES7中的javascript修饰器
2019/05/06 Javascript
Vue+axios+WebApi+NPOI导出Excel文件实例方法
2019/06/05 Javascript
使用 Element UI Table 的 slot-scope方法
2019/10/10 Javascript
用Python输出一个杨辉三角的例子
2014/06/13 Python
Python实现二分查找与bisect模块详解
2017/01/13 Python
Python使用内置json模块解析json格式数据的方法
2017/07/20 Python
恢复百度云盘本地误删的文件脚本(简单方法)
2017/10/21 Python
人工智能最火编程语言 Python大战Java!
2017/11/13 Python
python爬虫简单的添加代理进行访问的实现代码
2019/04/04 Python
一篇文章带你搞定Ubuntu中打开Pycharm总是卡顿崩溃
2020/11/02 Python
美国购买隐形眼镜网站:Lenses For Less
2020/07/05 全球购物
几道PHP面试题
2013/04/14 面试题
建筑公司文秘岗位职责
2013/11/29 职场文书
工厂保洁员岗位职责
2013/12/04 职场文书
社区服务标语
2014/07/01 职场文书
校园新闻稿范文
2015/07/18 职场文书
2015年城乡环境综合治理工作总结
2015/07/24 职场文书
演讲稿:态度决定一切
2019/04/02 职场文书
一文读懂go中semaphore(信号量)源码
2021/04/03 Golang