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 相关文章推荐
jQuery编写widget的一些技巧分享
Oct 28 Javascript
JavaScript实现页面滚动图片加载(仿lazyload效果)
Jul 22 Javascript
面向对象的Javascript之二(接口实现介绍)
Jan 27 Javascript
javascript实现树形菜单的方法
Jul 17 Javascript
jQuery实现信息提示框(带有圆角框与动画)效果
Aug 07 Javascript
第三章之Bootstrap 表格与按钮功能
Apr 25 Javascript
浅谈jQuery中的$.extend方法来扩展JSON对象
Feb 12 Javascript
js通过Date对象实现倒计时动画效果
Oct 27 Javascript
对Vue table 动态表格td可编辑的方法详解
Aug 28 Javascript
详解用场景去理解函数柯里化(入门篇)
Apr 11 Javascript
laravel-admin 与 vue 结合使用实例代码详解
Jun 04 Javascript
JS正则表达式验证端口范围(0-65535)
Jan 06 Javascript
使用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
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
Yii2前后台分离及migrate使用(七)
2016/05/04 PHP
Laravel 5.3 学习笔记之 配置
2016/08/28 PHP
PHP二分查找算法示例【递归与非递归方法】
2016/09/29 PHP
PDO::errorCode讲解
2019/01/28 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
2020/02/28 PHP
JavaScript的Cookies
2008/01/16 Javascript
JavaScript高级程序设计 读书笔记之九 本地对象Array
2012/02/27 Javascript
JavaScript验证电子邮箱的函数
2014/08/22 Javascript
jQuery插件Elastislide实现响应式的焦点图无缝滚动切换特效
2015/04/12 Javascript
jquery解析XML及获取XML节点名称的实现代码
2016/05/18 Javascript
JS数组操作中的经典算法实例讲解
2017/07/26 Javascript
jQuery读取本地的json文件(实例讲解)
2017/10/31 jQuery
React 组件转 Vue 组件的命令写法
2018/02/28 Javascript
微信小程序云开发之使用云函数
2019/05/17 Javascript
layui文件上传控件带更改后数据传值的方法
2019/09/23 Javascript
卸载vue2.0并升级vue_cli3.0的实例讲解
2020/02/16 Javascript
vue-router重写push方法,解决相同路径跳转报错问题
2020/08/07 Javascript
详细介绍Ruby中的正则表达式
2015/04/10 Python
Tensorflow卷积神经网络实例进阶
2018/05/24 Python
对python读取CT医学图像的实例详解
2019/01/24 Python
详解Python中pandas的安装操作说明(傻瓜版)
2019/04/08 Python
Python中将两个或多个list合成一个list的方法小结
2019/05/12 Python
python调用动态链接库的基本过程详解
2019/06/19 Python
罗德与泰勒百货官网:Lord & Taylor
2016/08/12 全球购物
澳大利亚头发和美容产品购物网站:OZ Hair & Beauty
2020/03/27 全球购物
怎样自定义一个异常类
2016/09/27 面试题
幼儿园教育教学反思
2014/01/31 职场文书
总账会计岗位职责
2014/03/13 职场文书
2015年党员公开承诺事项
2015/04/27 职场文书
通讯稿范文
2015/07/22 职场文书
新党员入党决心书
2015/09/22 职场文书
Python中的套接字编程是什么?
2021/06/21 Python
python分分钟绘制精美地图海报
2022/02/15 Python
「回转企鹅罐」10周年纪念展「輪るピングドラム展」海报公开
2022/03/22 日漫