写前端项目最影响启动速度的往往不是你的代码——是那个悄悄拖慢加载的第三方模块。import defer 把这件事从框架层拿到了语言层。

import defer 彻底变了前端模块加载的账。

写前端项目,最影响启动速度的往往不是你的代码——是那些带顶层副作用的第三方模块悄悄拖慢了加载。以前解决这个问题要靠动态 import()、懒加载路由、代码分割,但这些都是「绕过问题」,不是「解决问题本身」。

2026 年,这件事终于进了语言层。

import defer 是什么

这是 TC39 的 Stage 3 提案(已接近完成),由 Yulia Startsev、Guy Bedford、Nicolò Ribaudo 推动,它的核心想法很简单:模块声明时不执行,首次访问导出绑定才求值。

// 传统写法:引入时立即执行,拖慢启动
import * as analytics from "./analytics.js";

// import defer:声明但不执行
import defer * as analytics from "./analytics.js";

// 只有真正访问 analytics 时,整个模块图才会执行
console.log(analytics.trackEvent); // ← 这一行触发求值

关键点在于「首次访问」触发。这意味着:如果你只是 import 了但从未用过,模块根本不会跑。这和 dynamic import() 有本质区别——后者是异步的、会产生新的网络请求;而 import defer 是同步的、静态可分析的,构建工具在打包时就能优化模块图。

它解决了什么问题

传统 ES Module 的顶层 await 有一个隐藏的性能陷阱:任何一个顶层模块有副作用,整个依赖链都会被迫等待。

比如你引入了这样的模块:

// analytics.js
const start = performance.now();
console.log("Analytics loaded in", performance.now() - start, "ms");
// 发送初始化请求
fetch("/api/analytics/init");
export function trackEvent(name) { ... }

无论你在业务代码里有没有用到 trackEvent,这个模块在 import 时就会立即执行(fetch 请求 + console 全部跑一遍)。如果项目里有几十个这样的「安静模块」,启动时的网络开销和 CPU 时间就是一笔糊涂账。

import defer 把这个执行时机推迟到真正需要的时候。你不访问,就不执行。

对构建工具的影响

这件事的影响是全链路的。

打包层面: Rollup 和 Vite 早就开始探索延迟执行的可行性,但始终受限于语言层没有原生支持——打包工具只能通过静态分析推断哪些模块是「纯」的、可以安全延迟。import defer 给了语言层面的语义,构建工具可以更激进地做代码 Elimination,因为引擎保证了一个 defer 模块在被访问前不会产生任何副作用。

SSR/Serverless 层面: Node.js 和 Deno 都在关注这个提案。在 Serverless 环境里,冷启动时间是核心指标。一个顶层有很多工具库依赖的函数,import defer 可以让它在真正的 handler 调用前都不执行——冷启动时间直接从依赖图加载时间变成「第一个访问触发的延迟」。

浏览器的长期影响: V8 团队在多个场合表示过,Module Graph 的加载时间是大页面启动的主要瓶颈之一。原生 defer 支持意味着浏览器可以在网络层面并行预取所有 defer 模块的依赖树,但在执行层面严格按需——这比现在的 <link rel="modulepreload"> 更精确。

迁移路径

语法上完全向后兼容:现有 import * as ns from ./mod 不变,import defer 只是多了一个关键字。你可以选择性地对「确定无副作用或延迟使用」的模块开启 defer,不需要全量迁移。

// 这些保持不变
import React from "react";
import "./init-polyfills.js"; // 有顶层副作用,不适合 defer

// 这些可以改成 defer
import defer * as analytics from "./analytics.js";
import defer * as featureFlags from "./flags.js";
import defer * as heavyUtils from "./heavy-utils.js";

什么时候能用

Stage 3,已经很接近完成了。Chrome/Firefox/Safari 都在跟进,实现速度取决于引擎对模块图的内部改造。Node.js 也在关注这个提案(尤其是在 Serverless 场景下的需求)。

你不需要现在就在生产环境用它——但你需要知道这个方向是对的:前端工具链里那套「手动延迟加载」的样板代码,未来五年会逐步被语言层的原语接管。

下一步:如果你在维护一个 SSR 框架或者构建工具链,现在就可以开始规划对 defer 模块的构建时优化;如果你在写业务代码,可以开始审视项目里那些「引入但不立即使用」的模块——等浏览器支持到位,这些就是第一批可以加 defer 的目标。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 409 阅读