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

渲染优化:虚拟列表优化

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

在 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. 按需加载,减轻首屏渲染的负担,合理利用路由懒加载,组件库按需加载,延迟加载第三方包
相关推荐
天宇&嘘月2 小时前
web第三次作业
前端·javascript·css
小王不会写code2 小时前
axios
前端·javascript·axios
发呆的薇薇°3 小时前
vue3 配置@根路径
前端·vue.js
luckyext3 小时前
HBuilderX中,VUE生成随机数字,vue调用随机数函数
前端·javascript·vue.js·微信小程序·小程序
小小码农(找工作版)4 小时前
JavaScript 前端面试 4(作用域链、this)
前端·javascript·面试
前端没钱4 小时前
前端需要学习 Docker 吗?
前端·学习·docker
前端郭德纲4 小时前
前端自动化部署的极简方案
运维·前端·自动化
海绵宝宝_4 小时前
【HarmonyOS NEXT】获取正式应用签名证书的签名信息
android·前端·华为·harmonyos·鸿蒙·鸿蒙应用开发
码农土豆5 小时前
chrome V3插件开发,调用 chrome.action.setIcon,提示路径找不到
前端·chrome
鱼樱前端5 小时前
深入JavaScript引擎与模块加载机制:从V8原理到模块化实战
前端·javascript