性能优化
在构建现代 Web 应用时,性能始终是开发者关注的重点之一。无论是首次加载速度、响应式更新效率,还是组件渲染粒度,合理的优化手段都能带来更流畅的用户体验。通过减少不必要的依赖追踪、按需渲染、延迟更新以及原始值操作等方式,可以有效降低开销、提升整体运行效率,让应用在保持复杂功能的同时依然快速响应。
摇树优化
使用 create-qingkuai 创建的项目默认采用 Vite 作为构建和打包工具,而 Vite 底层基于 Rollup,它具备优秀的摇树优化(Tree-shaking)能力,这得益于 import 语法的静态导入特性。
在设计之初,Qingkuai 就充分考虑了 Tree-shaking 的优势。所有 API 乃至指令都支持摇树优化。比如,如果你在代码中未使用 #for 指令,那么与其相关的代码不会被打包进最终产物。其他指令和功能也遵循相同原则,从源头上避免无用代码引入,进一步优化构建性能与产物体积。
<!-- 除 #if 指令外的其他指令的运行时代码不会被打包到最终产物 -->
<div #if={visible}>...</div>
为了获得更好的 Tree-shaking 效果,建议在导入第三方库时尽量使用 ESM(ES Module)格式的版本。相比于 CommonJS,ESM 支持静态分析,使构建工具能够准确识别和移除未使用的模块代码,从而减小打包体积。例如,在使用一些既提供 CommonJS 又提供 ESM 的库时,应优先选择其 ESM 版本,这种导入方式将显著提升最终构建产物的精简度与执行性能:
// 推荐:ESM 模块,Tree-shaking 友好,打包体积更小
import { debounce } from "lodash-es"
// 不推荐:CommonJS 模块,无法可靠地进行 Tree-shaking,可能引入整个 lodash
import { debounce } from "lodash"
样式复用
当同一个通用样式文件在多个组件的作用域嵌入样式块中,通过 src 或 @import 被重复引入时,编译结果通常会生成多份等价样式规则副本(分别附加不同组件的作用域标识)。这会增加 CSS 体积并放大样式解析开销。
<lang-css src="./common.css" />
<lang-css>
@import "./common.css";
</lang-css>
上面这种写法会让 common.css 在每个组件里都被单独作用域化一次:同一条原始规则会附加不同组件的作用域标识并生成多份副本。随着组件数量增加,这类重复规则会线性累积,直接推高 CSS 体积与浏览器样式匹配开销。对于跨组件复用的通用样式,建议优先采用以下方式:
将稳定的通用样式放到全局样式入口统一加载(如应用入口 CSS 或布局组件的全局样式);
对确实需要在组件内声明、但不依赖作用域隔离的样式,使用
global样式块或全局文件集中维护;仅把与组件结构强耦合、必须依赖作用域隔离的规则保留在组件作用域样式中;
代码分割
代码分割(Code-splitting)是前端性能优化的重要手段,用于将应用拆分成多个按需加载的模块,从而加快首屏加载速度并减少资源浪费。像 Vite 和 Rollup 这样的构建工具会根据静态依赖分析和 动态导入 自动进行模块拆分,并支持手动配置分块策略(如将第三方库分离),从而提升加载效率和浏览器缓存利用率:
// module.js及其依赖会被拆分到一个单独的文件中,
// 另外只有loadModule方法被调用时才会加载该模块
function loadModule() {
return import("./module.js")
}
在多路由应用中,不应将所有路由组件打包进主应用,而应借助代码分割机制实现路由懒加载,以显著提升加载效率和用户体验。这正是我们之前介绍的 异步组件 的核心作用:
<lang-js>
const ComponentModule = import("./Component.qk")
</lang-js>
<qk:spread
#await={ComponentModule}
#then={{ default: Component }}
>
<Component />
</qk:spread>