对CommonJS,AMD,CMD规范以及script标签异步加载的理解

ES6模块和CommonJS规范区别,以及AMD CMD,import按需加载 暴露 ES6模块和CommonJS规范区别 ①CommonJS支持动态导入,ES6不支持,是静态编译。②CommonJS同步加载,用于服务端,文件放在本地磁盘,读取速度快。同步导入卡住主线程也并无影响。ES6是异步加载,用于浏览器端,不能同步加载,会导致页面渲染,用户体验差。③CommonJS模块输出的是值拷贝,内部的变化影响不到值的变化。ES6模块输出的是值引用,原始值变化,加载的值也会跟着变化,ES6模块是动态引用,并且不会缓存值。④CommonJS模块是运行时加载,ES6模块是编译时输出接口。CommonJ 阅读详情
1.牢骚

CommonJS, AMD, CMD , 其实很早就接触过了。
当时, 网上的文章看得眼花缭乱, 只依稀记得几个模糊的概念。
什么依赖前置 , 什么按需加载。
一头雾水。

现在再回过头来看看概念 , 网上部分文章用词模棱两可。
给我们这些菜鸡, 带来了理解的偏差和困惑。
记得第一个项目还用了requireJS 。
时过境迁,现在入门前端 , 都是直接上webpack了 。
但我觉得还是有必要理一理 。


2. 是什么

CommonJS, AMD, CMD是规范, 理念 ;

  • 对 CommonJS 的实现 , 有 node 的模块系统 ;
  • 对 AMD 的实现有require.js ;
  • 而 CMD, 是在sea.js的实现中提出来的 (但是在Google和Stack Overflow, 这个概念很少被提到, 一般出现在国内)。

  • CommonJS规范, 模块加载是同步的
    对node来说,模块存放在本地硬盘,同步加载,等待时间就是硬盘的读取时间,这个时间非常短;

  • AMD、CMD 规范,模块加载是异步的
    目的, 是为了适应浏览器环境,加载的时间取决于网络的好坏,可能要等很长时间;


3. 先说 async 和 defer

记得看文章的时候, 看到了下面这段话 ,
在这里插入图片描述
我看了半天, 总觉得不是很理解 , 为什么呢 ?
这里说, 脚本标签天生是异步的 , 那为什么会出现 async 和 defer ?
然后, 我发觉我并没有把 加载和执行的概念区分清楚 , 这里的加载我把它理解为浏览器中的下载
这里贴一张图就很清楚了:
defer和async

  • <script> 标签, 在下载和执行的时候 , 会阻塞dom的渲染进程 , 所以如果把<script> 标签放在<head>中, 当 js 文件很大或者网络差时, 会导致页面长时间空白( 顺带提一下, <script>标签并不会阻止其他的<script>标签的下载, 现代浏览器中多个<script>下载是并行的, 在chrome中, 默认支持6个资源(http1.x)并行下载 ), 另外 , 脚本是按照<script>标签的书写顺序执行的 ;
  • <script defer> 在加上defer以后, 下载的过程就不会阻塞dom渲染了, 但脚本的执行是在dom渲染完毕之后;
  • <script async>在加上async以后, 下载的过程同样不会阻塞dom渲染, 但脚本会在下载完后立刻执行, 所以存在多个<script async>时, 无法保证多个js文件的执行顺序, 加载较快的脚本会执行;

所以defer, async主要作用于加载阶段, 执行阶段仍然会阻塞dom渲染


4. 再看 require.js 的异步体现

再看看使用require.js的模块写法
新建 main.js / a.js / b.js , main.js 为入口, 引用了a.js , b.js

	// main.js
	// waitSeconds = 0的配置, 是为了防止文件过大或网络不佳时, 加载时间过长导致require报`Load timeout for modules`的错误 
	require.config({
   		 waitSeconds: 0
  	});
	require(['a.js', 'b.js'], function(a, b){
		// handle / use a, b
		console.log(a)
		console.log(b)
	})
	
	// a.js   ------------------------------
	define([], function(){
		return {
			a: 111111111111
		}
	})
	
	// b.js   ------------------------------
	define([], function(){
		return {
			b: 222222222222
		}
	})
	
  • 文件 开始下载 的 顺序: main, a, b
    为什么文件下载的顺序是 main, a, b 呢? main依赖了 a b, 不是 a b 先下载吗? 那是因为,只有 main 加载之后,才知道mian依赖了啥啊
  • 执行的 顺序 : a, b, main 或者 b, a, main
    这里体现 require.js 的异步加载。 a 和 b 的加载或者说下载是并行的, 但 a 和 b 的执行顺序不确定的 , a 和 b 先执行哪一个都无所谓 ,只需要保证回调函数在 a 和 b 都执行完之后再执行就可以了;

在require.js中模块加载是怎么实现的呢?
看一下require.js的源码:

    /**
     * Creates the node for the load command. Only used in browser envs.
     */
    req.createNode = function (config, moduleName, url) {
        var node = config.xhtml ?
                document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
                document.createElement('script');
        node.type = config.scriptType || 'text/javascript';
        node.charset = 'utf-8';
        node.async = true;   
        return node;
    };

这段代码, 新建了script标签, 并把它的 async设置为true ,

另外, 前面说 , 依赖的模块都执行完之后, 才会执行回调函数。 那怎么判断是否 所有依赖的模块 都已经执行完 ?
多个模块的情况 , 还没看懂(捂脸) , 但是单个模块的执行状态是可以监听的:

	...
	...
	...
        //mentioned above about not doing the 'script execute,
        //then fire the script load event listener before execute
        //next script' that other browsers do.
        //Best hope: IE10 fixes the issues,
        //and then destroys all installs of IE 6-9.
        //node.attachEvent('onerror', context.onScriptError);
    } else {
        node.addEventListener('load', context.onScriptLoad, false);
        node.addEventListener('error', context.onScriptError, false);
    }
    node.src = url;
    ...
    ...

上面的代码可以看到, 通过 <script>标签的onload事件可以判断, 该脚本是否执行完毕 ;

所以, 个人理解, require.js的异步
第一, 是指下载的异步,
第二, 还指回调机制, 依赖模块执行完之后再执行回调函数

5. AMD 和 CMD 的理解误区

现在 再来看 AMD 和 CMD 的区别, 网上的说法:

  1. AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
  2. CMD推崇就近依赖,只有在用到某个模块的时候再去require

第二点 只有在用到某个模块的时候再去require, 这种说其实是带有误导性的,
看看sea.js的写法:

	define(function(require, exports, module) {  
		console.log(123) 
	    var a = require('a.js')
	    console.log(a)
	    var b = require('b.js')
	    console.log(b)
	})

这里, 难道是执行到require, 才去加载/下载require的文件吗 ?
当然不是 ! 看一下sea.js的代码:

	window.define = function(callback) {
    	var id = getCurrentJs()
    	var depsInit = s.parseDependencies(callback.toString())
    	var a = depsInit.map(item => basepath + item)
    ....

sea.js把callback回调函数用转换成字符串, 再找出有哪些依赖, 这些依赖模块同样是预先加载的 ,
不同在于, require.js会立刻执行依赖模块, 而sea.js 在遇到 require 语句的时候 , 再执行依赖模块;

5. 总结

AMD和CMD最大的区别是: 对依赖模块的执行时机处理不同(注意不是加载的时机)
很多人说, requireJS是异步加载模块,SeaJS是同步加载模块,这么说实际上是不准确的 ;
二者加载模块都是异步的 ;
只不过AMD依赖前置,可以方便知道依赖了哪些模块,然后马上加载 , 在加载完成后, 就会执行该模块;
而CMD推崇就近依赖,把模块变为字符串解析一遍, 找到依赖了哪些模块, 在加载模块完成后, 不立刻执行, 而是等到require后再执行;
上面只说了异步相关的概念, 其实 require.js / sea.js , 最重要的还是模块化。
模块化降低耦合,依赖清晰,让调试, 加功能, 任务分配和交接都更方便。

带你全面理解JS模块的标准(AMD、CMD、COMMON.JS 、 UMD、ESM) 在前端的世界演变里,有着几种JS的模块规范,从出现的序言来说就是: ①amd ②cmd ③common.js ④ umd ⑤ esm 现在Vue框架里面都是遵守esm规范,不得不说esm是目前最好最流行的一种js规范了 amd - 浏览器中的js模块化解决方案 AMD 全称是 Async Module Definition -中文: 异步模块化定 义 require.js是AMD模块规范的一个具体实现 核心是通过define方法对无序的代码进行有序的模块化定义,通过require方法实现代码的模块化加 阅读详情

相关推荐

amd规范转commonjs规范

目的是在项目框架中安装外部组件时,组件的规范能够统一。由于早期开发未整体文档,细节已记不太清,先把代码地址贴上来:https://github.com/tianmiyingzi/feather2-command-install需要了解的知识点:AMD规范,CMD规范,Comonjs规范,UMD规范等。以下是调研知识点笔记:Javascript模块化编程问:为什么要模块化?答:提高代码重复利用率。问...

panying0903的专栏 1322

AMD规范、CMD规范、CommonJS

一、AMD规范 AMD规范,全称是Asynchronous Module Definition,即异步模块加载机制。完整描述了模块的定义,依赖关系,引用关系以及加载机制。 AMD的核心是预加载,先对依赖的全部文件进行加载,加载完了再进行处理。 实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出 优点: 适合在浏览器环境中异步加载模块。可以并行加载多个模块。 缺点: 提高了开发成本,并且不能按需加载,而是必须提前加载所有的依赖。 RequireJS主要解决了两...

zyz00000000的博客 2585

使用MeshLab高效对齐3D模型:从OBJ导入到坐标修正全流程

本文详细介绍了使用MeshLab高效对齐3D模型的全流程,涵盖从OBJ导入、坐标修正到最终导出的核心步骤。通过将模型中心归位至坐标原点,并利用主轴对齐功能快速摆正模型,为后续的3D打印、体素化等处理奠定精确的几何基础。

weixin_29313423的博客 93

前端小白如何快速上手Vue框架(上篇)

前言: 我之前没有接触过任何前端知识,连基本的HTML语法,css,js的基础知识都不懂,再刚接手vue的时候也是一个头两个大. 然后当然先查vue官方文档,官网会有如下提示: 然后如果你按照提示开始按部就班的看html,css,js然后再回来学习Vue的话,你可能已经被OUT了(况且周期过长,着实不推荐).直接着手一个项目是进步最快的方式,何况还有度娘和Google保驾护航. 推荐vue学习文...

Logbook的博客 15万+

算法竞赛推荐书单

前言 入坑算法竞赛已经一年半了,在这期间也读了不少关于算法竞赛的书,这些书对我的帮助还是蛮大的。平时看题解多是个人零散的题解,很难以系统的去学习,认认真真的挑选1-2本书来阅读,无论是从思维能力还是文字表达能力都会得到提升,以下都是我自己读过的书进行一下分享,难度由浅入深,部分书籍浅尝而止。 入门:《啊哈!算法》 适合:总题量150以下初步掌握C语言的萌新 一本充满智慧和趣味的算法入门书。没有枯燥的描述,没有难懂的公式,一切以实际应用为出发点,通过幽默的语言配以可爱的插图来讲解算法。你更像是在阅读一个个轻松

TGX的博客 8244

coze开发-5、给智能体添加“技能”

中间编排与技能组件 中间编排的定义 中间编排是指在智能体的构建过程中,使用一些工具对智能体进行协调和管理。通过这些工具,我们能够更好地实现智能体在特定业务场景中的应用。

andyyah晓波的博客 527

手写CMD规范的异步加载机制(seaJs)

实现完上文的AMC规范 异步加载机制后, https://blog.youkuaiyun.com/weixin_38407447/article/details/117407660 这里实现一下CMD 规范的 异步加载机制 同样 需要 用到 这篇文章实现 的 模块加载器 __load https://blog.youkuaiyun.com/weixin_38407447/article/details/117402939?spm=1001.2014.3001.5501 新建cmd.js gb.sj = {} .

能 526

DDR内存设计必看:DFI接口协议详解与实战避坑指南(附时序图解析)

本文深入解析了DDR内存设计中连接内存控制器与物理层的DFI接口协议,聚焦于DDR4/DDR5设计的实际痛点。文章详细阐述了协议版本兼容性、时钟架构(匹配频率与频率比系统)、PCB信号完整性设计以及上电初始化与调试等关键环节,为硬件工程师提供了一套从理论到实战的完整避坑指南,并附有时序图解析以助理解。

weixin_29256771的博客 331

MVC和MVVM区别

1、MVC MVC是一种设计模式: M(Model):模型层。是应用程序中用于处理应用程序数据逻辑的部分,模型对象负责在数据库中存取数据; V(View):视图层。是应用程序中处理数据显示的部分,视图是依据模型数据创建的; C(Controller):控制层。是应用程序中处理用户交互的部分,控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。 2、MVVM vue框

qq_40007317的博客 1万+

Oracle19c-集群节点重新添加

Oracle RAC集群在极端情况下,如硬件、主机,集群软件损坏,导致集群节点永久无法使用,需要对集群节点进行修复,删除节点集群信息并重新加入集群,以恢复集群原有的架构。 本文主要讲述一套两节点的Oracle19c RAC集群,节点一orcl01由于主机异常无法正常启动,在对主机进行重装之后,需要将orcl01节点重新加入集群的操作步骤。环境信息: 操作系统:Linux 7 RAC集群:19C 主机节点:orcl0...

sinat_36757755的博客 2352

银河麒麟V10离线安装VLC播放器:依赖处理与3.0.9.2版本实操指南

在国产化操作系统日益普及的背景下,软件安装方式成为政企内网用户关注的重点。离线安装作为一种不依赖公网源的部署手段,常用于解决内网环境下的软件获取问题。其核心在于理解Linux包管理机制,如dpkg与apt对依赖关系的处理逻辑。掌握这一原理,不仅能应对多媒体软件的部署,也能提升系统维护效率。VLC作为跨平台多媒体播放器,凭借强大的解码能力与协议支持,广泛应用于本地视频播放、RTSP拉流及监控大屏等场景。本文从离线安装的通用概念出发,结合银河麒麟V10桌面版的实际环境,详细梳理了VLC 3.0.9.2离线包的获

weixin_32247165的博客 370

AMD、CMD规范详解

AMD规范 1.1什么是AMD规范 Asynchronous Module Definition,用白话文讲就是 异步模块定义,对于 JSer 来说,异步是再也熟悉不过的词了,所有的模块将被异步加载,模块加载不影响后面语句运行。所有依赖某些模块的语句均放置在回调函数中。 1.1.2AMD规范是怎么出来的 是 RequireJS 在推广过程中对模块定义的规范化产出的 1.2用法 AMD规范定义了一个自由变量或者说是全局变量 define 的函数。 define( id?, dependencies?, fac

minimorezhd的博客 1752

ThingsBoard PE专业版解决方案技术文档——温度&湿度

温湿度解决方案

weixin_67440240的博客 819

前端模块化——CommonJS、AMD、CMD、ES6规范

前言        随着技术的发展,各种前端库层出不穷,前端代码日益膨胀。如果不对前端代码加以模块化规范去管理,维护将变得异常困难。本文的主要内容是理解什么是模块化、为什么要模块化、模块化的优缺点以及当下最流行的AMD、CMD、CommonJS、ES6规范。本文旨在用通俗易懂的语言介绍抽象的概念,希望对大家有所帮助。 什么是模块...

五撸超人的博客 2223

VTK:vtkAssembly用法实战

VTK:vtkAssembly用法实战程序输出程序完整源代码 程序输出 程序完整源代码 #include <vtkActor.h> #include <vtkAssembly.h> #include <vtkAxesActor.h> #include <vtkCubeSource.h> #include <vtkNamedColors.h> #include <vtkNew.h> #include <vtkOrientation

希望我的博客,能帮上你解决学习中工作中所遇到的问题 936

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

CommonJS,AMD和CMD规范的区别

1、CommonJS          CommonJS 是javascript模块化编程的一种规范,主要是在服务器端模块化的规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性。         在CommonJS中有一个全局性方法require( ),用于加载模块。CommonJS 加载模块是同步

明天回火星 2680

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

前端模块化CommonJS、AMD、CMD、ES6

一、前端模块化 什么是模块化?为什么前端需要模块化? js代码量激增,放在同一个文件里面,不容易维护,而且牵一发而动全身。 这时候就需要将代码按照逻辑放在不同的文件里面,按照一定的语法规则,遵循特定的规范将一个庞大的文件拆分若干个相互依赖的文件。这些文件对外暴露数据或接口,在需要的时候导入引用。这就是前端模块化。 说的很官方,举个简单的栗子来通俗的理解。就像是社会的分工合作,彼此依赖,彼此独立,每个社会的部门可以理解为一个模块,按照某种规则负责特定的功能,组装起来形成一个整体,从而完成整个社会系统所要求的

weixin_45709829的博客 2069

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

AMD,CMD,CommonJs到底是何方神圣?以及三者之间的区别

这篇短文写的挺清晰。 知道JS有模块化开发的说法,也偶尔听过requireJs,AMD,CMD等等名字,甚至使用node的时候,还用过require之类的方法,但是对这些一直没有一个明确的认识和概念。想必这就是许多新手刚接触这方面知识时的一个普遍状态。 其实仅仅做一些基础的活儿的时候,并不需要对它们有太多的了解,知道怎么用就行了,管他是什么理念,是什么实现呢。于是人就懒下来了。 终于有一天,下定决心,一定要把这一块知识搞清楚,至少对此有个鲜明的认知,不再那么朦朦胧胧,A/C不分。 查了一些文章博客和知乎回答

weixin_43597801的博客 2742

JS模块化规范:AMD/CMD/CommonJS

一、模块化规范的由来随着网页的复杂化,javascript代码也相应变得庞大起来,代码之间的分工合作就尤为重要了,这时候有了模块,我们就可以只关注自己业务的核心逻辑,其他想要实现的功能直接加载他人的模块便足够了。考虑到模块的统一,便有了模块规范化。接下来介绍的模块化规范,包含:CommonJS,AMD,CMD。 二、三者的区别 AMD CMD CommonJS 预先加载 延迟加载

Horzen的博客 1305

AMD , CMD , CommonJs 和 ES6 对比

1.CommonJS 1.1 基本概念 为JS的表现来制定规范,因为js没有模块的功能所以CommonJS应运而生,它希望js可以在任何地方运行,不只是浏览器中。 同步 CommonJS规范 通过model.exports定义的,在前端浏览器中并不支持 NodeJS是CommonJS规范的实现,webpack 也是以CommonJS的形式来书写的。 CommonJS定义的模块分为: ...

小毛驴的博客 2730

理解CommonJS、AMD、CMD三种规范

理解CommonJS、AMD、CMD三种规范 这三个规范都是为Js模块化加载而生的,使模块能够按需加载,使系统同庞杂的代码得到组织和管理。模块化的管理代码使多人开发得到了更好的合作。 一、CommonJS 是一种为JS的表现指定的规范,它希望js可以运行在任何地方,更多的说的是==服务端模块规范,同步加载模块==,N...

MichaelAn的博客 191

说说AMD、CMD、commonJS模块化规范的区别

在 CommonJs 的模块化规范中,每一个文件就是一个模块,拥有自己独立的作用域、变量、以及方法等,对其他的模块都不可见。项目是由多个模块组成的,模块和模块之间的调用,需要各个模块有相同规范的 API,这样一来在使用的过程中不会有那么多的学习成本,并且对于单个模块来说是类聚的。AMD,CMD,CommonJs是JS模块化开发的标准,目前对应的实现是RequireJs,SeaJs,nodeJs.CMD优点:因为只有在使用的时候才会解析执行js文件,因此,每个JS文件的执行顺序在代码中是有体现的,是可控的。

m0_60676278的博客 404

对CommonJs和AMD,CMD的理解,AMD和CMD的区别,CommonJS与ES6的module的区别

对CommonJs和AMD,CMD的理解是为了使js代码模块化的规范,以前的时候如果一个js模块调用另一个模块,需要在html中进行link,而且必须有严格的引入顺序,但是这样又有可能造成阻塞,使页面失去响应。 CommonJS规定一个文件是一个模块,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,

qq1024884152的博客 1204

前端模块规范AMD/UMD/CommonJs

.babelrc文件中的:module设置为false,为什么会要设置成false? 解释:使ES6模块语法转换到另一个模块类型(默认启用“commonjs”)。 设置为假则不变换模块。或者传入(“amd”、“umd”,“systemjs”、“commonjs”)。 什么是模块? Javascript的组件生态在最近几年的发展很给力,我们的可选性更加广泛了。这本是一件好事,但是当多个第三方Javascript在一起混合使用的时候,我们可能会遇到一个很尴尬的问题,那就是不是所有的组件都能在一

若末lan的博客 2067

说说你对模块化的理解(CommonJS、AMD、CMD、ES Module)

记录js模块化规范理解

weixin_45313351的博客 1052

Javascript模块规范(CommonJS、AMD、CMD、ESM)

​CommonJS node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。 var math = require('math'); math.add(2,3); // 5 CommonJS的特点 所有代码都运行在模块作用域,不会污染全局作用域; 模块是同步加载的,即只有加载完成,才能执行后面的操作; 模块在首次执行后就会缓存,再次加载只返回缓存结果,如

halations的博客 1249
上一篇: Javascript中创建对象的几种方式
下一篇: instanceof 原理和简单实现
飞驰的地铁
博客等级 码龄11年 13粉丝 64原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值