博主信息
Sky
博文
291
粉丝
0
评论
0
访问量
7243
积分:0
P豆:617

前端模块化规范

2021年10月18日 20:43:06阅读数:12博客 / Sky

相关问题

JavaScript 主要有哪几种模块化规范AMD / CMD 有什么异同ESM 是什么模块化解决了什么问题/痛点

回答关键点

CommonJS AMD CMD UMD ESM

CommonJS[1]: 主要是 Node.js 使用,通过 require 同步加载模块,exports 导出内容。AMD[2]: 主要是浏览器端使用,通过 define 定义模块和依赖,require 异步加载模块,推崇依赖前置。CMD[3]: 和 AMD 比较类似,主要是浏览器端使用,通过 require 异步加载模块,exports 导出内容,推崇依赖就近。UMD[4]: 通用模块规范,是 CommonJS、AMD 两个规范的大融合,是跨平台的解决方案。ESM[5]: 官方模块化规范,现代浏览器原生支持,通过 import 异步加载模块,export 导出内容。

知识点深入

1. 为什么需要模块化和模块化规范

模块化可以解决代码之间的变量、函数、对象等命名的冲突/污染问题,良好的模块化设计可以降低代码之间的耦合关系,提高代码的可维护性、可扩展性以及复用性。

模块化规范的作用是为了规范 JavaScript 模块的定义和加载机制,以统一的方式导出和加载模块,降低学习使用成本,提高开发效率。

2. 各种模块化规范的细节

2.1 CommonJS

CommonJS 主要是 Node.js 使用,通过 require 同步加载模块,exports 导出内容。在 CommonJS 规范下,每一个 JS 文件都是独立的模块,每个模块都有独立的作用域,模块里的本地变量都是私有的。

示例

// hzfe.jsconst hzfeMember = 17;const getHZFEMember = () => {
 return `HZFE Member: ${hzfeMember}`;};module.exports.getHZFEMember = getHZFEMember;// index.jsconst hzfe = require("./hzfe.js");console.log(hzfe.getHZFEMember()); // HZFE Member: 17

使用场景

CommonJS 主要在服务端(如:Node.js)使用,也可通过打包工具打包之后在浏览器端使用。

加载方式

CommonJS 通过同步的方式加载模块,首次加载会缓存结果,后续加载则是直接读取缓存结果。

优缺点

优点

简单易用可以在任意位置 require 模块支持循环依赖

缺点

同步的加载方式不适用于浏览器端浏览器端使用需要打包难以支持模块静态分析

2.2 AMD (Asynchronous Module Definition)

AMD,即异步模块定义。AMD 定义了一套 JavaScript 模块依赖异步加载标准,用来解决浏览器端模块加载的问题。AMD 主要是浏览器端使用,通过 define 定义模块和依赖,require 异步加载模块,推崇依赖前置。

AMD 模块通过 define 函数定义在闭包中:

/**
* define
* @param id 模块名
* @param dependencies 依赖列表
* @param factory 模块的具体内容/具体实现
*/define(id?: string, dependencies?: string[], factory: Function | Object);

示例

// hzfe.jsdefine("hzfe", [], function () {
 const hzfeMember = 17;
 const getHZFEMember = () => {
   return `HZFE Member: ${hzfeMember}`;
 };

 return {
   getHZFEMember,
 };});// index.jsrequire(["hzfe"], function (hzfe) {
 // 依赖前置
 console.log(hzfe.getHZFEMember()); // HZFE Member: 17});

使用场景

AMD 主要在浏览器端中使用,通过符合 AMD 标准的 JavaScript 库(如:RequireJs)加载模块。

加载方式

AMD 通过异步的方式加载模块,每加载一个模块实际就是加载对应的 JS 文件。

优缺点

优点

依赖异步加载,更快的启动速度支持循环依赖支持插件

缺点

语法相对复杂依赖加载器难以支持模块静态分析

具体实现

RequireJs

2.3 CMD (Common Module Definition)

CMD,即通用模块定义。CMD 定义了一套 JavaScript 模块依赖异步加载标准,用来解决浏览器端模块加载的问题。CMD 主要是浏览器端使用,通过 define 定义模块和依赖,require 异步加载模块,推崇依赖就近。

CMD 模块通过 define 函数定义在闭包中:

/**
* define
* @param id 模块名
* @param dependencies 依赖列表
* @param factory 模块的具体内容/具体实现
*/define(id?: string, dependencies?: string[], factory: Function | Object);

示例

// hzfe.jsdefine("hzfe", [], function () {
 const hzfeMember = 17;
 const getHZFEMember = () => {
   return `HZFE Member: ${hzfeMember}`;
 };

 exports.getHZFEMember = getHZFEMember;});// index.jsdefine(function (require, exports) {
 const hzfe = require("hzfe"); // 依赖就近
 console.log(hzfe.getHZFEMember()); // HZFE Member: 17});

使用场景

CMD 主要在浏览器端中使用,通过符合 CMD 标准的 JavaScript 库(如 sea.js)加载模块。

加载方式

CMD 通过异步的方式加载模块,每加载一个模块实际就是加载对应的 JS 文件。

优缺点

优点

依赖异步加载,更快的启动速度支持循环依赖依赖就近与 CommonJS 保持很大的兼容性

缺点

语法相对复杂依赖加载器难以支持模块静态分析

具体实现

Sea.js

2.4 UMD (Universal Module Definition)

UMD,即通用模块定义。UMD 主要为了解决 CommonJS 和 AMD 规范下的手机游戏账号拍卖平台代码不通用的问题,同时还支持将模块挂载到全局,是跨平台的解决方案。

示例

// hzfe.js(function (root, factory) {
 if (typeof define === "function" && define.amd) {
   // AMD
   define(["exports", "hzfe"], factory);
 } else if (
   typeof exports === "object" &&
   typeof exports.nodeName !== "string"
 ) {
   // CommonJS
   factory(exports, require("hzfe"));
 } else {
   // Browser globals
   factory((root.commonJsStrict = {}), root.hzfe);
 }})(typeof self !== "undefined" ? self : this, function (exports, b) {
 const hzfeMember = 17;
 const getHZFEMember = () => {
   return `HZFE Member: ${hzfeMember}`;
 };

 exports.getHZFEMember = getHZFEMember;});// index.jsconst hzfe = require("./hzfe.js");console.log(hzfe.getHZFEMember()); // HZFE Member: 17

使用场景

UMD 可同时在服务器端和浏览器端使用。

加载方式

UMD 加载模块的方式取决于所处的环境,Node.js 同步加载,浏览器端异步加载。

优缺点

优点

跨平台兼容

缺点

代码量稍大

2.5 ESM (ECMAScript Module)

ESM,即 ESModule、ECMAScript Module。官方模块化规范,现代浏览器原生支持,通过 import 加载模块,export 导出内容。
示例

// hzfe.jsconst hzfeMember = 17;export const getHZFEMember = () => {
 return `HZFE Member: ${hzfeMember}`;};// index.jsimport * as hzfe from "./hzfe.js";console.log(hzfe.getHZFEMember()); // HZFE Member: 17

使用场景

ESM 在支持的浏览器环境下可以直接使用,在不支持的端需要编译/打包后使用。

加载方式

ESM 加载模块的方式同样取决于所处的环境,Node.js 同步加载,浏览器端异步加载。

优缺点

优点

支持同步/异步加载语法简单支持模块静态分析支持循环引用

缺点

兼容性不佳

扩展阅读

1. 静态分析

静态程序分析(Static program analysis)是指在不运行程序的条件下,进行程序分析的方法。 静态程序分析 - Wiki

简而言之,前文里提到的静态分析就是指在运行代码之前就可判断出代码内有哪些代码使用到了,哪些没有使用到。

2. 模块化与工程化:webpack

webpack 同时支持 CommonJS、AMD 和 ESM 三种模块化规范的打包。根据不同规范 webpack 会将模块处理成不同的产物。

CommonJS

(function (module, exports) {
 const hzfeMember = 17;
 const getHZFEMember = () => {
   return `HZFE Member: ${hzfeMember}`;
 };

 module.exports = getHZFEMember;});

AMD

(function (module, exports, __webpack_require__) {
 var __WEBPACK_AMD_DEFINE_ARRAY__, // 依赖列表
   __WEBPACK_AMD_DEFINE_RESULT__; // factory 返回值

 __WEBPACK_AMD_DEFINE_ARRAY__ = [];

 // 执行 factory
 __WEBPACK_AMD_DEFINE_RESULT__ = function () {
   const hzfeMember = 17;
   const getHZFEMember = () => {
     return `HZFE Member: ${hzfeMember}`;
   };

   return {
     getHZFEMember,
   };
 }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__);

 __WEBPACK_AMD_DEFINE_RESULT__ !== undefined &&
   (module.exports = __WEBPACK_AMD_DEFINE_RESULT__);});

ESM

(function (module, __webpack_exports__, __webpack_require__) {
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.d(__webpack_exports__, "getHZFEMember", function () {
   return getHZFEMember;
 });

 const hzfeMember = 17;
 const getHZFEMember = () => {
   return `HZFE Member: ${hzfeMember}`;
 };});

3. 模块化与工程化:Tree Shaking

Tree shaking 是一个通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)行为的术语。它依赖于 ES2015 中的 import 和 export 语句,用来检测代码模块是否被导出、导入,且被 JavaScript 文件使用。 Tree Shaking - MDN

简单来说,Tree Shaking 是一种依赖 ESM 模块静态分析实现的功能,它可以在编译时安全的移除代码中未使用的部分(webpack 5 对 CommonJS 也进行了支持,在此不详细展开)。


版权申明:本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论
  • Node应用由组成,其系统借鉴了CommonJS,但是并未完全按照实现,而是根据自身需求增加了一些特性,算是CommonJS的一个变种。
    本篇文章给大家详细了解一下Nodejs中的。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
    Python视频教程栏目今天为大家介绍学习Python导入机制与大型项目的,在我们平常工程里使用Python的过程中,经常需要解决各个的导入问题,而且也常常遇到引用路径查找不到、交叉导入等等问题
    本篇文章给大家介绍一下Bootstrap视图中使用@RenderPage实现页面内容隔离的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
    对数据库式进行处理,是在数据库设计的“逻辑设计阶段”。数据库的逻辑结构设计就是把概念结构设计阶段设计好的基本实体-关系图转换为与选用的数据库管理系统产品所支持的数据型相符合的逻辑结构。
    layui是一款采用自身编写的UI框架,遵循原生HTML/CSS/JS的书写与组织形式,并且layui提供了丰富的内置,他们皆可通过的方式按需加载。
    layui框架属于,是一款采用自身编写的UI框架,遵循原生HTML/CSS/JS的书写与组织形式。
    HTTP事务:首先、HTTP事务描述得是一次完整的从请求到响应的过程:用户发起请求时,首先进行域名解析拿到域名所对应的 IP 地址之后,通过 TCP 协议建立与服务的通信连接。

    2021-07-14

    946

    CSS3是CSS技术的升级版本,是朝着发展的版本。以版本的作为一个比较庞大,且比较复杂,这一版本把它分解为一些小的,加入了更多新的
    layui是一款采用自身编写的UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。
    Layui是一款采用自身编写的国产UI框架,本文就来为大家介绍一下使用layui实现分页功能的方法,希望对大家有一定的帮助。
    layui是一款采用自身编写的UI框架,事实上layui更多是面向于后开发者,本文就来为大家介绍一下使用layui实现登录功能的方法。
    layui使用的方法:遵循layui的建立一个入口文件,并通过layui use方法加载该入口文件即可,如【layui.use(['layer'],function(){var layer
    layui是一款采用自身编写的UI框架,本文就来为大家介绍一下Layui连接mysql操作CRUD的方法,希望对大家有一定的帮助。
    Layui是一款采用自身编写的情怀型UI框架,本文就来为大家介绍一下layui中使用的一些弹出框,希望对大家有一定的帮助。
    layui:layui是一款采用自身编写的 UI 框架,遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用,非常适合界面的快速开发。
    区别:AMD和CMD对依赖的执行时机处理不同,AMD推崇依赖置,在定义的时候就要声明其依赖的;CMD推崇就近依赖,只有在用到某个的时候再去require。
    layui是一款采用自身编写的UI框架,遵循原生HTML/CSS/JS的书写与组织形式,本文就来为大家介绍一下layui实现点击按钮添加一行的方法。
    ​layui的首个版本发布于2016年金秋,是一款采用自身编写的UI框架,遵循原生HTML/CSS/JS的书写与组织形式;layui兼容人类正在使用的全部浏览器,可作为PC后台系统与台界面的速成开发方案
    layui是一款采用自身编写的UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。本文就来为大家介绍一下layui中动态设置checkbox选中状态的方法。