模块包和commonjs,模块包和库
更新:2022-11-19 02:10
本文目录一览:
- ECMAScript 6 的模块相比 CommonJS 的 有什么优点
- ES6 模块与 CommonJS 模块的差异
- react+webpack 模块化应该采用CommonJS规范还是ES6规范,为什么
- CMD 规范是不是就是 commonJS 规范
- 如何让模块支持AMD/CMD和commonjs标准
- webpack打包原理
ECMAScript 6 的模块相比 CommonJS 的 有什么优点
ECMAScript 6 很多新功能都是毁誉参半,其中添加的一个新功能「模块 Module」也一样,有人认为 Module 可以帮助我们更好地写代码,也有人认为这增加了 Javascript 的复杂度,大多数人其实并不需要它。 到底是好是坏,这里不去辩别。但目前 Module 的语法已经定下来了,我们可以来探索下它。
ES6 模块与 CommonJS 模块的差异
讨论 Node.js 加载 ES6 模块之前,必须了解 ES6 模块与 CommonJS 模块完全不同。
它们有三个重大差异。
第二个差异是因为 CommonJS 加载的是一个对象(即module.exports
属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
下面重点解释第一个差异。
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。请看下面这个模块文件lib.js
的例子。
上面代码输出内部变量counter
和改写这个变量的内部方法incCounter
。然后,在main.js
里面加载这个模块。
上面代码说明,lib.js
模块加载以后,它的内部变化就影响不到输出的mod.counter
了。这是因为mod.counter
是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值。
上面代码中,输出的counter
属性实际上是一个取值器函数。现在再执行main.js
,就可以正确读取内部变量counter
的变动了。
上面代码说明,ES6 模块输入的变量counter
是活的,完全反应其所在模块lib.js
内部的变化。
再举一个出现在export
一节中的例子。
上面代码中,m1.js
的变量foo
,在刚加载时等于bar
,过了 500 毫秒,又变为等于baz
。
让我们看看,m2.js
能否正确读取这个变化。
上面代码表明,ES6 模块不会缓存运行结果,而是动态地去被加载的模块取值,并且变量总是绑定其所在的模块。
由于 ES6 输入的模块变量,只是一个“符号连接”,所以这个变量是只读的,对它进行重新赋值会报错。
上面代码中,main.js
从lib.js
输入变量obj
,可以对obj
添加属性,但是重新赋值就会报错。因为变量obj
指向的地址是只读的,不能重新赋值,这就好比main.js
创造了一个名为obj
的const
变量。
最后,export
通过接口,输出的是同一个值。不同的脚本加载这个接口,得到的都是同样的实例。
上面的脚本mod.js
,输出的是一个C
的实例。不同的脚本加载这个模块,得到的都是同一个实例。
现在执行main.js
,输出的是1
。
这就证明了x.js
和y.js
加载的都是C
的同一个实例。
react+webpack 模块化应该采用CommonJS规范还是ES6规范,为什么
研究react的时候也考虑过这个问题,首先可以先了解下这两种模块的机制。参考这里 要考虑的点:
- 目前Commonjs是nodejs(浏览器环境需要模块加载器)原生支持的,而es6需要借助babeljs来实现。意味着如果要实现自动编译上线(我司没有在线上安装node_modules做法)可能需要将babel之类的node_modules提交代码仓库,大概45M。
- 还有要考虑下你选择的react的组件库是基于es6还是Commonjs。如果你业务使用Commonjs规范,组件使用es6,这个就没法统一了。
- 考虑下团队对es6的熟悉程度,关系到代码质量和维护成本。 暂时就想到这些。
CMD 规范是不是就是 commonJS 规范
CMD是国内玉伯大神在开发SeaJS的时候提出来的,属于CommonJS的一种规范,此外还有AMD,其对于的框架是RequireJS
- 二者都是异步模块定义(Asynchronuous Module Definition)的一个实现;
- CMD和AMD都是CommonJS的一种规范的实现,RequireJS和SeaJS是对应的实践;
- CMD和AMD的区别:CMD相当于按需加载,定义一个模块的时候不需要立即制定依赖模块,在需要的时候require就可以了,比较方便;而AMD则相反,定义模块的时候需要制定依赖模块,并以形参的方式引入factory中。 区别看下边例子:
// AMD方式定义模块
define(['dep1','dep2'], function(dep1, dep2) {
// 内部只能使用制定的模块
return function(){};
});
// CMD
define(function(require, exports, module) {
// 此处如果需要某XX模块,可以引入
var xx = require('XX');
});
- JavaScript语言是弱结构性的,通过CommonJS定义一些规范,CMD和AMD得定义模块的方式对代码进行管理,使得更易维护;此外,NodeJS的诞生,对模块的规范定义,和包(npm)的概念的引入,让JS管理不再困难,一个字,爽爆了!
如何让模块支持AMD/CMD和commonjs标准
CommonJS是服务器端模块的规范,Node.js采用了这个规范。 根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require
方法,该方法读取一个文件并执行,最后返回文件内部的exports
对象。下面就是一个简单的模块文件example.js
。
webpack打包原理
webpack打包原理是根据文件间的依赖关系对其进行静态分析,然后将这些模块按指定规则生成静态资源,当 webpack 处理程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
webpack有两种组织模块的依赖方式,同步、异步。异步依赖将作为分割点,形成一个新的块;在优化了依赖树之后,每一个异步区块都将作为一个文件被打包。
webpack有一个智能解析器,几乎可以处理任何第三方库。无论它们的模块形式是CommonJS、AMD还是普通的JS文件;甚至在加载依赖的时候,允许使用动态表require("、/templates/"+name+"、jade")
。
扩展资料
在使用webpack构建的典型应用程序或站点中,有三种主要的代码类型:
- 团队编写的源码。
- 源码会依赖的任何第三方的library或"vendor"代码。
- webpack的runtime和manifest,管理所有模块的交互。 runtime 包含:在模块交互时,连接模块所需的加载和解析逻辑;包括浏览器中的已加载模块的连接,以及懒加载模块的执行逻辑。