import() 是返回 Promise 的动态导入函数,支持运行时按需加载和代码分割;而 static import 是顶层静态声明,编译期即打包进主 chunk。
import() 动态导入?它和 import 静态声明有什么本质区别?import() 是一个返回 Promise 的函数,用于在运行时按需加载模块;而 import 语句必须写在模块顶层,是编译期静态分析的依赖,会被 Webpack/Vite 等打包工具提前收集并打包进初始 chunk。
关键区别在于:只有 import() 能触发真正的代码分割,让模块不进入主包,也不参与首屏加载。
import:哪怕只用了一行 import { utils } from './utils.js',整个 utils.js 就会打进 main.js
import():写成 const { utils } = await import('./utils.js'),打包工具会自动把它抽成独立 chunk(如 789.js),仅当执行到这行才发起请求if 外层或函数参数里写 import() —— Vite/Webpack 要求路径必须是“可静态分析的字符串”,比如 import(`./pages/${page}.js`) 可以,但 import(`./pages/${getModule()}.js`) 会报错React.lazy() + Suspense 懒加载组件,为什么有时不生效?React.lazy() 底层就是封装了 import(),但它有硬性限制:只支持默认导出(export default),且必须配合 使用。漏掉任意一点,懒加载就退化成同步加载。
常见失效场景:
export const Page = () => {...}),没写 export default Page → 报错 lazy function must resolve a component
里 → React 会立刻同步执行 import(),失去懒加载意义React.lazy() → 不支持,会抛错,得改用 loadable-components 或手动判断 typeof window !== 'undefined'
const Dashboard = React.lazy(() => import('./Dashboard'));
// ✅ 正确:default export + Suspense 包裹
function App() {
return (
Loading...>
);
}/* webpackChunkName: "xxx" */ 注释有什么实际作用?这个魔法注释不是装饰,而是明确告诉 Webpack:“把这个动态导入生成的 chunk,命名为 xxx”,否则它会用数字 ID(如 123.js),不利于调试、缓存和 CDN 配置。
更关键的是:同名 chunk 会被合并。比如多个地方都写了 /* webpac,最终只会生成一个
kChunkName: "vendor" */ import('lodash')vendor.js,而不是重复打包多份 lodash。
/* webpackChunkName: "pages-[request]" */ 会让 import(`./pages/${name}.js`) 生成 pages-home.js、pages-about.js 等可读文件名build.rollupOptions.output.manualChunks 或 dynamicImportVars 插件替代common)会导致不同业务逻辑挤进同一个 chunk,反而增大单个请求体积懒加载 ≠ 自动优化首屏性能。如果懒加载的模块本身依赖大量其他模块(比如某个页面组件内部又 import 了 5 个大图表库),这些依赖仍会被打到该页面 chunk 里,导致 chunk 体积暴涨,HTTP 请求耗时反而更长。
真正起效的前提是:被懒加载的模块足够“轻”,且它的依赖树也被合理拆分。
import 全量 UI 库(如 import ElementPlus from 'element-plus'),应改用按需导入或异步加载子组件最常被忽略的一点:懒加载只是把下载时机延后,但首次交互(如点击跳转)仍需等待 JS 下载 + 解析 + 执行,这部分延迟无法靠懒加载消除 —— 如果用户刚打开首页就猛点导航栏,体验上仍是“卡一下”。