动态导入(Dynamic Import)

动态导入使用 import() 函数,在运行时按需加载模块。


📚 基本语法

import() 函数

// 动态导入返回 Promise
import('./math.js')
  .then(module => {
    console.log(module.add(1, 2));
  })
  .catch(error => {
    console.error('加载模块失败', error);
  });

使用 async/await

async function loadModule() {
  try {
    const module = await import('./math.js');
    console.log(module.add(1, 2));
  } catch (error) {
    console.error('加载模块失败', error);
  }
}

🎯 使用场景

1. 按需加载(Code Splitting)

// 路由懒加载
const routes = [
  {
    path: '/home',
    component: () => import('./components/Home.js')
  },
  {
    path: '/about',
    component: () => import('./components/About.js')
  }
];

2. 条件加载

async function loadPolyfill() {
  if (!window.IntersectionObserver) {
    await import('./polyfills/intersection-observer.js');
  }
}

3. 按环境加载

async function loadConfig() {
  const isDev = process.env.NODE_ENV === 'development';
  const config = isDev
    ? await import('./config.dev.js')
    : await import('./config.prod.js');
  return config.default;
}

4. 用户交互触发加载

button.addEventListener('click', async () => {
  const { showModal } = await import('./modal.js');
  showModal();
});

📦 导入方式

导入默认导出

const module = await import('./utils.js');
const formatDate = module.default;
formatDate(new Date());

导入命名导出

const { add, subtract } = await import('./math.js');
console.log(add(1, 2));

导入全部

const math = await import('./math.js');
console.log(math.add(1, 2));
console.log(math.subtract(5, 2));

🔄 与静态导入对比

特性静态导入 import动态导入 import()
加载时机编译时运行时
返回值模块对象Promise
代码分割自动需要配置
Tree shaking支持支持
条件加载不支持支持
性能初始加载按需加载

💡 最佳实践

1. 错误处理

async function loadModule() {
  try {
    const module = await import('./math.js');
    return module;
  } catch (error) {
    console.error('模块加载失败:', error);
    // 降级处理
    return null;
  }
}

2. 预加载提示

// 使用 link rel="modulepreload" 预加载
const link = document.createElement('link');
link.rel = 'modulepreload';
link.href = './math.js';
document.head.appendChild(link);

3. 批量动态导入

async function loadModules() {
  const [math, utils, config] = await Promise.all([
    import('./math.js'),
    import('./utils.js'),
    import('./config.js')
  ]);
  
  return { math, utils, config };
}

4. React 懒加载示例

import { lazy, Suspense } from 'react';
 
const Home = lazy(() => import('./components/Home'));
const About = lazy(() => import('./components/About'));
 
function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Home />
      <About />
    </Suspense>
  );
}

⚠️ 注意事项

1. 返回 Promise

// ❌ 错误:不能直接使用
const module = import('./math.js'); // 这是 Promise,不是模块
 
// ✅ 正确:使用 await 或 then
const module = await import('./math.js');

2. 路径必须是字符串字面量

// ❌ 错误:不能使用变量
const path = './math.js';
import(path); // 语法错误
 
// ✅ 正确:使用字符串字面量
import('./math.js');

3. 浏览器兼容性

动态导入需要现代浏览器支持,旧浏览器需要 polyfill 或转译。


🔗 相关链接


参考


javascript 模块化 动态导入 code-splitting 懒加载