前端性能优化
构建优化
webpack优化
(1) build Cache
- 开启缓存选项 exg:bable-loader?cacheDirectory
(2)减少代码体积
- code splitting想把不变的代码单独抽离出来,方便浏览器缓存,提升加载速度
-
使用optimization,减少总体积
optimization: { splitChunks: { //用于拆分代码,找到 chunk 中共同依赖的模块,取出来生成单独的 chunk([SplitChunksPlugin]) chunks: 'all' }, runtimeChunk: true, // 将 webpack 生成的 runtime 作为独立 chunk ,runtime 包含在模块交互时,模块所需的加载和解析逻辑(manifest),所以你每次改动都会影响它,如果不把它提取出来的话,等于app.js每次都会改变,缓存就失效了 minimize:true // 用于控制压缩的开关,开发环境默认关闭,生产环境默认开启[uglifyjs-webpack-plugin] optimization.minimizer:用于配置压缩项及其配置项 }
- css文件压缩,用到了
mini-css-extract-plugin
- 部分依赖转移到CDN上,避免每次编译过程都有webpack处理
-
删除未使用的依赖
- 通过 package.json 的 "sideEffects" 属性作为标记,向 compiler 提供提示,表明项目中的哪些文件是 "pure(纯的 ES2015 模块)",无副作用的,由此可以安全地删除文件中未使用的部分
(3)减少目录检索范围
- 通过exclude/include,减少loader遍历范围,加快编译速度
(4)减少检索路径
- resolve.alias 配置解析别名
(5)使用DllPlugin/DllReferencePlugin进行预先构建用某种方法实现了拆分 bundles,同时还大大提升了构建的速度。
-
将改变频率较小的第三库和依赖单独打包构建(npm包)
(i)新建一个单独webpack配置文件 (webpack.dll.config.js)
(ii)在这个配置文件中,使用 webpack DllPlugin 生成 manifest.json 文件和 Dll 模块文件。也可以引入诸如 uglifyPlugin 对第三方依赖进行压缩等处理
(iii) 在正常的 webpack 配置文件中,使用 webpack DllReferencePlugin 解析上一步生成的 manifest.jsonnew webpack.DllReferencePlugin({ context: path.join(__dirname), manifest: require('./manifest.json')})
(6)happypack
-
happypack 的原理是让loader可以多进程去处理文件 将需要通过loader处理的文件先交给happypack去处理,happypack 在收集到这些文件的处理权限后,统一分配CPU资源
var HappyPack = require('happypack'), os = require('os'), happyThreadPool = HappyPack.ThreadPool({ size:os.cpus().length }); modules: { loaders: [ { test: /\.js|jsx$/, loader: 'HappyPack/loader?id=jsHappy', exclude: /node_modules/ } ] } plugins: [ new HappyPack({ // 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件 id: 'jsHappy', cache: true, threadPool: happyThreadPool, // 如何处理 .js 文件,用法和 Loader 配置中一样 loaders: [{ path: 'babel', query: { cacheDirectory: '.webpack_cache', presets: [ 'es2015', 'react' ] } }] }), //如果有单独提取css文件的话 new HappyPack({ id: 'lessHappy', // 如何处理 .js 文件,用法和 Loader 配置中一样 loaders: ['style','css','less'] }) ]
(7)模块热替换(它允许在运行时更新所有类型的模块,而无需完全刷新) ---开发环境
-
更新[webpack-dev-server]配置,使用 webpack 内置的 HMR 插件[HotModuleReplacementPlugin]
``` devServer: { contentBase: './dist', hot: true } plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: '模块热替换' }), new webpack.HotModuleReplacementPlugin() ] ```
(8)懒加载 不即时加载所有资源,而是在需要的时候才加载
-
@babel/plugin-syntax-dynamic-import
test: /\.js$/, exclude: /node_modules/, use:[ { loader: 'babel-loader', options: {//如果有这个设置则不用再添加.babelrc文件进行配置 "babelrc": false,// 不采用.babelrc的配置 "plugins": [ "@babel/plugin-syntax-dynamic-import" ] } } ]
代码优化
JS优化
- 变量名在不影响语义的情况下尽量简单(可以选择首字母命名)
- 尽量使用局部变量(避免作用域链一层一层查找)
-
避免增长作用域链(with/try...catch..)
- with使对象的属性可以像全局变量使用,增长了作用域链
- try...catch中catch在作用域顶端增加对象,命名的异常对象,影响较少
-
条件判断
- 条件分支较多时将出现概率较大的放在最上面
- 层数较深时,switch比if性能更高
- 对应的结果是单一值,可以使用数组
var a = [v0,v1,v1]; return a[value];
-
快速循环
- 尽量少使用for in 循环,需要查询hash键
- 循环总次数使用局部变量
var len = arr.length;for(var i = 0; i< len ; i++){}
-
高效存取数据
- 字面量值和变量中存取数据是最快的,从数组元素和对象属性中存取值相对较慢
- 减少对象的查找 将其缓存在变量中
-
使用第三库时,用子模块代替整个包
import _ from 'loadsh';(不推荐) import forEach from 'lodash/forEach';(推荐)
-
字符串连接
- 追加字符串,最好使用
s+=anotherStr
- 连接多个字符串,不要个个使用+=,使用
s+=a+b+c
- 追加字符串,最好使用
-
类型转换
- 数字转换字符转 性能:("" +) > String() > .toString() > new String()
- 浮点数转换成整型使用Math.floor()/Math.round(),parseInt()将字符串转换成数字,使用内部对象,没有使用太多查询方法和调用的时间,速度最快
- 尽量使用json格式创建对象或者数组,而不是new,json格式引擎直接解释,new需要调用构造器
- 对字符串进行循环操作(替换,查找),使用正则(c写的api,速度高于js循环)
- 对象查询[]会比.查询快
-
减少对dom的操作
- 对dom操作,保证N次创建(js),最后一次写入(html)
react优化
- 不要滥用{...this.props},只传递组件需要的props,传递太多或层次太深,会加重shouldComponentUpdate的负担
- 使用箭头函数来绑定函数
- 尽量使用稳定常量作为key值,避免index
- 尽量少用不可控的refs、DOM操作
- props,state的数据尽量简单,明了,扁平化,便于数据对比,遍历等
- 使用React Fragments避免额外的标记
- 尽量少使用内联函数,每次调用render函数都会创建一个新的函数实例,渲染阶段会额外增加垃圾回收和绑定新函数的操作
- 避免在componentWillMount()中异步请求 初始化不会获取数据,重新渲染才会获取数据
-
组件化
- 组件分类(展示型、交互型、数据型、高阶组件)
- 可复用性 组件自己控制自己内部的state,setState只用局部更新视图,降低组件之间的耦合度
- 组件拆分细(可读性强,维护性高,便于复用)
- 耦合度低
-
减少render次数
- Immutable 配合 shouldComponentUpdate 具体请看这里
- 使用防抖函数来减少不必要的setState,从而减少render次数
css优化
- 尽量少使用style属性修改元素,每次修改元素style,会触发回流
-
频繁触发重绘和回流,会导致UI频繁渲染,最终导致js变慢
- 回流必将触发重绘,重绘不一定触发回流
- 用translate(重绘)代替top(回流)
- 用opacity代替visibility(重绘)
- 不要使用table布局,很小的改动会导致整个table重新布局
- 尽量减少标签选择器的使用
- 减少ID标签使用,多使用样式选择器(具有通用性)
html优化
- 避免使用空的src和href,浏览器会将当前页面的url作为其属性值
备注:
webpack4生产环境优化
webpack4大结局:加入腾讯IM配置策略,实现前端工程化环境极致优化
webpack4 的30个步骤打造优化到极致的 react 开发环境,如约而至
前端性能优化指南
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。