0Pricing
Frontend Academy · 课时

ES 模块:import、export 与动态 import

使用具名导出、默认导出和命名空间导入,并通过动态 import() 延迟加载代码以提升性能。

ES 模块:import、export 与动态 import 是 CoddyKit 上的免费 Frontend Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Frontend Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Frontend Academy 课程共包含 4 节课。

回顾:ES Module 基础

ES Modules 会为每个文件创建独立的作用域。具名导出共享特定值,默认导出共享主要值。打包器或浏览器会在加载时解析导入。

// Named exports
export const API_BASE = '/api/v1';
export function formatDate(d) { return d.toISOString().slice(0, 10); }

// Default export
export default class ApiClient {
  constructor(base = API_BASE) { this.base = base; }
}

树摇——为什么具名导出很重要

打包器(Rollup、esbuild、Vite)会移除未使用的导出。如果您只导入 { formatDate },打包器就会从构建包中移除其他所有内容。具名导出支持树摇,而 import * as utils 可能会阻止树摇。

// consumers/report.js — only needs formatDate
import { formatDate } from './utils.js';
// Bundler omits API_BASE and ApiClient from this chunk

动态 import()——延迟加载

动态 import() 会返回一个 Promise。只有代码运行到这里时,模块才会被获取。打包器会自动将这些内容拆分为独立的代码块。

// Only load the heavy charting library when needed:
const showChart = async () => {
  const { Chart } = await import('./Chart.js');
  new Chart(canvas, config);
};

btn.addEventListener('click', showChart);

带错误处理的动态 import

将动态导入放在 try/catch 中,以便优雅地处理网络故障或缺失模块。

try {
  const module = await import('./optional-feature.js');
  module.activate();
} catch (err) {
  console.warn('Optional feature unavailable:', err.message);
}

import.meta

import.meta 包含当前模块的元数据。主要属性包括:import.meta.url(绝对 URL)、import.meta.env(Vite 环境变量)和 import.meta.resolve()。

// Get the directory of this module:
const dir = new URL('.', import.meta.url).pathname;

// Vite env vars:
const API_URL = import.meta.env.VITE_API_URL;
const isProd = import.meta.env.PROD;

模块执行——一次

无论被导入多少次,ES Modules 都只会执行一次。同一模块的所有导入方共享同一个实例。因此,模块非常适合实现单例(存储、事件总线)。

// store.js — evaluated once
const state = { count: 0 };
export const increment = () => state.count++;
export const getCount = () => state.count;

// Any file that imports from store.js gets the same state instance

循环依赖

两个模块可以相互导入。JavaScript 能够处理这种情况,但由于求值顺序的原因,某些值在首次使用时可能是 undefined。在大多数情况下,请重新组织代码以避免循环依赖。

TypeScript 中仅导入类型

使用 import type { ... } 仅导入类型。这些内容会在编译时被擦除,永远不会出现在输出构建包中。使用它们可以避免由仅类型引用导致的循环依赖。

import type { User } from './types.js';

function greet(user: User): string {
  return `Hello, ${user.name}`;
}

重新导出与聚合文件

聚合文件会从多个模块重新导出内容,从而创建一个便捷的统一导入入口。在大型应用中使用聚合文件时请务必小心,因为它们可能会妨碍树摇。

// components/index.ts
export { Button } from './Button';
export { Input } from './Input';
export type { ButtonProps } from './Button';

// Consumer:
import { Button, Input } from '@/components';

浏览器中的 script type=module

将 type="module" 添加到 script 标签中,即可直接在浏览器中启用 ES 模块语法,而不需要打包器。模块默认会延迟执行,并拥有自己的作用域。

<script type="module">
  import { greet } from './utils.js';
  greet('World');
</script>

CommonJS 与 ESM 的互操作性

Node.js 同时支持两者。ESM 文件使用 .mjs,或者在 package.json 中设置 "type": "module"。从 ESM 使用 CommonJS 软件包时,默认导出就是 module.exports 的值。打包器会透明地处理这一过程。

快速检查

与使用单个默认导出对象相比,使用具名导出的主要性能优势是什么?

回顾:深入了解 ES Modules

模块只执行一次,所有导入方共享同一个实例。树摇会移除未使用的具名导出。动态 import() 支持延迟加载和代码拆分。import.meta 提供模块上下文。聚合文件很方便,但可能会损害树摇。TypeScript 中仅导入类型的内容不会产生输出。

常见问题解答

「ES 模块:import、export 与动态 import」课时是免费的吗?

是的 — 「ES 模块:import、export 与动态 import」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Frontend Academy 课程的其余内容,请升级到 CoddyKit PRO。 Frontend Academy 课程共包含 4 节课。

「ES 模块:import、export 与动态 import」这节课中我会学到什么?

使用具名导出、默认导出和命名空间导入,并通过动态 import() 延迟加载代码以提升性能。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Frontend Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Frontend Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「ES 模块:import、export 与动态 import」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Frontend Academy 课中编写并运行代码吗?

能。每节 Frontend Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. ES 模块:import、export 与动态 import
  2. npm 与 package.json:依赖和脚本
  3. Vite:开发服务器与构建
  4. 打包概念:摇树优化与代码拆分
← 返回 Frontend Academy