webpack 代码分离优化快速指北


Posted in Javascript onMay 18, 2019

分离代码文件

在此之前,首先要知道经常配置的 output 中有关 filename 和 chunkFilename 的区别;简单来说在 entry 定义的入口文件走的就是 filename 配置项,在入口文件内部引入的通常情况下是 chunk,走 chunkFilename 的配置

所以很多时候分离代码文件就是将不同的 chunk 分离开来,生产环境中有利于浏览器缓存,加快二次访问的速度

代码分离的时候,optimization 中配置的 splitChunks 默认就是 async,默认对异步代码进行分离;所以通常情况下能用异步的用异步 import;配合 prefetching 和 preloading 能够产生很好的效果

filename 和 chunkFilename 的区别

output: {
 filename: '[name].js',
 chunkFilename: '[name].chunk.js'
}

举个例子

如果入口文件是 main.js

那么打包后生成的文件是 main.js

如果 main.js 中引入了其他模块,比如引入了 lodash 那么可能会生成一个名为 lodash.chunk.js 文件

基本概念了解了,接下来开始对 js 和 css 文件进行分离的操作:

js 代码分离

js 代码的分离操作,首先要考虑的就是对异步代码的分离。这里使用 dynamicImport

dynamicImport

可以使用 magic comment 来修改动态 import 导出的 chunkname,语法规则如下:

import('/* webpackChunkName: "lodash" */' 'lodash').then(//...)

如果需要使用这种注释的写法,应该安装模块 @babel/plugin-syntax-dynamic-import,并在 babelrc 中引入这个插件,使用方法很简单这里不多说了

splitChunks

splitChunk 的相关配置参数

建议将公共使用的第三方类库显式地配置为公共的部分,而不是 webpack 自己去判断处理

  • chunks: 表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all;
  • minSize: 表示在压缩前的最小模块大小,默认为0;
  • minChunks: 表示被引用次数,默认为1;
  • maxAsyncRequests: 最大的按需(异步)加载次数,默认为1;
  • maxInitialRequests: 最大的初始化加载次数,默认为1;
  • name: 拆分出来块的名字(Chunk Names),默认由块名和hash值自动生成;
  • cacheGroups: 缓存组。

缓存组中还有其他几个参数:

  • priority: 表示缓存的优先级;
  • test: 缓存组的规则,表示符合条件的的放入当前缓存组,值可以是function、boolean、string、RegExp,默认为空;
  • reuseExistingChunk: 表示可以使用已经存在的块,即如果满足条件的块已经存在就使用已有的,不再创建一个新的块。
module.exports = {
 entry: {
 vendor: ["react", "lodash", "angular", ...], // 指定公共使用的第三方类库
 },
 optimization: {
 splitChunks: {
  cacheGroups: {
  vendor: {
   chunks: "initial",
   test: "vendor",
   name: "vendor", // 使用 vendor 入口作为公共部分
   enforce: true,
  },
  },
 },
 },
 // ... 其他配置
}

或者:

optimization: {
 splitChunks: {
  name: true, // 自动处理文件名
  chunks: 'all',
  minChunks: 1, // 至少 import 1 次的即需要打包
  automaticNameDelimiter: '-',
  cacheGroups: {
  vendors: {
   test: /axios|lodash/, // 将这两个第三方模块单独提取打包
   chunks: 'initial',
  }
  }
 }
 },

optimization-splitchunks

chunks 的配置

注意 ⚠️

如果是动态 import,import('/* webpackChunkName: "lodash" */' 'lodash').then() 那么 splitChunks 设置为 async,代码分离将会起作用。

如果是同步加载 import, import _ from 'lodash' 那么 splitChunks 设置为 async 将不起作用,如果设置为 all,那么还需要配置 cacheGroups

cacheGroups 的配置

vendors 缓存组的配置可以检测第三方模块是否在 node_modules 中,如果存在则该 splitChunks 生效,将会分离到 vendors~... 这样的文件中

配置 filename 则会打包成 [filename] 命名的文件中

runtimeChunk 的作用

这个 runtimeChunk 实际上就是链接业务逻辑和第三方类库之间的关系的 manifest。需要将其提取出来,否则使用 contenthash 的情况下有可能会导致模块内容没发生改变的情况下出现 contenthash 多次打包出现不一致的情况(实际上就是存在在业务逻辑和模块中的 manifest 发生了改变)

// v4版本的 webpack 不用配置,但最好也提取出来
optimization: {
 runtimeChunk: {
 name: 'runtime'
 }
}

reuseExistingChunk:

如果 a 模块使用了 b,b 模块又使用了 a;a 被打包到 common.js 中,打包 b 时将直接使用已经打包好的 common.js 中的 a;这就是 reuseExistingChunk 的作用:

default: {
 reuseExistingChunk: true,
 filename: 'common.js'
}

他的含义就是只要其中一个模块使用了 import $ from 'jquery',其他文件中就可直接使用 $ 变量,webpack 会自动在打包过程中 import 这个模块

css 代码分离

css 部分分离代码文件 直接使用 extract-text-webpack-plugin 即可

一个 JS 文件,加载页面时虽然只需要加载一个 JS 文件,但代码一旦改变,用户访问新的页面时就需要重新加载一个新的 JS 文件。有些情况下,我们只是单独修改了样式,这样也要重新加载整个应用的 JS 文件,相当不划算。
多个组件共用一部分样式,如果分离开来,第二个页面就有了 CSS 文件的缓存,访问速度自然会加快

MiniCssExtractPlugin

新版本的 webpack 使用这个插件

注意,在引入样式文件 import './style.css' 的时候,如果配置了 treeshaking,应当在 package.json 中配置:

"sideEffects": [
 "*.css"
]

⚠️ 注意,另外在 vue 中如果有 style 标签,还需要在 sideEffects 中加入 *.vue 的配置项。不必担心 vue 中的 script 部分会被 treeShaking 掉。

插件的相关配置

filename 指的是如果该 css 文件会直接被插入 html 中那么走的就是 filename 的配置

plugins: [
 new MiniCssExtractPlugin({
 filename: '[name].css',
 chunkFilename: '[name].chunk.css'
 })
]

既然有分离那就有合并,这里顺便提及一下 css 代码合并

如果有多个入口,想把多个入口引入的样式文件全部打包到一个地方,那么可以使用 optimization 配置项的 splitChunks,所以这个配置项不仅仅只作用于 js,css 也是可以的:

optimization: {
 splitChuns: {
 cacheGroups: {
  styles: {
  name: 'style', // 将多个入口文件中的样式文件全部合并打包
  test: /\.css$/,
  chunks: 'all',
  enforce: true
  }
 }
 }
}

css 代码根据入口分别打包

还可以根据入口的不同,来分别打包 css 文件,文档已经讲的很详细了,这部分比较简单可以直接戳文档 https://webpack.js.org/plugins/mini-css-extract-plugin

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

Javascript 相关文章推荐
ymPrompt的doHandler方法来实现获取子窗口返回值的方法
Jun 25 Javascript
拉动滚动条加载数据的jquery代码
May 03 Javascript
删除select中所有option选项jquery代码
Aug 12 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
Jan 13 Javascript
jquery解析xml字符串简单示例
Apr 11 Javascript
详解JavaScript for循环中发送AJAX请求问题
Jun 23 Javascript
JavaScript 继承详解(六)
Oct 11 Javascript
ECMAScript6变量的解构赋值实例详解
Sep 19 Javascript
解决layui上传文件提示上传异常,实际文件已经上传成功的问题
Aug 19 Javascript
Vue实现星级评价效果实例详解
Dec 30 Javascript
小程序选项卡以及swiper套用(跨页面)
Jun 19 Javascript
Vue如何清空对象
Mar 03 Vue.js
如何实现小程序tab栏下划线动画效果
May 18 #Javascript
微信小程序结合Storage实现搜索历史效果
May 18 #Javascript
Fetch超时设置与终止请求详解
May 18 #Javascript
微信小程序实现搜索历史功能
Mar 26 #Javascript
微信小程序云开发修改云数据库中的数据方法
May 18 #Javascript
小程序云开发教程如何使用云函数实现点赞功能
May 18 #Javascript
微信小程序实现元素渐入渐出动画效果封装方法
May 18 #Javascript
You might like
IIS6.0+PHP5.x+MySQL5.x+Zend3.0x+GD+phpMyAdmin2.8x通用安装实例(已经完成)
2006/12/06 PHP
解析用PHP读写音频文件信息的详解(支持WMA和MP3)
2013/05/10 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
2014/06/23 PHP
详解 PHP加密解密字符串函数附源码下载
2015/12/18 PHP
PHP读取Excel类文件
2017/05/15 PHP
php微信公众号开发之二级菜单
2018/10/20 PHP
基于jQuery的可以控制左右滚动及自动滚动效果的代码
2010/07/25 Javascript
关于JavaScript中var声明变量作用域的推断
2010/12/16 Javascript
分享一个用Mootools写的鼠标滑过进度条改变进度值的实现代码
2011/12/12 Javascript
js setTimeout 参数传递使用介绍
2013/08/13 Javascript
jQuery实现跨域iframe接口方法调用
2015/03/14 Javascript
使用jQuery在移动页面上添加按钮和给按钮添加图标
2015/12/04 Javascript
ionic在开发ios系统微信时键盘挡住输入框的解决方法(键盘弹出问题)
2016/09/06 Javascript
js原生日历的实例(推荐)
2017/10/31 Javascript
vue3.0 CLI - 2.6 - 组件的复用入门教程
2018/09/14 Javascript
详解关于element级联选择器数据回显问题
2019/02/20 Javascript
通过JQuery,JQueryUI和Jsplumb实现拖拽模块
2019/06/18 jQuery
layer 关闭指定弹出层的例子
2019/09/25 Javascript
微信小程序 点击切换样式scroll-view实现代码实例
2019/10/11 Javascript
[01:25]2014DOTA2国际邀请赛 zhou分析LGD比赛情况
2014/07/14 DOTA
浅谈python jieba分词模块的基本用法
2017/11/09 Python
python实现决策树分类(2)
2018/08/30 Python
使用python判断jpeg图片的完整性实例
2019/06/10 Python
python如何支持并发方法详解
2020/07/25 Python
Python jieba结巴分词原理及用法解析
2020/11/05 Python
理肤泉加拿大官网:La Roche-Posay加拿大
2018/07/06 全球购物
澳大利亚家用电器在线商店:Billy Guyatts
2020/05/05 全球购物
摄影专业毕业生求职信
2014/03/13 职场文书
捐赠仪式主持词
2014/03/19 职场文书
我爱读书演讲稿
2014/05/07 职场文书
应届生求职自荐信
2014/07/04 职场文书
2015年感恩节演讲稿(优选篇)
2015/03/20 职场文书
送给客户微信问候语!
2019/07/04 职场文书
python生成可执行exe控制Microsip自动填写号码并拨打功能
2021/06/21 Python
SpringBoot快速入门详解
2021/07/21 Java/Android
NASA 机智号火星直升机拍到了毅力号设备碎片
2022/04/29 数码科技