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 反馈 — 无需本地设置。
此课程中的所有课时
- ES 模块:import、export 与动态 import
- npm 与 package.json:依赖和脚本
- Vite:开发服务器与构建
- 打包概念:摇树优化与代码拆分