极客时间返利平台,你可以在上边通过山月的链接购买课程,并添加我的微信 (shanyue94) 领取返现。
每天晚上九点 B站讲解前端工程化直播,并解答相关问题。

# 前端打包时 cjs、es、umd 模块有何不同

Issue

欢迎在 Gtihub Issue 中回答此问题: Issue 475 (opens new window)

# cjs (commonjs)

commonjs 是 Node 中的模块规范,通过 requireexports 进行导入导出 (进一步延伸的话,module.exports 属于 commonjs2)

同时,webpack 也对 cjs 模块得以解析,因此 cjs 模块可以运行在 node 环境及 webpack 环境下的,但不能在浏览器中直接使用。但如果你写前端项目在 webpack 中,也可以理解为它在浏览器和 Node 都支持。

比如,著名的全球下载量前十 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 (es module)

esm 是 tc39 对于 js 模块的规范,在 Node 及 浏览器中均会支持,使用 export/import 进行模块导入导出

// sum.js
export const sum = (x, y) => x + y;

// index.js
import { sum } from "./sum";

由于 esm 为静态导入,正因如此,可在编译器进行 Tree Shaking,减少 js 体积。tc39 为动态加载模块定义了 API: import(module)

esm 是未来的趋势,目前一些 CDN 厂商,前端构建工具均致力于 cjs 模块向 esm 的转化,比如 skypacksnowpackvite 等。

目前,在浏览器与 node.js 中均原生支持 esm。

  • cjs 模块输出的是一个值的拷贝,esm 输出的是值的引用
  • cjs 模块是运行时加载,esm 是编译时加载

示例: array-uniq (opens new window)

# umd

一种兼容 cjsamd 的模块,既可以在 node/webpack 环境中被 require,也可以在浏览器中直接用 CDN 被 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 (opens new window)

这三种模块方案大致如此,但是部分 npm package 也会同时打包出 commonjs/esm/umd 三种模块化格式,供不同需求的业务使用

Last Updated: 11/27/2021, 10:11:48 AM