基于JS模块化现状谈谈选择ES6模块的原因
2016-09-29 13:40
621 查看
基于JS模块化现状谈谈选择ES6模块的原因
本文转载自:众成翻译译者:旭日云中竹
链接:http://www.zcfy.cc/article/1010
原文:http://blog.js-republic.com/start-of-art-of-javascript-modularization-why-choose-es2015/
这篇文章,我们将了解为什么JS社区有必要选择ES6模块。
现状
要明白这种重要性,首先我们需要描述一下JS的实际情况。过去5年,JavaScript 发展得非常迅猛,大多数开发人员几乎没意识到当前已经有5种方式,可以为 JavaScript 脚本和应用创建模块了!
原始的 IIFE () : 这是最古老,也是比较简单的创建 JS 模块的方法了。以下是用
IIFE实现的简单模块化示例:
const myModule = (function (...deps){ // JavaScript chunk return {hello : () => console.log(‘hello from myModule’)}; })(dependencies);
相信大家对这段代码都不陌生,它只是把变量和方法都封装在本身作用域内的一种普通模式。其存在的缺点就是没有帮我们处理依赖。
AMD (异步模块依赖) : Require.js 很受欢迎,它可以给模块注入依赖,还允许动态地加载 JS 块。
<pre>define(‘myModule’, [‘dep1’, ‘dep2’], function (dep1, dep2){ // JavaScript chunk, with a potential deferred loading return {hello: () => console.log(‘hello from myModule’)}; }); // anywhere else require([‘myModule’], function (myModule) { myModule.hello() // display ‘hello form myModule’ });
效率高,可惜有点冗长,而且不能在 Node.js 本地运行。
CommonJs : Node.js 平台的默认格式. 通常用法类似这样:
// file1.js modules.export = { hello : () => console.log(‘hello from myModule’) } // file2; const myModule = require('./file1.js'); myModule.hello();
感觉这种方式更酷吧,不仅可以定义变量的作用域,还可以定义模块之间的依赖。可惜这是专为
Node设计的,不支持在浏览器运行,也不能异步加载模块。但是,它可以在前端app使用,借助
Browserify或者其他工具来转换,就可以让它在浏览器运行了。
UMD (通用模块依赖) : 到这里,我们发现还没有一种既可以同时兼容浏览器和 Node 服务器的解决方案。AMD 适合浏览器,CommonJS 适合 Node.
UMD 就来尝试解决这个问题了。它通过把 AMD 和 CommonJS 结合起来,使之在各种需求下都是可集成的,代码大概如下:
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); }(this, function () { // JavaScript chunk return { hello : () => console.log(‘hello from myModule’) } });
该模式根据内容来判断选择 AMD 还是 CommonJS. 这种模式对于打包
多环境的库,如
lodash或者
moment.js是十分适合的。
因此,为何要加一个新模块类型 ?
首先,这些解决方案没有一个是由TC39团队定义的标准。ECMA6 现在已经被大量的开发者所使用,那为何不选择该版本JS定义的标准(ES6模块)呢?这个标准提供了一个更加灵活有力的解决方式。我推荐你看这篇文章, 了解 ES6模块的全部属性,因为这篇文章,我把重点放在了ES6模块这个性质上。它能够更加精确地定义模块间哪些需要被
exposed/imported。一起看看下面的代码:
// file1.js const f1 = ()=> console.log(‘f1’); const f2 = ()=> console.log(‘f2’); const f3 = ()=> console.log(‘f3’); export {f1, f2, f3}; // file2.js import {f1, f2} from “./file1”; f1(); // display ‘f1’ f2(); // display ‘f2’
从这里可以看出,只需要静态地声明我们想要
import的内容就可以。与其它模式不同,像 CommonJS 我们可以动态加载需要的文件。如果我们在 CommonJS 里面使用这个例子,就会有点不同:
// file1.js const f1 = ()=> console.log(‘f1’); const f2 = ()=> console.log(‘f2’); const f3 = ()=> console.log(‘f3’); modules.exports = {f1,f2,f3}; // file2.js const file1 = require(‘./file1’); file1.f1(); // display ‘f1’ file1.f2(); // display ‘f2’ file1[process.ENV.funcName]();
很明显,最后一行无法呈现成真正的代码,但它表明了一些值超出了可控范围,无法在静态分析中被预知。这里,我们实质上是可以调用
f3,因为用
CommonJs(AMD、IIFE 或者 UMD) 我们都是无法限制
import的内容。
所以?了解代码的静态分析是使用什么是不是也很重要呢?
答案是肯定的!
因为有了这个控制,开发者工具可以检测到一些 bug。 如果你使用 WebPack 2 或者 Rollup.js 将会更有趣,结合
Tree Shaking, 你编译的文件将会更小。
Tree Shaking的功能就是把不用用到的代码移除掉。
这就是
tree shaking的一个例子 :
原文件
//------------- // main.js import {cube} from './maths.js'; console.log( cube( 5 ) ); // 125 //------------- // maths.js export function square ( x ) { return x * x; } // This function gets included export function cube ( x ) { return x * x * x; }
输出文件
function cube ( x ) { return x * x * x; } console.log( cube( 5 ) ); // 125
Mathieu Breton CTO chez JS-Republic
相关文章推荐
- 基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
- 谈谈基于.NET开源Wiki程序的选择
- 实验1--基于框架的应用系统开发框架选择原因及其说明
- 基于.NET的CMS软件的选择
- 谈谈我对国内ERP发展现状的看法![转自老男人的blog]
- 选择pmp的原因
- 上周技术关注:从选择Java框架谈谈技术人员的舒适区
- 谈谈我对国内ERP发展现状的看法!
- 基于UML的工作流管理系统分析 选择自 winboy20 的 Blog
- VS.net2005基于VC++实现windows mobile下调用颜色选择对话框
- 选择 WebLogic 9.2 的原因 (文章来源www.itzhe.cn)
- 我来谈谈 Borland 的失败原因
- 选择 Vista Ultimate 的两大原因 BitLocker 和 Media Center
- 针对浙江中小企业的现状谈谈应如何开展电子商务
- 选择SOA的原因和时机
- 基于价值增值逻辑进行绩效指标选择
- 现状,疑问,思考,探索,选择
- 发布您的基于Eclipse的产品 选择自 smallnest 的 Blog
- [讨论]基于.NET的开源论坛软件的选择
- 基于AE删除选择的要素-