无需登录 数据私有 本地保存

Service Worker 缓存内容预览器 - 查看离线资源列表

33
0
0
0
打包体积(Bundle Size)

打包体积是指前端项目经过构建工具(如 Webpack、Vite、Rollup 等)打包后输出的 JavaScript、CSS 等资源文件的总大小。打包体积通常以字节(B)、千字节(KB)或兆字节(MB)为单位。打包体积分为未压缩体积(用于开发和调试)和压缩后体积(用于生产部署)。未压缩体积是原始代码加上所有依赖后的大小,压缩后体积是经过代码压缩(如 Terser)、Tree Shaking、代码分割等优化后的大小。浏览器实际下载的是压缩后的体积,而 gzip 或 brotli 压缩可以进一步减小传输体积。打包体积是影响页面加载速度的关键因素。

Tree Shaking

Tree Shaking 是一种基于 ES Modules 静态分析的代码优化技术,用于移除项目中未被使用的导出代码。该技术最早由 Rollup 引入,后被 Webpack 2+ 和 Vite 等构建工具支持。Tree Shaking 的名称来源于"摇晃树木抖落枯叶"的比喻:构建工具会分析模块的导入和导出关系,找到真正被使用的代码(活代码),移除未被引用的代码(死代码)。Tree Shaking 只能处理 ES Modules 的静态导入,对 CommonJS 的动态 require 和动态 import 无法生效。正确使用 Tree Shaking 需要确保依赖库提供了 ES Modules 版本的导出,并且在 package.json 中配置了 sideEffects: false。

代码分割(Code Splitting)

代码分割是将一个大的打包文件拆分为多个小的代码块(chunk)的技术。用户在访问页面时只需要下载当前页面需要的代码块,其他代码块在需要时(如路由切换、用户交互)再动态加载。代码分割可以显著减少首屏加载时间。常见的代码分割策略包括:路由级分割(每个路由对应一个代码块)、组件级分割(使用 React.lazy 或 defineAsyncComponent 懒加载组件)、条件分割(根据用户设备或功能开关加载不同的代码)。Webpack 的 dynamic import() 语法和 Vite 的动态导入功能都支持代码分割。

依赖树(Dependency Tree)

依赖树是描述项目中各模块之间依赖关系的数据结构。在前端项目中,每个模块(组件、工具函数、第三方库等)都可能依赖其他模块,形成一棵树状的依赖关系。依赖树的根节点通常是应用的入口文件(如 main.js 或 index.js),从根节点出发可以遍历到所有被引用的模块。构建工具在打包过程中会解析依赖树,确定哪些模块需要被打入最终的打包文件。分析依赖树可以帮助开发者理解项目的模块结构、发现不必要的依赖、识别重复依赖和评估每个模块对总体积的贡献。

按需导入(On-demand Import)

按需导入是指只导入实际使用的组件或功能代码,而不是导入整个库的全部代码。许多前端组件库(如 Ant Design、Element UI、Material UI 等)都支持按需导入功能。例如,如果项目只使用了 Button 和 Input 两个组件,按需导入只会打包这两个组件的代码,而不会引入整个组件库的所有组件代码。按需导入通常通过 Babel 插件(如 babel-plugin-import)或构建工具的自动导入功能(如 Vite 的 unplugin-vue-components)来实现。按需导入可以大幅减少第三方组件库的体积占用,是前端性能优化的重要手段之一。

自身体积 vs 累计体积

自身体积(Self Size)是指一个组件或模块自身代码的大小,不包含它所依赖的其他模块的体积。累计体积(Total Size)是指一个组件的自身体积加上它所有子依赖的累计体积之和。区分这两个概念对于体积优化非常重要。如果一个组件的自身体积很大,说明组件自身的代码量需要优化(如简化逻辑、提取公共代码)。如果一个组件的自身体积很小但累计体积很大,说明它引入的第三方库体积较大,需要考虑替换为更轻量的替代方案或使用按需导入。本工具同时展示两个维度的体积数据,帮助开发者做出正确的优化决策。

Source Map

Source Map 是一种将压缩、混淆后的代码映射回原始源代码的文件。在生产环境中,JavaScript 和 CSS 代码通常会被压缩和混淆以减小体积和保护源代码。Source Map 文件记录了压缩后代码的每个位置对应的原始源代码位置。Source Map 的常见用途包括:浏览器开发者工具中的代码调试(可以看到原始源代码而非压缩后的代码)、体积分析工具(可以精确分析每个源文件对最终打包文件的体积贡献)。Webpack 和 Vite 等构建工具在打包时可以生成 Source Map 文件,通过 source-map-explorer 等工具可以基于 Source Map 分析打包文件的体积构成。

Gzip 和 Brotli 压缩

Gzip 和 Brotli 是两种广泛使用的 HTTP 压缩算法,用于在服务器和浏览器之间传输数据时减小资源体积。Gzip 基于 DEFLATE 算法,是 Web 上最常用的压缩方式,通常可以将文本资源(JS、CSS、HTML)压缩到原始大小的 20% 到 30%。Brotli 是 Google 开发的新一代压缩算法,在相同压缩级别下比 Gzip 压缩率更高 15% 到 25%,但压缩速度稍慢。现代浏览器(Chrome 50+、Firefox 44+、Safari 11+、Edge 79+)都支持 Brotli 压缩。在评估前端资源的实际传输大小时,应该考虑 Gzip 或 Brotli 压缩后的体积,而非原始的未压缩体积。

Side Effects

Side Effects(副作用)是指模块在被导入时执行的、与模块导出值无关的操作。例如,修改全局变量、注册全局事件监听器、操作 DOM、执行立即函数等都属于副作用。在 Tree Shaking 的上下文中,如果一个模块被标记为有副作用,构建工具会保守地保留该模块的全部代码,即使其导出值没有被使用。在 package.json 中配置 "sideEffects": false 告诉构建工具该项目的所有模块都没有副作用,可以安全地进行 Tree Shaking。如果确实有部分文件包含副作用,可以使用数组形式精确指定:"sideEffects": ["*.css", "./src/polyfill.js"]。正确配置 sideEffects 是最大化 Tree Shaking 效果的关键。

动态导入(Dynamic Import)

动态导入是 ES2020 引入的 import() 函数语法,允许在运行时按需加载模块。与静态 import 语句在编译时确定依赖关系不同,动态导入在执行到该语句时才加载目标模块。动态导入返回一个 Promise,解析为模块的命名空间对象。在前端开发中,动态导入常用于实现路由级别的代码分割和组件级别的懒加载。例如,React 中使用 React.lazy(() => import('./HeavyComponent')) 来懒加载重型组件,Vue 中使用 defineAsyncComponent(() => import('./HeavyComponent')) 实现类似效果。动态导入是实现代码分割的基础技术,配合构建工具可以自动生成独立的代码块。