前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库动态 import 与静态 import 使用场景
JavaScript模块与语言机制

什么时候该用动态 import() 而不是静态 import?

静态 import 写在文件顶部,编译期就确定依赖关系,支持 tree-shaking。import() 在运行时按需加载,返回 Promise,适合路由懒加载、条件加载、重型库延迟加载这些不需要一开始就用到的场景。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#模块与语言机制
先看核心答案读代码示例
理解线索

两种导入的适用场景

  1. 静态 import始终需要的依赖,编译期分析,可被 tree-shaking
  2. import() 按需加载路由切换、用户操作触发时才需要的模块
  3. import() 条件加载根据环境、平台、用户权限决定加载哪个实现

能用静态 import 的场景就不要用 import()。静态导入对打包工具更友好,tree-shaking 更彻底,类型检查也更完整。

核心回答

先记住这个答案

静态 import 用于始终需要的依赖。它写在文件顶部,编译期就确定了模块之间的依赖关系,打包工具可以据此做 tree-shaking、类型检查、静态分析。import() 用于运行时才决定要不要加载的模块。它返回 Promise,可以出现在函数里、if 里、事件回调里,什么时候执行到就什么时候加载。

  • 静态 import 编译期确定依赖,支持 tree-shaking
  • import() 运行时加载,可以放在 if 或函数里
  • 路由懒加载是最常见的 import() 使用场景
  • 首屏不需要的重型库用 import() 延迟加载

路由懒加载:最典型的 import() 场景

单页应用里,用户进首页时不需要加载"设置页"的代码。如果全部静态 import,所有页面的代码会被打进一个大的 bundle,首屏加载时间变长。

React 路由配合 import() 实现懒加载JavaScript
// 每个路由组件用 import() 加载
// 打包工具会把每个 import() 的目标拆成单独的 chunk
const Home = lazy(() => import('./pages/Home'))
const Settings = lazy(() => import('./pages/Settings'))
const Dashboard = lazy(() => import('./pages/Dashboard'))

// 用户点击"设置"时才下载 Settings 的 chunk
// 首屏只下载 Home 的代码

React 的 lazy() 接受一个返回 import() 的函数,组件首次渲染时才触发加载。Vue Router 也是同样的思路——component: () => import('./views/About.vue')。这个写法已经是前端项目的标配了。

条件加载和环境判断

有些模块只在特定条件下才需要用到。比如只有管理员需要的权限管理模块,或者只在移动端需要的手势库。静态 import 没办法做到"满足条件才加载",因为它在编译期就确定了。

根据用户角色决定加载哪个模块JavaScript
async function initDashboard(user) {
  if (user.role === 'admin') {
    // 管理员才加载后台管理模块
    const { AdminPanel } = await import('./AdminPanel')
    renderAdmin(AdminPanel)
  } else {
    // 普通用户加载精简版
    const { UserPanel } = await import('./UserPanel')
    renderUser(UserPanel)
  }
}

这样普通用户永远不会下载管理员模块的代码,既减小了下载量,也避免了前端代码泄露管理功能的逻辑。 另一个常见场景是根据浏览器能力加载不同的 polyfill。比如检测到不支持 IntersectionObserver 时再动态加载 polyfill,支持的浏览器就省下这部分体积。

重型库延迟到用户操作时再加载

有些库体积很大,但只在用户触发特定操作时才用到。比如图表库只在用户点击"查看报表"时才需要,代码编辑器只在用户进入编辑页面时才需要。把这些库放在静态 import 里会拖慢首屏。

用 import() 可以在用户操作时才加载。虽然用户第一次点击时会有一点延迟(网络请求的时间),但首屏速度的提升通常远大于这个代价。可以配合 <link rel="modulepreload"> 或者在空闲时间用 requestIdleCallback 预加载来减少等待感。

回答前,多想一步

容易答错的地方

觉得所有 import 都可以换成 import()
import() 是异步的,用起来比静态 import 复杂——要处理 Promise、要考虑加载失败、要考虑加载期间的 UI 状态。而且 import() 加载的模块不能被 tree-shaking 分析得那么彻底。能用静态 import 就用静态的,只有真正需要按需加载的场景才用 import()。
以为 import() 只能用在浏览器环境
Node.js 同样支持 import()。在 CommonJS 文件里 import() 是加载 ESM 模块的唯一方式。Node.js 里虽然没有"首屏加载"的概念,但 import() 在写插件系统、按配置加载模块这些场景也很有用。
试着用自己的话回答

面试官还会怎么问?

import() 会影响 tree-shaking 吗?

会。静态 import 让打包工具在编译期就知道模块的哪些导出被用到了,没用到的可以删掉。import() 加载的模块,打包工具通常会把它的所有导出都保留,因为无法在编译期确定运行时会用到哪些。不过如果对 import() 的结果做了解构,有些打包工具能做一定程度的优化。

用 import() 加载的模块什么时候会被卸载?

不会被卸载。一旦模块被加载并执行,它就一直在内存里,下次 import() 同一个路径时直接从缓存拿。如果需要释放内存,需要确保没有任何引用指向该模块的导出对象,等待垃圾回收器处理——但模块本身在模块缓存里不会被清除。

import() 能和顶层 await 一起用吗?

可以。在支持顶层 await 的 ESM 模块里,可以直接写 const mod = await import('./a.js'),不需要包在 async 函数里。但要注意顶层 await 会阻塞依赖该模块的其他模块的执行,用在入口文件问题不大,用在被多处导入的工具模块里就要谨慎了。

从一道题,走向一组知识

把知识连起来

模块与语言机制

浏览器里用 script type="module" 加载模块要注意什么?

了解浏览器原生模块加载机制后,能更好地理解 import() 在浏览器里的实际行为。

模块与语言机制

export default 后面跟表达式和跟声明,有什么区别?

import() 拿到的命名空间对象里,默认导出在 .default 上,这和 export default 的行为直接相关。

参考资料

  • JavaScript:模块与语言机制参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 路由懒加载:最典型的 import() 场景
  3. 条件加载和环境判断
  4. 重型库延迟到用户操作时再加载
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑