6.3 性能优化


文档摘要

6.3 性能优化 Bootstrap 全量 CSS 编译后约 230KB(压缩前)、bundle 脚本约 80KB——对首屏预算(经验值:关键 CSS 50KB、总脚本 150KB 量级)都是超标项。本节的裁决顺序:先立预算,再砍体积,后优加载。没有预算的优化是玄学,有预算的优化是工程。 位置:进阶四案第三案。它直接消费 5.1 节的按需引入能力,产出的加载策略将在 6.4 节的构建管线里固化。 预算立牌:先量再砍 图 6-3 一个内容站的首屏预算分配 图 6-3 一个内容站的首屏预算分配 第一刀:CSS 按需编译 工具类是体积大头(几万条选择器),5.1 的裁剪之外还有一招「只启用要用的工具族」:在引入 utilities 前调整 映射,把不用的族(如 float、overflow)摘除。

6.3 性能优化

Bootstrap 全量 CSS 编译后约 230KB(压缩前)、bundle 脚本约 80KB——对首屏预算(经验值:关键 CSS 50KB、总脚本 150KB 量级)都是超标项。本节的裁决顺序:先立预算,再砍体积,后优加载。没有预算的优化是玄学,有预算的优化是工程。

位置:进阶四案第三案。它直接消费 5.1 节的按需引入能力,产出的加载策略将在 6.4 节的构建管线里固化。

预算立牌:先量再砍

图 6-3 一个内容站的首屏预算分配

图 6-3 一个内容站的首屏预算分配

第一刀:CSS 按需编译

// 全量入口:@import "bootstrap/scss/bootstrap"; —— 230KB 的来源 // 按需入口(内容站只用到栅格、排版、卡片与少量工具类): @import "bootstrap/scss/functions"; @import "bootstrap/scss/variables"; @import "bootstrap/scss/variables-dark"; @import "bootstrap/scss/maps"; @import "bootstrap/scss/mixins"; @import "bootstrap/scss/root"; @import "bootstrap/scss/reboot"; @import "bootstrap/scss/type"; @import "bootstrap/scss/grid"; @import "bootstrap/scss/card"; @import "bootstrap/scss/utilities"; @import "bootstrap/scss/utilities/api"; // 效果:产物收缩到 60KB 上下,且 5.1 的变量覆盖照常生效

工具类是体积大头(几万条选择器),5.1 的裁剪之外还有一招「只启用要用的工具族」:在引入 utilities 前调整 $utilities 映射,把不用的族(如 float、overflow)摘除。反向的坑也要记:压缩工具类时别用字符串匹配清理器盲删——d-md-none 这类动态拼接的类名(JS 里拼、CMS 里配)清理器看不见,删完线上布局随机崩,属于「优化制造的事故」。

第二刀:脚本按需引入

// 全量:import 'bootstrap/dist/js/bootstrap.bundle.min.js' —— 80KB 全家桶 // 按需:只用 Modal 与 Dropdown 两个插件 import Modal from 'bootstrap/js/dist/modal'; import Dropdown from 'bootstrap/js/dist/dropdown'; // dropdown 自带依赖 Popper;modal 不带。按插件粒度引入时依赖各自携带,无需手动补 // 效果:脚本从 80KB 到 20KB 上下,交互代码只在用到时加载 // 再进一步:非首屏交互延迟初始化 const loadCarousel = () => import('bootstrap/js/dist/carousel'); document.querySelector('#hero')?.addEventListener('mouseenter', loadCarousel, { once: true });

第三刀与第四刀:图片与字体

<!-- 图片三判:响应式尺寸(srcset 按视口取图)、懒加载、明确尺寸防抖动 --> <img src="cover-md.jpg" srcset="cover-sm.jpg 576w, cover-md.jpg 992w, cover-lg.jpg 1400w" sizes="(max-width: 768px) 100vw, 50vw" width="640" height="360" loading="lazy" decoding="async" class="img-fluid rounded" alt="课程封面"> <!-- loading lazy:视口外不请求;width height 先占位,布局零跳动 -->
/* 字体两判:中文字体必须子集化(常用三千字全量动辄数 MB),加载策略用 swap */ @font-face { font-family: "BrandSans"; src: url("brand-sans-subset.woff2") format("woff2"); font-display: swap; /* 先用系统字渲染,字体到了再换,避免文字隐身 */ unicode-range: U+4E00-9FFF; /* 只在遇到中文字符时启用该字体 */ }

⚠️ 常见坑:font-display: swap 配未子集化的中文字体会造成「字体到了整页重排」的闪动;先子集化再 swap,闪动可控。另一个坑是给 loading="lazy" 加到首屏头图上——首屏图要抢时间,懒加载反而推迟它,判反了。

案例:官网首屏从 4.1 秒到 1.6 秒

背景:营销官网首屏(LCP 指标)4.1 秒。测量拆解:全量 CSS 230KB、bundle 80KB、首屏大图 1.8MB(手机上也下原图)、未子集化品牌字体 2.4MB。

操作:按四刀顺序——CSS 裁到 62KB(按需编译加工具族裁剪);JS 裁到 18KB(只引 modal 与 dropdown,轮播改动态导入);大图出三档(576/992/1400)配 srcset 与懒加载(头图除外),手机档 90KB;品牌字体子集化到 180KB 并 font-display swap。

结果:传输总量从约 4.5MB 降到 350KB,LCP 1.6 秒,四刀全部来自本节判例,没有换框架。

解读:优化次序的经济性——图片一刀砍掉 1.7MB,收益最大且零风险;字体一刀 2.2MB;CSS 与 JS 各几十 KB 但改善了渲染阻塞。先砍大头的传输,再动阻塞链的渲染,是预算思维的执行序。

变式:若站点进一步要做秒开(LCP 低于 1.2 秒),追加两判:头图改为带优先级提示的预加载;关键 CSS 内联进 HTML 首字节。两判都已越过 Bootstrap 本身,属于通用前端工程手段。

结案要点

  • 先立预算(传输大小口径)再优化,每版对比防「慢慢烂掉」;
  • CSS 四刀第一刀按需编译,工具类可整族裁但不可盲删(动态类名风险);
  • JS 按插件粒度引入,非首屏交互动态导入;
  • 图片三判(srcset、lazy、定宽高)与字体两判(子集化、swap);
  • 大头先砍传输、再理阻塞,换框架是最后选项。

下一节把编译与引入收进工具链,并审框架集成与版本迁移两案。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U