工程化层面优化
常见问题:如何让 webpack 打包更快
并发:使用多进程打包
缓存:打包时利用缓存
打包量要小:缩小文件搜索范围,减小不必要的编译工作
webpack优化
单独打包 runtime
splitChunks 将 react、vue 依赖单独打包
modulelds
多页面
common插件
code split 代码分割
- runtime
- node modules -> verdors 全局
- common 公共模块
- self(main/admin)自身
为什么 runtime 单独打包
额外的代码就是runtime
因为如果不单独打包,那么我们在修改webpack 配置的时候会导致用户的缓存失效,必须下载最新的main.js
如果单独打包,只要我不修改 index.js 里的内容,main.js 就不需要重新请求,节省用户带宽,用户访问速度就会加快
splitChunks 将 react、vue 依赖单独打包
vendors 表示 第三方的意思
webpack 多页面
common chunks 共有文件
打包优化
- webpack
- loader
- dll
- happypack
- 代码压缩
- tree shaking
- scope hositing
- code splitting
- 图片 base64,cdn
如何做页面的性能优化
1.减少体积(打包优化、babel 优化)
webpack 打包,使用 webpack content-hash
文件指纹是打包后输出的文件名的后缀
Hash
:和整个项目的构建相关,只要项目文件有修改,整个项目构建的 hash 值就会更改Chunkhash
:和 webpack 打包的 chunk 有关,不同的入口会有不同的 chunkhashContenthash
:根据文件内容来定义 hash,文件内容不变,则 contenthash 不变2.延迟加载(资源的异步加载)
资源合并
CSS 雪碧图 -> Icon Font -> SVG Symbols
webpack
资源内敛
小图片 -> data url
小 CSS 文件 -> <style>代码</style>
小 JS 文件 -><script>代码</script>
webpack 配置即刻
资源压缩(gzip)
nginx 、 Apache、Node.js
资源精简
HTML -> 删空格、删闭合
CSS -> 删未用
JS -> 改名、tree shaking
SVG -> 删无用标签、属性
图片 -> 减少体积(有损/无损)
减少 Cookie 体积
4kb 新域名
CDN 的原理和实施
CDN 内容分发网络
- 分离 Manifest
- Code Splitting(代码分割)
- Bundle Splitting(打包分割)
- Tree Shaking(删除死代码)
- 开启 gzip
分离 Manifest
module.exports = (config, resolve) => {
return() => {
config
.optimization
.runtimeChunk({
name: "manifest"
})
}
}
Code Splitting
- 使用动态 import 或者 require.ensure 语法
- 使用
babel-plugin-import
插件按需引入一些组件库
Bundle Splitting
将公共的包提取到 vendors
里面,比如你
Tree Shaking
config.optimization.usedExports(true);
开发环境:
值得去配置的:
优化开发体验
自动刷新 -> 模块热更新
实时预览反应更快,等待时间更短
不刷新浏览器能保留当前网页的运行状态
需要在入口文件进行配置:
javascript// 入口文件 if (module.hot) { module.hot.accept(['./App'], () => { render(<App />, document.getElementById('app')); }); }
PS: 模块热更新机制
1. 当子模块发生更新时,更新事件会一层层往上传递,也就是从 App.js 文件传递到 main.js 文件,直到有某层的文件接受了当前变化的模块,也就是 main.js 文件中定义的 module.hot.appept(['./App', callback]),这时就会调用 callback 函数去执行自定义逻辑 2. 如果事件一直往上抛到最外层都没有文件接受它,就会直接刷新网页
webpack 方面也有相应的开启热跟新的处理
javascriptconst HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin'); module.exports = webpackMerge(baseConfig, { plugins: [new HotModuleReplacementPlugin()], devServer: { // 每次构建时候自动打开浏览器并访问网址 open: true, // 开启热更新 hot: true, // 设置静态资源地址如:/public,从这获取你想要的一些外链资源,图片。 contentBase: DIST_PATH, // 设置端口号 port: 9000, // 将热更新代码注入到模块中 inline: true, // 如果你希望服务器外部可访问 host: '0.0.0.0', // 设置 proxy 代理 proxy: { context: ['/api'], target: '//www.proxy.com', pathRewrite: { '^/api': '' }, }, // 设置 https https: true, }, });
- 配置 sourcemap,方便调试
javascriptmodule.exports = { devtool: 'source-map', };
PS: devtool 有各种选择,不同的选项构建速度不同
尽可能减少构建时间
减少模块朝招范围,缩小 Babel 的编译范围,并使用 webpack cache 缓存模块
javascriptmodule.exports = { // 减小模块的查找范围 resolve: { modules: [path.resolve(__dirname, 'node_modules')], }, module: { rules: [ { test: /\.js?$/, use: [ { loader: 'babel-loader', query: { // 将 babel 编译过的模块缓存在 webpack_cache 目录下,下次优先复用 cacheDirectory: './webpack_cache/', }, }, ], // 减少 babel 编译范围,忘记设置会让 webpack 编译慢上好几倍 include: path.resolve(__dirname, 'src'), }, ], }, };
使用 DllPlugin 预先打包好第三方库
1. ```javascript // dll.config.js const webpack = require('webpack'); const path = require('path'); const DllPlugin = require('webpack/lib/DllPlugin') const vendors = [ 'react', 'react-dom', 'react-router', 'redux', 'react-redux', 'jquery', 'antd', 'lodash', ] module.exports = { entry: { 'dll': vendors, }, output: { filename: '[name].js', path: path.resolve(__dirname, 'public'), library: '__[name]__lib', }, plugins: [ new DllPlugin({ name: '__[name]__lib', path: path.join(__dirname, 'build', '[name].manifest.json'), }), ] }
具体配置 3. 使用 Happypack 多线程加快构建
webpack 构建慢是因为要解析和处理大量的文件,它需要一件件去做。 Happypack 的核心原理就是把这部分任务分解到多个进程去并行处理,从而减少总的构建时间
需要配置哪些 loader 使用 Happypack 就要改写那些配置,比如你想要修改 babel 为多核编译:
javascriptmodule.exports = { module: { rules: [ { test: /\.js?$/, use: ['happypack/loader?id=babel'], include: path.resolve(__dirname, 'src'), }, ], }, plugins: [ new HappyPack({ id: 'babel', loaders: [ { loader: 'babel-loader', query: { cacheDirectory: './webpack_cache/', }, }, ], }), ], };
不使用 webpack css 模块方案
css in js 会增加机器的编译时间,所以不使用
不值得去配置的
1. 代码丑化 2. 模块拆包,持久化缓存 3. 减少打包文件大小
生存环境:
- 值得去配置的
- 模块拆包
- 尽可能减少打包文件大小
- 代码丑化压缩
- 尽可能减少构建时间
- 不值得去配置 1. 优化开发体验 2. 开发环境才需要的配置
预取/预加载模块(prefetch/preload module)
作用:先加载页面需要的,而异步操作等浏览器进程闲置的时候再会去加载
Import(/* webpackPrefetch: true */ ‘LoginModal’)