作者:余韵之
Tree Shaking
1、什么是Tree Shaking
表示 只引入需要的模块里的代码,没有使用的是不会打包
import { add } from './math.js';
add(1, 2);
math.js里有两个方法,如果使用了Tree Shaking 那么只会打包add方法
2、如何配置
webpack.prod.js 生产环境不需要配置这个,即使配置了这个也是无作用的。
optimization: { // 使用tree shaking
usedExports: true
}
package.json
"sideEffects": false, // 表示对所有的模块都要使用 tree shaking
"sideEffects":["@babel/polly-fill","*.css"] //表示排除@babel/polly-fill ,排除所有的css文件 其余import 模块都使用 tree shaking
注意如果是开发环境development tree shaking 会不生效,因为调试的话sourceMap行数会不准,生产环境production就会生效
Production Development
1、如何切换开发环境和生产环境webpack配置
- 创建生产环境文件 ./build/webpack.prod.js
- 创建开发环境文件 ./build/webpack.dev.js
- 创建公共的代码文件 ./build/webpack.common.js
使用插件 webpack-merge 把配置文件合并
2、配置打包命令
package.json
"scripts": {
"dev": "webpack-dev-server --config ./build/webpack.dev.js", // 启动热更新,选择dev配置文件
"build": "webpack --config ./build/webpack.prod.js" // 直接打包,走prod配置文件
}
Code Splitting
我们为什么要做代码分割呢?举个例子。
假设我们引入了一个lodash第三方库,它的大小是1MB,我们的业务代码也有1MB。此时不做任何处理最后打包生成一个main.js大小为2MB。用户打开浏览器需要请求一个2MB的main.js文件。
import _ from "lodash"; // 假设lodash有1MB
// 假设业务代码有1MB
console.log(_.join(['a', 'a', 'c'],"---"))
console.log(_.join(['a', 'b', 'c'],"---"))
此时我们修改业务代码
import _ from "lodash"; // 假设lodash有1MB
// 假设业务代码有1MB
console.log(_.join(['a', 'xxxxx', 'c'],"---"))
console.log(_.join(['a', 'b', 'c'],"---"))
重新打包,生成 main.js 2MB。用户需要重新拉取2MB的代码文件。这会使得加载时间很慢,性能不够好。
所以有什么好的方式来解决这个问题呢?
第一种方式:同步方式
import _ from "lodash" // 假设lodash有1MB
window._ = _
// 假设业务代码有1MB
console.log(_.join(['a', 'd', 'c'],"---"))
console.log(_.join(['a', 'b', 'c'],"---"))
webpack.config.js
entry: {
lodash: './src/lodash.js',
main: './src/index.js'
}
- 首次访问页面,加载 main.js: 被拆成vendor~lodash.js 1MB 和 业务代码main.js 1MB
- 此时修改了业务代码,用户是不需要重新加载vendor~lodash代码的。只需要重新加载main.js
优点:可以有效提提高代码运行的速度、用户体验提高、性能提高
缺点:需要手动拆分页面的代码,不够智能
第二种方式:同步方式
webpack.config.js
optimization:{
splitChunks:{
chunks:'all'
}
}
import _ from "lodash"; // 假设有1MB
console.log(_.join(['a', 'd', 'c'],"---"))
// 此处省略10万行业务逻辑
console.log(_.join(['a', 'b', 'c'],"---"))
优点:相比第二种方式,可以自动拆分,打包引入 main.js 和 vendors~main.js
第三种方式:异步方式
安装插件
yarn add -D babel-plugin-dynamic-import-webpack
.babelrc
"plugins": ["babel-plugin-dynamic-import-webpack"]
异步代码如下
function getComponent(){
return import('lodash').then(({default:_})=>{
let element = document.createElement('span')
element.innerHTML = _.join(['x','y'],'-');
return element;
})
}
getComponent().then(ele=>{
document.body.appendChild(ele)
})
注意:异步代码import引入的模块,无需配置额外的webpack.config.js,会自动引入
SplitChunksPlugin 配置参数详情
1、webpackChunkName
修改第三方打包的文件的名字
安装官方的依赖
npm install --save-dev @babel/plugin-syntax-dynamic-import
.babelrc
"plugins": ["@babel/plugin-syntax-dynamic-import"]
项目代码里添加名字 /_ webpackChunkName:"lodash" _/
function getComponent(){
return import(/* webpackChunkName:"lodash" */'lodash').then(({default:_})=>{
let element = document.createElement('span')
element.innerHTML = _.join(['x','y'],'-');
return element;
})
}
getComponent().then(ele=>{
document.body.appendChild(ele)
})
注意:生成的代码文件为 ./dist/vendors~lodash.js
如果生成的代码文件不想加入 vendors~ ,而是直接lodash.js
那么配置webpack.config.js
optimization:{
splitChunks:{
chunks:'all',
cacheGroups:{ // 表示打包的文件是否要带vendors,无论同步或者异步
vendors:false,
default:false
}
}
}
2、详细的splitChunks的参数功能
optimization: {
splitChunks: {
chunks: 'all', // async 表示只对异步代码分割,initial 表示只对同步代码分割,all的话是所有同时会走到cacheGroups.vendors
minSize: 30000, // 表示最小模块大于30000个字节才会做代码分割
// maxSize: 50000, // 如果拆分的代码大小超过50000,会进行二次拆分,一般配置的比较少
minChunks: 1,//引入几次才分割打包,如果只引入1次就分割,如果是2表示必须大于等于2次才做代码分割
maxAsyncRequests: 5,// 表示不能超过5个模块分割,超过后面的模块就不分割了
maxInitialRequests: 3,// 表示整个网站首页或入口文件 如果做代码分割不超过3个
automaticNameDelimiter: '~', //组和文件名链接符号 vendors~main.js
name: true,// 表示要更新名字,一般是不需要改变的
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 如果在node_modules里,那么会打包到vendors.js
priority: -10, // 比如jquery 符合vendors 也符合default,值越大,说明优先级更大
filename:'vendors.js' // 表示所有的第三方打包到一个叫vendors.js文件
},
default: { // 如果是引入自己在项目里写的模块引入走这里,非node_modules
// minChunks: 2,
priority: -20,// 值越大,说明优先级更大
reuseExistingChunk: true, // 如果代码已经打包过,重复引用时就不会再分割打包,而是复用之前的。
filename: 'common.js'
}
}
}
},
这里要注意
- 如果是引入同步代码不会立刻分割,而是会走cacheGroups,根据实际情况来分割
对 Electron 感兴趣?请关注我们的开源项目 Electron Playground,带你极速上手 Electron。我们每周五会精选一些有意思的文章和消息和大家分享,来掘金关注我们的 晓前端周刊。
我们是好未来 · 晓黑板前端技术团队。
我们会经常与大家分享最新最酷的行业技术知识。
欢迎来 知乎、掘金、Segmentfault、CSDN、简书、开源中国、博客园 关注我们。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。