动态 import() 的使用场景和注意事项?

import() 是 ESM 的动态加载语法,返回 Promise,用于按需加载模块。

基本用法

// 静态导入(编译时加载)
import { add } from './math.js'

// 动态导入(运行时加载)
const module = await import('./math.js')
console.log(module.add(1, 2))

使用场景

1. 路由懒加载

// React
const Home = lazy(() => import('./pages/Home'))
const About = lazy(() => import('./pages/About'))

// Vue
const routes = [
  { path: '/', component: () => import('./pages/Home.vue') },
  { path: '/about', component: () => import('./pages/About.vue') }
]

2. 条件加载

if (featureFlags.advanced) {
  const advanced = await import('./features/advanced.js')
  advanced.init()
}

3. 按需加载大依赖

// 只在需要时加载 PDF 库
async function exportPDF() {
  const { jsPDF } = await import('jspdf')
  const doc = new jsPDF()
  doc.text('Hello', 10, 10)
  doc.save()
}

4. 加载语言包

async function setLanguage(lang) {
  const messages = await import(`./locales/${lang}.js`)
  i18n.setLocaleMessage(lang, messages.default)
}

import() 与代码分割

构建工具遇到 import() 会自动创建单独的 chunk:

// 构建前
import('./heavy.js').then(module => {
  module.run()
})

// 构建后生成:
// main.js(入口 chunk)
// heavy.[hash].js(单独 chunk,按需加载)

预加载提示

// Webpack magic comments
const module = import(
  /* webpackChunkName: "dashboard" */
  /* webpackPrefetch: true */  // 空闲时预加载
  './Dashboard'
)

/* webpackPreload: true */  // 与父 chunk 并行加载

prefetch vs preload

<!-- HTML 中的 prefetch/preload -->
<link rel="prefetch" href="/next-page.js">
<link rel="preload" href="/critical.js" as="script">

动态导入的注意事项

1. 模块路径

// ✅ 静态字符串
import('./module.js')

// ✅ 模板字符串(有限制)
import(`./locales/${lang}.js`)  // 构建工具会生成所有可能的 chunk

// ❌ 完全动态
import(variablePath)  // 不支持

2. 错误处理

try {
  const module = await import('./optional.js')
} catch (e) {
  console.log('模块加载失败')
  // 降级处理
}

3. 缓存

// 同一模块多次 import() 只加载一次
const a = await import('./math.js')
const b = await import('./math.js')
console.log(a === b)  // true(缓存的模块记录)

Vite 中的动态导入

// Vite 支持 glob 导入
const modules = import.meta.glob('./pages/*.vue')
// 返回: { './pages/Home.vue': () => import('./pages/Home.vue'), ... }

// Eager(立即加载)
const modules = import.meta.glob('./pages/*.vue', { eager: true })

使用建议

同分类其他题目