Open kangyana opened 1 year ago
commonjs 是 Node 中的模块规范,通过 require 和 exports 进行导入导出 。 (进一步延伸的话,module.exports 属于 commonjs2)
commonjs
require
exports
module.exports
commonjs2
同时,webpack 也对 cjs 模块得以解析,因此 cjs 模块可以运行在 node 环境及 webpack 环境下的,但不能在浏览器中直接使用。 但如果你写前端项目在 webpack 中,也可以理解为它在浏览器和 Node 都支持。
cjs
比如,著名的全球下载量前十 10 的模块 ms (opens new window)只支持 commonjs, 但并不影响它在前端项目中使用(通过 webpack),但是你想通过 cdn 的方式直接在浏览器中引入,估计就会出问题了。
基本使用方法:
// sum.js exports.sum = (x, y) => x + y; // index.js const { sum } = require("./sum.js");
由于 cjs 为动态加载,可直接 require 一个变量:
require(`./${a}`);
esm 是 tc39 对于 ESMAScript 的模块话规范,正因是语言层规范,因此 在 Node 及 浏览器中均会支持。
esm
它使用 import/export 进行模块导入导出:
import/export
// sum.js export const sum = (x, y) => x + y; // index.js import { sum } from "./sum";
esm 为静态导入,正因如此,可在编译期进行 Tree Shaking,减少 js 体积。
Tree Shaking
如果需要动态导入,tc39 为动态加载模块定义了 API:import(module)。
import(module)
const ms = await import("https://cdn.skypack.dev/ms@latest"); ms.default(1000);
esm 是未来的趋势,目前一些 CDN 厂商,前端构建工具均致力于 cjs 模块向 esm 的转化,比如 skypack、 snowpack、vite 等。
skypack
snowpack
vite
目前,在浏览器与 node.js 中均原生支持 esm。
cjs 模块输出的是一个值的拷贝,esm 输出的是值的引用。 cjs 模块是运行时加载,esm 是编译时加载。
示例: array-uniq
一种兼容 cjs 与 amd 的模块,既可以在 node/webpack 环境中被 require 引用,也可以在浏览器中直接用 CDN 被 script.src 引入。
amd
node/webpack
script.src
(function (root, factory) { if (typeof define === "function" && define.amd) { // AMD define(["jquery"], factory); } else if (typeof exports === "object") { // CommonJS module.exports = factory(require("jquery")); } else { // 全局变量 root.returnExports = factory(root.jQuery); } })(this, function ($) { // ... });
示例: react-table (opens new window), antd
这三种模块方案大致如此,部分 npm package 也会同时打包出 commonjs/esm/umd 三种模块化格式,供不同需求的业务使用,比如 antd (opens new window)。
commonjs/esm/umd
antd 的 cjs(opens new window) antd 的 umd(opens new window) antd 的 esm
1. cjs (commonjs)
commonjs
是 Node 中的模块规范,通过require
和exports
进行导入导出 。 (进一步延伸的话,module.exports
属于commonjs2
)同时,webpack 也对
cjs
模块得以解析,因此cjs
模块可以运行在 node 环境及 webpack 环境下的,但不能在浏览器中直接使用。 但如果你写前端项目在 webpack 中,也可以理解为它在浏览器和 Node 都支持。比如,著名的全球下载量前十 10 的模块 ms (opens new window)只支持
commonjs
, 但并不影响它在前端项目中使用(通过 webpack),但是你想通过 cdn 的方式直接在浏览器中引入,估计就会出问题了。基本使用方法:
由于
cjs
为动态加载,可直接require
一个变量:2. esm (es module)
esm
是 tc39 对于 ESMAScript 的模块话规范,正因是语言层规范,因此 在 Node 及 浏览器中均会支持。它使用
import/export
进行模块导入导出:esm
为静态导入,正因如此,可在编译期进行Tree Shaking
,减少 js 体积。如果需要动态导入,tc39 为动态加载模块定义了 API:
import(module)
。esm
是未来的趋势,目前一些 CDN 厂商,前端构建工具均致力于cjs
模块向esm
的转化,比如skypack
、snowpack
、vite
等。目前,在浏览器与 node.js 中均原生支持
esm
。cjs
模块输出的是一个值的拷贝,esm
输出的是值的引用。cjs
模块是运行时加载,esm
是编译时加载。示例: array-uniq
3. umd(Universal Module Definition)
一种兼容
cjs
与amd
的模块,既可以在node/webpack
环境中被require
引用,也可以在浏览器中直接用 CDN 被script.src
引入。示例: react-table (opens new window), antd
这三种模块方案大致如此,部分 npm package 也会同时打包出
commonjs/esm/umd
三种模块化格式,供不同需求的业务使用,比如 antd (opens new window)。antd 的 cjs(opens new window) antd 的 umd(opens new window) antd 的 esm