实战总结:让首屏加载时间锐减 50%+ 的优化策略

31 阅读2分钟

1、JavaScript优化

代码分割

使用动态导入实现路由级、组件级分割 -- 路由懒加载

Tree Shaking(树摇)增强

Tree Shaking 是一种用于JavaScript的 死代码消除技术,它通过静态分析的方式,在打包构建阶段移除应用程序中没有被实际使用的代码(好比摇晃树枝将枯叶掉落一样)。

一、核心原理:

1、静态分析:在代码不执行的情况下,通过分析模块之间的导入导出关系,识别哪些导出被使用,哪些从未被使用。

2、ES Module特性:Tree Shaking 依赖ES6模块系统的 静态结构(import/export必须在顶层作用域,不能动态导入导出)。

3、副作用(Side Effects)识别:有些代码虽然没有直接被使用,但可能有副作用(如修改全局变量、polyfill等),需要特殊处理。

二、工作流程

1、收集依赖:从入口文件开始,建立模块之间的依赖关系;

2、标记活跃代码:标记从入口开始可达的所有代码路径;

3、移除无用代码:删除所有未被标记的代码(包括整个模块、函数、变量等);

4、副作用处理:根据配置判断是否保留有副作用的代码。

三、在不同构建工具中的实现

1、webpack中的 Tree Shaking

// webpack.config.js
module.exports = {
    mode: 'production',
    optimization: {
        usedExports: true, // 标记被使用的导出
        minimize: true, // 启用压缩,实际删除未使用代码
        sideEffects: true, // 启用副作用分析
    }
}
// package.json

{
    "sideEffects": [
        "*.css", // 标记css文件有副作用(应保留)
        "*.scss", 
        "src/polyfill.js", // 特定的副作用文件
    ]
    // 或
    
    "sideEffects": false, // 表示所有文件都没有副作用
}

2、vite中的 Tree Shaking

vite 基于 Rollup 和 esbuild, 默认在生产构建中启用 Tree Shaking:

// vite.config.js

export default defineConfig({
    build: {
        rollupOptions: {
            treeshake: 'smallest', // 可选:smallest | safest | recommended
        }
    }
})

3、Rollup中的 Tree Shaking

Rollup 是最早实现 Tree Shaking 的打包工具,天生支持:

// rollup.config.js

export default {
    treeshake: {
        moduleSideEffects: true, // 更精细的副作用控制
        propertyReadSideEffects: false
    }
}

预加载关键资源

<link rel="preload" href="critical.css" as="style">
<link rel="prefetch" href="non-critical.js" as="script">

CSS 优化

CSS压缩与优化

// 移除未使用CSS
const PurgeCSSPlugin = require('purgecss-webpack-plugin')

图片与媒体优化

图片策略

实现图片懒加载

<!-- 响应式图片 -->
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" loading="lazy" decoding="async">
</picture>

<!-- 懒加载 -->
<img data-src="image.jpg" class="lazyload">