>

前端模块化,Js模块化方案计算

- 编辑:www.bifa688.com -

前端模块化,Js模块化方案计算

CommonJS 模块输出的是值的正片,约等于说,一旦输出三个值,模块内部的生成就影响不到那么些值。

也足以借助取值函数(getter),将counter转为援引类型值,效果如下。

时间: 2019-11-20阅读: 251标签: 模块化

ES6 在语言专门的学业的范围上,达成了模块成效,况且贯彻得一定简单,意在成为浏览器和服务器通用的模块施工方案。其模块功用首要由多少个指令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入任何模块提供的功力。

在b.js之中,a.js未有实行完结,只实行了第一行main.js施行到第二行时,不会再一次实行b.js,而是输出缓存的b.js的推行结果,即它的第四行。

// 加载完成后将模块赋值给一个指定变量(默认值){ libraryTarget: 'var', ...}// 赋值为指定对象的一个属性,比如 `this` 或者 `window`{ libraryTarget: "this", // libraryTarget: "window", ...}// 同样的,若是指定 commonjs,那么便可以将模块分配给 exports,这也意味着可以用于 CommonJS 环境:{ libraryTarget: "commonjs", ...}

四、ES6 Module

define(function(require, exports) { exports.each = function (arr) { // 实现代码 }; exports.log = function (str) { // 实现代码 };});
  1. CMD

五、 ES6 模块与 CommonJS 模块的差别1. CommonJS 模块输出的是八个值的正片,ES6 模块输出的是值的援引。

ES6 模块是编写翻译时输出接口,因而犹如下2个特征

module.exports = { output: { // webpack 如何输出结果的相关选项 path: path.resolve(__dirname, "dist"), filename: 'index.js', library: 'hijiangtao', umdNamedDefine: true, libraryTarget: 'umd', },}

CMD是另一种js模块化方案,它与AMD相当帅似,分歧点在于:英特尔发扬重视前置、提前施行,CMD发扬注重就近、延迟实施。此标准其实是在sea.js推广进程中发出的。

//b.jsexports.done = false;var a = require('./a.js');console.log('在 b.js 之中,a.done = %j', a.done);exports.done = true;console.log('b.js 执行完毕');

正文包罗两局地,首盘部通过明显的陈诉介绍如何是 CommonJS、Intel、CMD、UMD、ES Module 以及它们的广阔用法,第二有个别则依据实际难题提出在正规的 webpack 构建过程中该怎样钦定打包配置中的模块化参数。

模块化的开发方式能够增进代码复用率,方便开展代码的治本。平时二个文书正是三个模块,有谈得来的作用域,只向外揭发特定的变量和函数。最近风行的js模块化标准有CommonJS、英特尔、CMD以致ES6的模块系统。参见阮一峰先生的稿子module-loader。

RequireJS基本思忖为,通过二个函数来将全部所需的要么所依赖的模块装载进来,然后重返二个新的函数(模块)。后续全部的关于新模块的事情代码都在此个函数内部操作。

require命令第叁遍加载该脚本时就能够试行总体脚本,然后在内部存款和储蓄器中生成三个指标(模块能够频仍加载,可是在率先次加载时才会运营,结果被缓存),那些结果长成那样:

define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) { // 等于在最前面声明并初始化了要用到的所有模块 if (false) { // 即便没用到某个模块 b,但 b 还是提前执行了 b.foo() } });

上边的代码表明了2点

output中有三特性质叫做libraryTarget,被用来钦定怎样暴光你的模块的性质。你能够如此尝试赋值给一个变量或许钦定对象的个性:

如上例所示,使用import命令的时候,顾客要求知道所要加载的变量名或函数名。其实ES6还提供了export default命令,为模块钦定暗许输出,对应的import语句无需接纳大括号。那也更趋近于ADM的引用写法。

CommonJS是服务器模块的正式,Node.js选取了那几个正式。

define(function(require, exports, module) { var a = require('./a'); a.doSomething(); var b = require('./b'); b.doSomething(); ...})
  1. CommonJS 模块是运作时加载,ES6 模块是编写翻译时输出接口。

CMD规范和AMD相通,都至关心重视要运维于浏览器端,写法上看起来也很相似。主借使分别在于模块伊始化学工业机械遇

必发88官网,JavaScript 模块化方案

三、CMD和sea.js

时刻: 2019-01-31观看: 275标签: 模块模块化开拓优点模块化开采中,平日四个文书就是叁个模块,有本人的功能域,只向外暴光特定的变量和函数,而且能够按需加载。重视自动加载,按需加载。进步代码复用率,方便开展代码的保管,使得代码管理进一层清晰、标准。减少了命名冲突,驱除全局变量。近期风行的js模块化规范有CommonJS、英特尔、CMD以至ES6的模块系统广大模块化标准CommonJs (Node.js卡塔尔国AMD (RequireJS卡塔尔国CMD (SeaJS卡塔尔(قطر‎CommonJS(Node.js卡塔尔

举个例证:

援引模块的时候,大家将模块名放在[]中作为reqiure(卡塔尔(قطر‎的第一参数;如若咱们定义的模块自己也依附其余模块,那就须要将它们放在[]中作为define(卡塔尔(قطر‎的率先参数。

ES6 模块在编写翻译时就能够静态解析,事情发生在此之前于模块内的别样剧情施行,所导招致了我们不大概写出像下边这样的代码

(function (factory) { if (typeof define === 'function'  define.amd) { // AMD. Register as an anonymous module. define(['jquery'], factory); } else if (typeof module === 'object'  module.exports) { // Node/CommonJS module.exports = function( root, jQuery ) { if ( jQuery === undefined ) { // require('jQuery') returns a factory that requires window to // build a jQuery instance, we normalize how we use modules // that require this pattern but the window provided is a noop // if it's defined (how jquery works) if ( typeof window !== 'undefined' ) { jQuery = require('jquery'); } else { jQuery = require('jquery')(root); } } factory(jQuery); return jQuery; }; } else { // Browser globals factory(jQuery); }}(function ($) { $.fn.jqueryPlugin = function () { return true; };}));

Intel标准使用异步方式加载模块,模块的加载不影响它背后语句的运行。全数正视这么些模块的说话,都定义在二个回调函数中,等到加载成功今后,这几个回调函数才会运维。这里介绍用require.js完结AMD规范的模块化:用require.config(卡塔尔国内定援引路线等,用define(卡塔尔(قطر‎定义模块,用require(卡塔尔加载模块。

虽说a模块中import引进晚于console.log('a'State of Qatar,但是它被 JS 引擎通过静态分析,提到模块推行的最前边,优于模块中的别的部分的进行。

通超过实际行该结构方法,能够得到模块向外提供的接口。在与 AMD比较上存在四个第一的分化点(来自玉伯回答):

// 定义math.js模块define(function () { var basicNum = 0; var add = function (x, y) { return x   y; }; return { add: add, basicNum :basicNum };});// 定义一个依赖underscore.js的模块define([‘underscore‘],function(_){ var classify = function(list){ _.countBy(list,function(num){ return num  30 ? ‘old‘ : ‘young‘; }) }; return { classify :classify };})// 引用模块,将模块放在[]内require([‘jquery‘, ‘math‘],function($, math){ var sum = math.add(10,20); $("#sum").html(sum);});

CommonJS中,加载模块使用require方法。该格局读取二个文本并实行,最终回来文件之中的exports对象。

倘使说的不知晓,那么我们直接看上边的代码用 Intel 该怎么写:

/** AMD写法 **/define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) { // 等于在最前面声明并初始化了要用到的所有模块 a.doSomething(); if (false) { // 即便没用到某个模块 b,但 b 还是提前执行了 b.doSomething() } });/** CMD写法 **/define(function(require, exports, module) { var a = require(‘./a‘); //在需要时申明 a.doSomething(); if (false) { var b = require(‘./b‘); b.doSomething(); }});/** sea.js **/// 定义模块 math.jsdefine(function(require, exports, module) { var $ = require(‘jquery.js‘); var add = function(a,b){ return a b; } exports.add = add;});// 加载模块seajs.use([‘math.js‘], function(math){ var sum = math.add(1 2);});
//规范 APIdefine(id?, dependencies?, factory);define.amd = {};// 定义无依赖的模块define({ add: function(x,y){ return x   y; }});// 定义有依赖的模块define(["alpha"], function(alpha){ return { verb: function(){ return alpha.verb()   1; } }});

咱俩见过这么的模块引用:

Node.js是commonJS标准的根本奉行者,它有四个首要的境况变量为模块化的兑现提供支撑:module、exports、require、global。实际运用时,用module.exports定义当前模块对外出口的接口(不推荐直接用exports),用require加载模块。

webpack中加载3种模块 | 语法

CommonJS 模块的特色:

commonJS用一块的办法加载模块。在服务端,模块文件都设有本地球磁性盘,读取一点也超快,所以这么做不会有标题。不过在浏览器端,限于互联网原因,更客观的方案是运用异步加载。

var a = require('./a.js');var b = require('./b.js');console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);

CMD 全称为 Common Module Definition,是 Sea.js 所推广的叁个模块化方案的输出。在 CMD define 的入参中,即便也支撑包蕴 id, deps 以至 factory 多个参数的款型,但推荐的是经受 factory 叁个入参,然后在入参推行时,填入四个参数 require、exports 和 module:

时间: 2019-12-27阅读: 78标签: 模块化

//AMDdefine(['./a','./b'], function (a, b) { //依赖一开始就写好 a.test(); b.test();}); //CMDdefine(function (requie, exports, module) { //依赖可以就近书写 var a = require('./a'); a.test(); ... //软依赖 if (status) { var b = requie('./b'); b.test(); }});

UMD的兑现很简短:

一、CommonJS

$ node main.js在 b.js 之中,a.done = falseb.js 执行完毕在 a.js 之中,b.done = truea.js 执行完毕在 main.js 之中, a.done=true, b.done=true

享有代码都运作在模块成效域,不会传染全局作用域。独立性是模块的首要性特征就,模块内部最佳不与程序的别的界分直接相互作用。模块能够频仍加载,可是只会在第叁回加载时运维一次,然后运转结果就被缓存了,现在再加载,就径直读取缓存结果。要想让模块再次运营,必需杀绝缓存。模块加载的逐一,依据其在代码中冒出的依次。2. 英特尔

编写翻译时加载: ES6 模块不是指标,而是通过export命令显式钦点输出的代码,import时接纳静态命令的花样。即在import时得以钦点加载某些输出值,并不是加载整个模块,这种加载称为“编写翻译时加载”。

Promise.all([ import('./a.js'), import('./b.js'), import('./c.js'),]).then(([a, {default: b}, {c}]) = { console.log('a.js is loaded dynamically'); console.log('b.js is loaded dynamically'); console.log('c.js is loaded dynamically');});
define(id?, dependencies?, factory);

来源:掘金,原链接:

require.ensure的面世是webpack的产品,它是因为浏览器需求一种异步的建制能够用来异步加载模块,进而减弱起头的加载文件的容量,所以只要在服务端的话,require.ensure就英雄无发挥专长了,因为服务端官样文章异步加载模块的情状,模块同步进行加载就足以满足使用景况了。 CommonJS 模块能够在运维时承认模块加载。

一旦须要更完整的模块化 bundle,以有限支撑和各模块系统合营,那么可以那样尝试:

ES6的模块不是目的,import命令会被 JavaScript 引擎静态深入分析,在编写翻译时就引进模块代码,并不是在代码运营时加载,所以不能落到实处标准化加载。也正因为这些,使得静态剖判成为可能。

因为编写翻译时静态解析,招致了咱们束手无策在尺度语句或许拼接字符串模块,因为那一个都以须要在运作时才具分明的结果在 ES6 模块是不被允许的,所以 动态引进import(卡塔尔应时而生。

对此依附的模块,AMD 是提前实行,CMD 是延迟实行。但是 RequireJS 从 2.0 开始,也改成可以推迟推行(依照写法不一样,管理形式分裂)。CMD 发扬 as lazy as possible.CMD 发扬信赖就近,AMD 发扬信任前置。

require.js在表达信赖的模块时会在首先之内加载并施行模块内的代码:

CommonJS标准加载模块是同台的,也正是说,唯有加载成功,才干举行后边的操作。

理所必然,以上说的各类都以社区提供的方案,历史上,JavaScript 一贯未曾模块系统,直到 ES6 在语言专门的学业的局面上,达成了它。其设计理念是硬着头皮的静态化,使得编写翻译时就能够明确模块的注重性关系,以致输入和出口的变量。CommonJS 和 AMD 模块,都必须要在运作时规定那几个事物。比方,CommonJS 模块正是目的,输入时必需寻觅对象属性。而 ES Modules 不是目的,而是通过export命令显式钦命输出的代码。

二、AMD和require.js

ES6模块的运维机制与CommonJS不等同。JS 引擎对台本静态解析时,碰到模块加载命令import,就能够变卦一个只读引用。等到脚本真的实践时,再依赖那个只读援用,到被加载的要命模块里面去取值。ES6 模块中,原始值变了,import加载的值也会随着变。因而,ES6 模块是动态援用,何况不会缓存值。 ——ES6 Module 的加载实现 | 阮一峰

webpack 打包输出配置

ES6 模块的运维机制与 CommonJS 不一样。JS 引擎对剧本静态解析的时候,遭受模块加载命令import,就可以变动二个只读引用。等到脚本真的推行时,再依照那几个只读引用,到被加载的不胜模块里面去取值。换句话说,ES6 的import有一点点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会随之变。因而,ES6 模块是动态引用,何况不会缓存值,模块里面包车型地铁变量绑定其所在的模块。

下边代码中,如若产生循环加载,require('a'State of Qatar.foo的值很可能前面会被改写,改用require('a'State of Qatar会更有限支撑一点。

ES Modules 的模块化才干由export和import组成,export命令用于规定模块的对外接口,import命令用于输入任何模块提供的效果。大家得以这么定义一个模块:

/** export default **///定义输出export default { basicNum, add };//引入import math from ‘./math‘;function test(ele) { ele.textContent = math.add(99   math.basicNum);}

通过exports就能够向外提供接口。通过require('./util.js'卡塔尔国就足以获得util.js中通过exports揭示的接口。这里的require能够以为是Sea.js给 JavaScript 语言增加的二个语法关键字,通过require能够获取此外模块提供的接口。

define(['./a', './b'], function(a, b) { a.doSomething(); b.doSomething(); ...})

首先大家须要引入require.js文件和一个进口文件main.js。main.js中配备require.config(State of Qatar并规定项目中用到的幼功模块。

RequireJS

importthiswindowrequire
/** 定义模块 math.js **/var basicNum = 0;var add = function (a, b) { return a   b;};export { basicNum, add };/** 引用模块 **/import { basicNum, add } from ‘./math‘;function test(ele) { ele.textContent = add(99   basicNum);}
// lib.jsvar counter = 3;function incCounter() { counter  ;}module.exports = { get counter() { return counter }, incCounter: incCounter,};

// main.jsvar mod = require('./lib');console.log(mod.counter); // 3mod.incCounter();console.log(mod.counter); // 4

先判别是还是不是扶助 AMD(define 是不是存在),存在则动用 Intel格局加载模块;再决断是还是不是帮衬 Node.js 模块格式(exports 是不是存在),存在则使用 Node.js 模块格式;前四个都空头支票,则将模块公开到全局(window 或 global);5. ES Modules

运作时加载: CommonJS 模块正是目的;即在输入时是先加载整个模块,生成三个指标,然后再从那么些目标方面读取方法,这种加载称为“运行时加载”。

RequireJS须要种种模块均位居独立的文书之中,并利用define定义模块,使用require方法调用模块。

define({ add: function(x, y){ return x   y; }});

CommonJS 加载的是一个指标(即module.exports属性),该对象独有在剧本运转完才会扭转。而 ES6 模块不是目的,它的对外接口只是一种静态定义,在代码静态解析阶段就可以生成。

ES6 模块ES6模块和CommonJS区别ES6 模块输出的是值的引用,输出接口动态绑定,而CommonJS输出的是值的正片。CommonJS模块是运维时加载,ES6 模块是编写翻译时输出接口。CommonJS 输出值的正片

require(['math'], function (math) { math.add(2, 3);});
/** 网页中引入require.js及main.js **/script src="js/require.js" data-main="js/main"/script/** main.js 入口文件/主模块 **/// 首先用config()指定各模块路径和引用名require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", //实际路径为js/lib/jquery.min.js "underscore": "underscore.min", }});// 执行基本操作require(["jquery","underscore"],function($,_){ // some code here});

AMD (RequireJS卡塔尔国 异步模块定义英特尔=Asynchronous Module Definition,即异步模块定义英特尔标准加载模块是异步的,并允许函数回调,不必等到全部模块都加载成功,后续操作能够寻常实践。AMD中,使用require获取信赖模块,使用exports导出API。

{ id: '...', exports: { ... }, loaded: true, ...}
// 定义模块math.jsvar basicNum = 0;function add(a, b) { return a   b;}module.exports = { //在这里写上需要向外暴露的函数、变量 add: add, basicNum: basicNum}// 引用自定义的模块时,参数包含路径,可省略.jsvar math = require(‘./math‘);math.add(2, 5);// 引用核心模块时,不需要带路径var http = require(‘http‘);(...).listen(3000);
var x = 5;var addX = function(value) { return value   x;};module.exports.x = x;module.exports.addX = addX;// 也可以改写为如下module.exports = { x: x, addX: addX,};

let math = require('./math.js');console.log('math.x',math.x);console.log('math.addX', math.addX(4));
import { firstName, lastName, year } from 'module';import { firstName as newName } from 'module';import * as moduleA from 'module';

在类的内部,基本上能用get和set关键字,对某些属性设置存执函数和取值函数,拦截该属性的存取行为。 ——class | 阮一峰

直接进去正题,大家来寻访平淡无奇的模块化方案都有如何以至他们皆有何内容。

基于大家的急需动态或有条件地加载它们,那使大家能够越来越快,更加好地创建越来越多优势应用程序。

除以上二种命令外,还应该有多少个export default命令用于钦点模块的暗中同意输出(三个模块只好有叁个暗许输出)。要是应用了export default语法,在 import 时则足以随意命名。由于export default命令的本质是将后边的值,赋给default变量,所以也能够一贯将二个值写在export default现在。当然,引用情势也存在种种:

CMD=Common Module Definition,即通用模块定义。CMD是SeaJS在松开进度中对模块定义的规范化产出。

模块化那么些话题在 ES6 以前是不设有的,因而那也被诟病为早先时代 JavaScript 开采全局污染重视管理混乱难题的源流。那类历史渊源和升高概述在本文将不会聊到,由此感兴趣能够活动物检疫索 JavaScript 发展史进行打探。

非独立模块,信任其余模块

UMD,全称 Universal Module Definition,即通用模块标准。既然 CommonJs 和 英特尔风格一模一样流行,那么要求贰个足以统一浏览器端甚至非浏览器端的模块化方案的正规化。

export 命令变量升高效果

var myModule = require('module');myModule.sayHello();

而import(卡塔尔国则差别,它最主借使为着解决 ES6 模块无法在运转时规定模块的援用关系,所以必要引进import(State of Qatar。

// 第一种方式export var firstName = 'Michael';export var lastName = 'Jackson';export var year = 1958;// 第二种方式var firstName = 'Michael';var lastName = 'Jackson';var year = 1958;export { firstName, lastName, year };

双面分别首要表以后模块开始化机会

直接来探视官方给出的 jQuery 模块怎么着用 UMD 定义的代码:

就此,对于b.js来讲,它从a.js只输入一个变量done,值为false。

id:模块名称,大概模块加载器诉求的钦命脚本的名字;dependencies:是个概念中模块所依赖模块的数组,默感觉 [“require”, “exports”, “module”],举例比较好掌握,当大家创立三个名称为 “阿尔法” 的模块,使用了require,exports,和名字为 “beta” 的模块,必要如下书写(示例1);factory:为模块初叶化要奉行的函数或对象。假如为函数,它应该只被施行二次。若是是指标,此指标应当为模块的输出值;

CommonJS 模块的严重性特点是加载时实行,即脚本代码在require的时候,就能够整整实施。一旦现身有个别模块被“循环加载”,就只输出已经试行的局地,还没执行的片段不会输出。

CommonJS 的多个模块正是一个本子文件,通过施行该文件来加载模块。CommonJS 标准规定,每种模块内部,module变量代表当前模块。这一个变量是二个对象,它的 exports 属性(即module.exports)是对外的接口。加载有些模块,其实是加载该模块的module.exports属性。

importMyModulefrom'./MyModule.js';
// 内容分配给 module.exports 对象,用于 CommonJS 环境{ libraryTarget: 'commonjs2', ...}// 暴露为 AMD 模块,通过特定属性引入{ libraryTarget: 'amd', ...}// 所有模块系统兼容的万金油,可以在 CommonJS, AMD 环境下运行,或将模块导出到 global 下的变量{ libraryTarget: 'umd', ...}

先来看下它的用法

var exports = module.exports;

Sea.jsSea.js Github PageSeaJS与RequireJS最大的界别

延长阅读JavaScript 模块的循环加载

if(some condition) { import a from './a';}else { import b from './b';}// or import a from (str   'b');

内需在乎的是 Modules 会自动选用严谨形式,且 import 命令具有进步效果,会升级到任何模块的尾部,首施夷光行。

CommonJS模块是运作时加载,ES6 模块是编写翻译时输出接口。

这是因为我们把模块的诀窍定义在了模块的品质上:

a.js已经奉行的一对,独有一行。

说罢理论,来走访实际项目中遇见的难题。当我们开采完八个 JavaScript 模块必然要阅历打包的流水生产线,而在 webpack 配置中,通过点名 output 选项就足以告知 webpack 如何输出 bundle, asset 以至别的载入的内容。那么怎样落到实处差异条件可配合的构建呢?

define({ method1: function(){}, method2: function(){}});//等价于define(function() { return { method1: function(){}, method2: function(){} }});

Node.js 的模块机制落实正是参照了 CommonJS 的标准。不过 Node.js 额外做了一件事,即为每一种模块提供了一个 exports 变量,以指向 module.exports,这一定于在各样模块最开头,写有这么一行代码:

(function (window, factory) { if (typeof exports === 'object') { module.exports = factory(); } else if (typeof define === 'function'  define.amd) { define(factory); } else { window.eventUtil = factory(); }})(this, function () { //module ...});
// 示例1define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); // 或者 return require("beta").verb(); }});
async function main() { const myModule = await import('./myModule.js'); const {export1, export2} = await import('./myModule.js'); const [module1, module2, module3] = await Promise.all([ import('./module1.js'), import('./module2.js'), import('./module3.js'), ]);}
require([module], callback);

人之常情,假若在浏览器端的import(卡塔尔(قطر‎的用场就能够变得更普遍,比如按需异步加载模块,那么就和require.ensure功用周围了。

  1. UMD

ES6 输出值的援引

import { default as foo } from 'module';import foo from 'module';

譬如说,对于下述util.js代码

倘使模块定义不设有依赖,那么能够直接定义对象:

var org = {};org.CoolSite = {};org.CoolSite.Utils = {};org.CoolSite.Utils.each = function (arr) { // 实现代码};org.CoolSite.Utils.log = function (str) { // 实现代码};
  1. CommonJS

CMD (SeaJS)

// module.jsmodule.exports.sayHello = function() { console.log('Hello ');};// 如果这样写module.exports = sayHello;// 调用则需要改为var sayHello = require('module');sayHello();

Demo 2

故此,如若只看 output 内容,那么本身的一个 webpack 临蓐意况布置能够写成这么:

重复引入有个别相像的模块时,模块只会执行三回。

而接纳时我们如故通过 require 关键字,它含有四个参数,第贰个数组为要加载的模块,第四个参数为回调函数:

CommonJS(Require)

Intel 的模块引进由 define 方法来定义,在 define API 中:

var a = require('a'); // 安全的写法 导入整体,保证module已经执行完成var foo = require('a').foo; // 危险的写法exports.good = function (arg) { return a.foo('good', arg); // 使用的是 a.foo 的最新值};exports.bad = function (arg) { return foo('bad', arg); // 使用的是一个部分加载时的值};

CommonJS 规范很好,然则不适用于浏览器情形,于是有了 AMD 和 CMD 三种方案。英特尔 全称 Asynchronous Module Definition,即异步模块定义。它使用异步格局加载模块,模块的加载不影响它背后语句的运作。全数重视那一个模块的言辞,都定义在叁个回调函数中,等到加载成功以往,这么些回调函数才会运作。除了和 CommonJS 同步加载形式各异之外,AMD 在模块的定义与援用上也迥然不相同。

用法通过exports暴光接口。那意味着没有供给命名空间了,更没有需求全局变量。那是一种深透的命名冲突应用方案。通过require引入重视。那能够让信任内置,开采者只需关切当前模块的依附,其余事情Sea.js都会自动管理好。对模块开拓者来讲,那是一种很好的 关心度分离,能让程序猿越多地饮鸩止渴编码的童趣。通过define定义模块,越来越多详细的情况参见SeasJS | 极客学院。示例

然后再如此引进他们:

// a.jsconst str = './b';const flag = true;if(flag) { import('./b').then(({foo}) = { console.log(foo); })}import(str).then(({foo}) = { console.log(foo);})// b.jsexport const foo = 'foo';// babel-node a.js// 执行结果// foo// foo

异步加载和回调require([module], callback)中callback为模块加载成功后的回调函数

Node.js主要用来服务器编制程序,加载的模块文件平时都曾经存在本地硬盘,加载起来相当的慢,不用思量异步加载的形式,所以CommonJS的一同加载模块标准是相比适用的。

exports.done =false;

Demo 1

但万一是浏览器碰到,要从服务器加载模块,那是就亟须采用异步格局。所以就有了英特尔,CMD等解决方案。

import(卡塔尔(قطر‎允许你在运维时动态地引进 ES6 模块,想到那,你或者也记念了require.ensure这几个语法,不过它们的用项却天地之别的。

// lib.jsexport let counter = 3;export function incCounter() { counter  ;}// main.jsimport { counter, incCounter } from './lib';console.log(counter); // 3incCounter();console.log(counter); // 4

require方法调用模块

counter是基本类型值,模块内部值的成形不影响输出的值变化。obj是援用类型值,模块内部值的转换影响输出的值变化。上述两点分别,类比于基本类型和援用类型的赋值操作。

依照是不是有凭仗别的模块情形,能够分为单身模块非独立模块

UMDUMD=Universal Module Definition,即通用模块定义。UMD是英特尔和CommonJS的混合。英特尔模块以浏览器第一的条件发展,异步加载模块。CommonJS模块以服务器第一准则升高,选拔同步加载。它的模块无需包装(unwrapped modules卡塔尔(قطر‎。那反逼大家又想出另一个更通用的情势UMD(Universal Module Definition卡塔尔国,完成跨平台的缓和方案。UMD先判别是或不是帮衬Node.js的模块(exports)是还是不是留存,存在则应用Node.js模块形式。再决断是还是不是帮助英特尔(define是不是存在),存在则选择英特尔情势加载模块。

循环信赖CommonJS 模块循环正视

但从SeaJS与CMD来说,也做了不菲没有错东西:1、绝对自然的信赖性评释风格 2、小而美的中间落到实处 3、贴心的外部成效设计 4、越来越好的国语社区扶助。

exports.done =true;
//加载 math模块,完成之后执行回调函数require(['math'], function(math) { math.add(2, 3);});

ES6 模块是动态关联模块中的值,输出的是值得引用。原始值变了,import加载的值也会随着变。

define(function(require, exports) { var util = require('./util.js'); exports.init = function() { // 实现代码 };});
//a.jsexports.done = false;var b = require('./b.js');console.log('在 a.js 之中,b.done = %j', b.done);exports.done = true;console.log('a.js 执行完毕');

动态的import(卡塔尔(قطر‎提供三个基于Promise的API动态的import(State of Qatar可以在本子的别的地点使用import(卡塔尔(قطر‎接收字符串文字,能够依附需求组织表达符

a模块引用了b模块,b模块也援引了a模块,export表明的变量也是优化模块其余内容的奉行的。但具体对变量赋值须求等到推行到相应代码的时候。

因为是依据Promise的,所以若是您想要同一时候加载多少个模块的话,可以是Promise.all举办相互影响异步加载。

跟 CommonJS 模块同样,ES6 不会再去施行重复加载的模块,又由于 ES6 动态输出绑定的特性,能保险 ES6 在别的时候都能博取其余模块当前的新型值。

本来,借令你认为那样写还相当不足文雅,也能够构成async/await语法糖来使用。

总之,CommonJS 输入的是被输出值的正片,不是引用。

ES6模块和CommonJS相似点模块不会再也实行

行使Sea.js,在书写文件时,须求遵从CMD(Common Module Definition)模块定义标准。叁个文件正是一个模块。

然后,b.js接着往下进行,等到一切施行实现,再把实践权交还给a.js。于是,a.js接着往下实施,直到推行完结。大家写二个剧本main.js,验证这些进程。

// a.jsimport { foo } from './b';console.log('a.js');export const bar = 1;export const bar2 = () = { console.log('bar2');}export function bar3() { console.log('bar3');}// b.jsexport let foo = 1;import * as a from './a';console.log(a);// 执行结果:// { bar: undefined, bar2: undefined, bar3: [Function: bar3] }// a.js

ES6 模块

AMD

const CDNs = [ { name: 'jQuery.com', url: '-3.1.1.min.js' }, { name: 'googleapis.com', url: '' }];console.log(`------`);console.log(`jQuery is: ${window.jQuery}`);Promise.race([ import(CDNs[0].url).then(()=console.log(CDNs[0].name, 'loaded')), import(CDNs[1].url).then(()=console.log(CDNs[1].name, 'loaded'))]).then(()= { console.log(`jQuery version: ${window.jQuery.fn.jquery}`);});

Webpack允许选取不相同的模块类型,可是底层必需接纳同一种达成。全数的模块能够一贯在盒外运转。

define([ 'module1', 'module2' ], function(m1, m2) { ...});//等价于define(function(require) { var m1 = require('module1'); var m2 = require('module2'); ...});

能够使用SeaJS重写为

英特尔中假如模块作为依据时,就能够加载并开头化CMD中,模块作为依据且被引述时才会初叶化,不然只会加载。CMD弘扬依赖就近,AMD发扬信任前置。英特尔的API暗许是贰个当多少个用,CMD严峻的不一样发扬任务单一。比如,英特尔里require分全局的和部分的。CMD里面未有大局的require,提供seajs.use(卡塔尔国来落实模块系统的加载运转。CMD里每种API都简短纯粹。

// a.jsconsole.log('a.js')import { foo } from './b';// b.jsexport let foo = 1;console.log('b.js 先执行');// 执行结果:// b.js 先执行// a.js

再看b.js的代码。

依附CommonJS标准,贰个单身的文本便是多个模块,每二个模块都以叁个独门的效用域,在一个文本定义的变量(还包括函数和类),都以个体的,对其余文件是不可以预知的。

地点代码之中,b.js施行到第二行,就能够去加载a.js,那时,就发生了“循环加载”。系统会a.js模块对应对象的exports属性取值,然而因为a.js还尚未实践完,从exports属性只好取回已经实践的一对,实际不是最后的值。

动态 import()

在文件中的任何职责引进import模块都会被提前到文件最上部

RequireJS是一个前端模块化管理的工具库,服从Intel规范,RequireJS是对AMD标准的阐述。

varMyModule =require('./MyModule.js');

从业内上来讲,英特尔特别简约且严厉,适用性更广,而在RequireJS强力的推动下,在国外大致成了实际的异步模块标准,各大类库也逐个辅助英特尔标准。

// lib.jsvar counter = 3;var obj = { name: 'David'};function changeValue() { counter  ; obj.name = 'Peter';};module.exports = { counter: counter, obj: obj, changeValue: changeValue,};

// main.jsvar mod = require('./lib');console.log(mod.counter); // 3console.log(mod.obj.name); // 'David'mod.changeValue();console.log(mod.counter); // 3console.log(mod.obj.name); // 'Peter'// Orconsole.log(require('./lib').counter); // 3console.log(require('./lib').obj.name); // 'Peter'
// a.jsconsole.log('a starting');exports.done = false;const b = require('./b');console.log('in a, b.done =', b.done);exports.done = true;console.log('a done');// b.jsconsole.log('b starting');exports.done = false;const a = require('./a');console.log('in b, a.done =', a.done);exports.done = true;console.log('b done');// node a.js// 执行结果:// a starting// b starting// in b, a.done = false// b done// in a, b.done = true// a done

从地点的推行进度中,能够看看,在 CommonJS 标准中,当遭逢require(卡塔尔国语句时,会履行require模块中的代码,并缓存实践的结果,当下一次重新加载时不会重新实施,而是直接取缓存的结果。正因为此,现身循环重视时才不会现身非常循环调用的景况。

require(['foo', 'bar'], function(foo, bar) { foo.func(); bar.func();});

试行main.js,运营结果如下。

独立模块,不借助于别的模块,直接定义

那是因为,CommonJS加载的是一个目的(即module.exports属性),该对象唯有在剧本运营完才会变动。而ES6模块不是指标,它的对外接口只是一种静态定义,在代码静态解析阶段就能变动。

define(['./MyModule.js'], function (MyModule) {});

ES6 模块循环信任

CommonJS 模块输出的是值的正片(类比于基本项目和引用类型的赋值操作)。对于大旨类型,一旦输出,模块内部的变化影响不到那几个值。对于援引类型,效果同援用类型的赋值操作。

由于import和export是静态实行,所以import和export具备变量提高成效。即import和export命令在模块中的地点并不影响程序的出口。

动态import(卡塔尔为大家提供了以异步方式接受 ES 模块的附加效率。

其他,由于 CommonJS 模块碰着循环加载时,再次来到的是现阶段早就实行的片段的值,实际不是代码全体执行后的值,两个只怕会有出入。所以,输入变量的时候,必需丰裕小心。

再有Promise.race方法,它检查哪个Promise被第一resolved或reject。我们可以运用import(卡塔尔(قطر‎来检查哪个CDN速度越来越快:

英特尔(RequireJS)中一经模块作为依赖时,就能加载并开首化。即尽早地推行(信任)模块。约等于全部的require都被提前了,而且模块奉行的逐一也不肯定百分之百就是require书写顺序。CMD(SeaJS)中,模块作为依据且被引述时才会初阶化,不然只会加载。即只会在模块真正需求接纳的时候才伊始化。模块加载的相继是从严坚决守住require书写的相继。

import命令会被 JS 引擎静态解析,优先于模块内的别样剧情推行export命令会有变量注脚进步的功能import 优先实施

CommonJS 运转时加载 ES6静态编写翻译

SeaJS与RequireJS区别

上面代码之中,a.js脚本先输出三个done变量,然后加载另一个本子文件b.js。注意,那时a.js代码就停在此,等待b.js实践完结,再往下实行。

本文由必发88官网发布,转载请注明来源:前端模块化,Js模块化方案计算