前端开发中常见的性能优化手段

渲染优化:虚拟列表优化

老生常谈的话题,一般在视口内维护一个虚拟列表(仅渲染十几条条数据左右),监听视口位置变化,从而对视口内的虚拟列表进行控制。

在 React 中可采用以下库:

  1. react-virtualized
  2. react-window

构建层优化

只介绍 Webpack 构建工具,其他构建工具也是大同小异按照此思路去配置就可以。

减少打包时间

  1. 避免不必要的选择,配置include/exclude减少Loader对文件的搜索范围。
js 复制代码
export default {
    module:{
        rules:[
            {
               exclude: /node_modules/, // node_modules 体积过于庞大,检索成本过高
               include: /src/, // 根据自身情况去选择 代码一般都写在src目录下 
               test: /\.js$/, 
               use: "babel-loader"
            }
        ]
    }
}
  1. 编译时只编译修改过的文件,配置cache缓存 loader 对文件的编译副本
js 复制代码
// 大部分Loader/Plugin都会提供一个可使用编译缓存的选项,通常包含cache字眼。
// 以babel-loader和eslint-webpack-plugin为例。

import EslintPlugin from "eslint-webpack-plugin"; 
export default { 
    module: { 
        rules: [{ 
            test: /\.js$/, 
            use: [{ 
                loader: "babel-loader", 
                options: { cacheDirectory: true } 
            }] 
        }] 
   }, 
   plugins: [ new EslintPlugin({ cache: true }) ]   
};
  1. 定向指定必须文件路径,配置resolve提高文件的搜索速度,或者某些第三方库以常规形式引入可能报错或者希望程序自动索引特定类型文件都可以通过该方式解决。
js 复制代码
// alias映射模块路径,extensions表明文件后缀,noParse过滤无依赖文件。通常配置alias和extensions就足够。
export default {
    resolve: {
        alias: {
            "@": AbsPath("src"), // src目录快捷方式
            swiper: "swiper/js/swiper.min.js"
        }, // 模块导入快捷方式
        extensions: [".js", ".ts", ".jsx", ".tsx", ".json", ".vue"] // import路径时文件可省略后缀名
    }
};
  1. 并行构建,释放CPU多核并发的优势。配置ThreadLoader单进程转换为多进程。

    在使用 webpack 构建项目时会有大量文件需要解析和处理,构建过程是计算密集型的操作,随着文件增多构建过程变得会越来越慢,因为运行在Node里的Webpack是单线程模型。

    可以通过thread-loader来根据CPU个数开启多线程,如果项目文件不多不建议使用,毕竟开启多个线程也会存在性能开销。

js 复制代码
import Os from "os";

export default {
    module: {
        rules: [{
            test: /\.js$/,
            use: [{
                loader: "thread-loader",
                options: { workers: Os.cpus().length }
            }, {
                loader: "babel-loader",
                options: { cacheDirectory: true }
            }]
        }]
    }
};
  1. 分割代码减少重复代码出现的频率,分割各个模块代码,提取相同部分代码,splitChunks官网详细配置 这里列举一下平常用的配置
js 复制代码
export default {
    // ...
    optimization: {
        runtimeChunk: { name: "manifest" }, // 抽离WebpackRuntime函数
        splitChunks: {
            cacheGroups: {
                common: {
                    minChunks: 2,
                    name: "common",
                    priority: 5,
                    reuseExistingChunk: true, // 重用已存在代码块
                    test: AbsPath("src")
                },
                vendor: {
                    chunks: "initial", // 代码分割类型
                    name: "vendor", // 代码块名称
                    priority: 10, // 优先级
                    test: /node_modules/ // 校验文件正则表达式
                }
            }, // 缓存组
            chunks: "all" // 代码分割类型:all全部模块,async异步模块,initial入口模块
        } // 代码块分割
    }
};
  1. 移除重复代码和未使用代码,在webpack里只需将打包环境设置成生产环境就能生效。
js 复制代码
export default {
    mode: "production"
};
  1. 通过垫片服务根据UA返回当前浏览器代码垫片,好处是无需将繁重的代码垫片打包进去。每次构建都配置@babel/preset-envcore-js根据某些需求将Polyfill打包进来,这无疑又为代码体积增加了贡献。

@babel/preset-env提供的useBuiltIns可按需导入Polyfill

  • false :无视target.browsers将所有Polyfill加载进来
  • entry :根据target.browsers将部分Polyfill加载进来(仅引入有浏览器不支持的Polyfill,需在入口文件import "core-js/stable")
  • usage :根据target.browsers和检测代码里ES6的使用情况将部分Polyfill加载进来(无需在入口文件import "core-js/stable")

在此推荐大家使用动态垫片动态垫片可根据浏览器UserAgent返回当前浏览器Polyfill,其思路是根据浏览器的UserAgentbrowserlist查找出当前浏览器哪些特性缺乏支持从而返回这些特性的Polyfill。对这方面感兴趣的同学可参考polyfill-librarypolyfill-service的源码。

在此提供两个动态垫片服务,可在不同浏览器里点击以下链接看看输出不同的Polyfill。相信IExplore还是最多Polyfill的,它自豪地说:我就是我,不一样的烟火

使用html-webpack-tags-plugin在打包时自动插入动态垫片

js 复制代码
import HtmlTagsPlugin from "html-webpack-tags-plugin";

export default {
    plugins: [
        new HtmlTagsPlugin({
            append: false, // 在生成资源后插入
            publicPath: false, // 使用公共路径
            tags: ["https://polyfill.alicdn.com/polyfill.min.js"] // 资源路径
        })
    ]
};
  1. 按需加载,减轻首屏渲染的负担,合理利用路由懒加载,组件库按需加载,延迟加载第三方包
相关推荐
喵叔哟8 分钟前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解1 小时前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
Mr.咕咕1 小时前
Django 搭建数据管理web——商品管理
前端·python·django