作者:余韵之
LazyLoading 懒加载 Chunk是什么?
咱们能够应用懒加载的形式引入模块,比如说当触发了某个条件,在通过import的形式引入模块。这样能够使得我的项目的性能会更加的好。
举个例子:
当咱们点击页面的时候,才会去引入lodash模块,这里 import()返回的是promise
async function getComponent() { const {default: _} = await import(/* webpackChunkName:"lodash" */'lodash') const element = document.createElement('div') element.innerHTML = _.join(['y', 'kk'], '-'); return element;}document.addEventListener('click', () => { getComponent().then(element => { document.body.appendChild(element) })})
同样的路由懒加载的意思,示意当咱们监听到路由变动了,才会去引入对应的页面模块。
因而能够晓得,Chunk是什么?打包生成几个JS文件,就是几个Chunk
Shimming
Shimming:在打包过程中,有时候须要对代码兼容。这种兼容不局限于浏览器高下版本。
举个例子
每个文件都是一个模块,每个模块都应该引入本人的依赖能力应用该依赖。
import $ from 'jquery'export function setBackground(){ $('body').css('background','red')}
然而这样的话,每个文件都要写一遍
import $ from 'jquery'
因而能够应用垫片的形式来主动配置
plugins:[ new webpack.ProvidePlugin({ $:'jquery', _join:['lodash','join'] })]
当咱们配置了上述内容,那么意味着当运行代码的时候看到
- $这个符号就会主动去node_modules里引入jquery。他的原理就是主动帮咱们增加了import的步骤。
- 看到_join就会主动找到 lodash里join的办法
于是咱们能够间接这些一个文件模块应用
export function setBackground(){ $('body').css('background', _join(['green'], ''))}
webpack与浏览器缓存(caching)
当咱们打包生成了
index.htmlmain.jsvendors.js
客户端从服务端拿到了两个js文件,会保留在浏览器里。客户端刷新后浏览器会先从缓存里获取。
当开发批改了代码,从新打包,生成了上述三个同名文件时,用户刷新后依然是原来的代码并没有更新。
这样如何解决呢?
1、打包文件增加contentHash
开发环境因为是热更新的,所以本地调试能够不增加,
生产环境在output里改为
output: { filename: '[name].[contentHash].js', chunkFilename: '[name].[contentHash].js'}
contentHash 示意只有不扭转源代码的内容,那么contentHash所产生的hash值是不会变的。如果代码是宰割成不同的chunk,某个chunk没有批改,该chunk的文件名contentHash也不会批改
同时做了代码宰割的参数最好也配置一下
optimization.splitChunks.cacheGroup.vendors.filename = 'vendors.[contentHash].js'
2、对老版本的兼容
可能老的版本即便不改内容,contentHash值也会扭转,这个时候能够配置
optimization: { runtimeChunk:{ name:'runtime' }}
新版本增加这个runtimeChunk也是没有问题的,此时打包会多出一个runtime.xxxxxxx.js文件
这是怎么回事呢?
因为在旧的webpack版本里main.js(业务逻辑) 和 vendors.js(第三方库) 之间是存在关联的,这部分的解决代码放在mainfest,尽管没有扭转代码,但在旧版本的webpack里 mainfest 包和包之间的关系每次打包可能会变动,当咱们配置了runtimeChunk的时候就把mainfest这块关系相干的代码抽离进去了放在runtime.js里
因而这样就解决了这个兼容老版本的问题。
对CSS代码宰割
失常打包的话,会把CSS文件一起打包的main.js文件,如何进行CSS代码宰割呢?
1、应用一个插件:mini-css-extract-plugin
但这个插件有一个毛病,目前不反对热更新,所以适宜线上环境做打包
配置形式装置依赖
yarn add mini-css-extract-plugin
在生产环境的webpack.config.js配置
const MiniCssExtractPlugin = require('mini-css-extract-plugin') module:{ rules:[ { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 2 } }, 'sass-loader', 'postcss-loader' ] }, { test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader' ] } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "[name].css", //index.html间接引入的文件 chunkFilename: "id.css" // 间接援用的文件 }) ]
留神 如果此时应用了tree shaking 看看 package.json 里 sideEffects 配置。如果为false那么css代码是没有宰割的。须要把css tree shaking排除在外。批改如下:
"sideEffects": [ "*.css" ],
2、接下来对合并的CSS代码压缩
装置依赖
yarn add optimize-css-assets-webpack-plugin -D
生产环境
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')optimization:{ minimizer:[new OptimizeCSSAssetsPlugin({})]}
打包剖析
生成webpack打包剖析json
webpack --profile --json > stats.json --config ./build/webpack.dev.js
而后把生成的stats.json放入相干的剖析网站就能够看到可视化的数据。当然也能够配置analyzer
装置依赖
npm install webpack-bundle-analyzer --save-dev
在webpack.config.js配置
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { ... configureWebpack: { plugins: [ new BundleAnalyzerPlugin({ // 能够是`server`,`static`或`disabled`。 // 在`server`模式下,分析器将启动HTTP服务器来显示软件包报告。 // 在“动态”模式下,会生成带有报告的单个HTML文件。 // 在`disabled`模式下,你能够应用这个插件来将`generateStatsFile`设置为`true`来生成Webpack Stats JSON文件。 analyzerMode: 'server', // 将在“服务器”模式下应用的主机启动HTTP服务器。 analyzerHost: '127.0.0.1', // 将在“服务器”模式下应用的端口启动HTTP服务器。 analyzerPort: 8888, // 门路捆绑,将在`static`模式下生成的报告文件。 // 绝对于捆绑输入目录。 reportFilename: 'report.html', // 模块大小默认显示在报告中。 // 应该是`stat`,`parsed`或者`gzip`中的一个。 // 无关更多信息,请参见“定义”一节。 defaultSizes: 'parsed', // 在默认浏览器中主动关上报告 openAnalyzer: true, // 如果为true,则Webpack Stats JSON文件将在bundle输入目录中生成 generateStatsFile: false, // 如果`generateStatsFile`为`true`,将会生成Webpack Stats JSON文件的名字。 // 绝对于捆绑输入目录。 statsFilename: 'stats.json', // stats.toJson()办法的选项。 // 例如,您能够应用`source:false`选项排除统计文件中模块的起源。 // 在这里查看更多选项:https: //github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21 statsOptions: null, logLevel: 'info' // 日志级别。能够是'信息','正告','谬误'或'缄默'。 }) ] }, ...};
应用形式 在打包或者启动的时候加 --report
npm run serve --reportnpm run build --report
prefetching && preloading
关注代码使用率:一开始不会执行的代码不要加载进去,而是当交互了再去加载。
webpack心愿尽可能应用异步加载模快在第一次加载进步性能,而同步是第二次加载了减少缓存对性能的晋升是无限的。
document.addEventListener('click', () => { import('./click.js').then(({default:func}) => { func() })})
留神 但这样会存在一个问题,就是当用户点击交互了才下载代码可能会有一点小小的提早,如何解决这个问题?
解决方案就是 : prefetching/preloading
- prefetching 会等到外围先展现的代码加载结束了,等宽带闲暇再持续下载。
只须要在代码增加如下内容即可:
document.addEventListener('click', () => { import(/* webpackPrefetch:true */'./click.js').then(({default:func}) => { func() })})
当用户点击了,依然会下载click.js文件,然而应用的工夫会十分短,因为之前曾经下载过了有了缓存了。
- preloading 会和主的代码同时下载。
document.addEventListener('click', () => { import(/* webpackPreload:true */'./click.js').then(({default:func}) => { func() })})
因而性能优化最好去思考代码的使用率更高。
对 Electron 感兴趣?请关注咱们的开源我的项目 Electron Playground,带你极速上手 Electron。咱们每周五会精选一些有意思的文章和音讯和大家分享,来掘金关注咱们的 晓前端周刊。
咱们是好将来 · 晓黑板前端技术团队。
咱们会常常与大家分享最新最酷的行业技术常识。
欢送来 知乎、掘金、Segmentfault、CSDN、简书、开源中国、博客园 关注咱们。