查看原文
其他

[翻译]从JS模块化现状阐释选择ES6模块的重要性

2016-09-21 grace_xhw 前端圈

本文由grace_xhw 美眉翻译


文章将告诉我们,整个JS社区为何要采用 ES6模块 ,以及这样做的重要性。

当前发展情况

为了弄明白为什么全部迁移到 ES6模块 如此重要,我们首先需要描述一下当前的实际状况。在过去5年,JavaScript 的发展如此迅猛,以至于大多数的开发者都没有意识到现在有 5 种方式可以来创建 JavaScript 脚本和应用!

原始的 IIFE () : 这是最古老也是最简单的使 JS 模块化的方法了。看下面这个例子就是用 IIFE 来实现JS 块的:

const myModule = (function (...deps){
// JavaScript chunk   return {hello : () => console.log(‘hello from myModule’)}; })(dependencies);

对这段代码不应该感到惊奇,它只是一种把变量或者方法包裹起来的普遍模式,也是适合在JS本地使用的唯一方法。它也存在一个问题,就是不能我们需要的依赖。


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

(http://twitter.com/@MatBreton) 

CTO chez (http://www.js-republic.com/)



【React启蒙系列文章】

一、[React启蒙系列] 初探React

二、[React启蒙系列] 学习React前需要理解的名词

三、[React启蒙系列] React和Babel的基本使用

四、[React启蒙系列]React节点

五、[React启蒙系列]使用JSX

六、[React启蒙系列]React 组件属性

七、[React启蒙系列]React 组件状态


【您可能感兴趣的文章】

一、手把手教你用react

二、React入门及资源指引

三、利用ESLint检查代码质量

四、构建一个安全的 JavaScript 沙箱

五、入门Webpack,看这篇就够了

六、第三届CSS大会广州找场地啦~~求介绍~~

七、Web Components 是个什么样的东西

八、JavaScript 被忽视的细节

九、[心得] 如何提高 React App 的性能

十、[心得] 自己动手打造 ES7 开发环境

十一、[译文] 如何运用新技术提升网页速度和性能

十二、你应该知道的HTTP基础知识

十三、Webpack from First Principles

十四、没时间阅读?佐克伯、比尔盖兹、马斯克教你「5小时原则」

十五、没快速成长,别说你在创业

十六、TCP三次握手&Render Tree页面渲染=>从输入URL到页面显示的过程?

十七、[翻译]React最佳实践与实用函数

十八、前端知识普及之HTML



前端圈--打造专业的前端技术会议

为web前端开发者提供技术分享和交流的平台

打造一个良好的前端圈生态,推动web标准化的发展

官网:http://fequan.com

微博:fequancom | QQ群:41378087


长按二维码关注我们

投稿:content@fequan.com

赞助合作:apply@fequan.com

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存