• 基于JS模块化现状谈谈选择ES6模块的原因


    这篇文章,我们将了解为什么JS社区有必要选择ES6模块。

    现状

    要明白这种重要性,首先我们需要描述一下JS的实际情况。过去5年,JavaScript 发展得非常迅猛,大多数开发人员几乎没意识到当前已经有 5 种方式,可以为 JavaScript 脚本和应用创建模块了!

    • 原始的 IIFE () : 这是最古老,也是比较简单的创建 JS 模块的方法了。以下是用 IIFE 实现的简单模块化示例:
       const myModule = (function (...deps){
           // JavaScript chunk
           return {hello : () => console.log(‘hello from myModule’)};
        })(dependencies);

    相信大家对这段代码都不陌生,它只是把变量和方法都封装在本身作用域内的一种普通模式。其存在的缺点就是没有帮我们处理依赖。

    • requirejsAMD (异步模块依赖) : 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();

    nodejs

    感觉这种方式更酷吧,不仅可以定义变量的作用域,还可以定义模块之间的依赖。可惜这是专为 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 的内容。

    tree-shacking

    所以?了解代码的静态分析是使用什么是不是也很重要呢?

    答案是肯定的!

    因为有了这个控制,开发者工具可以检测到一些 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

    原文链接https://www.zcfy.cc/article/1010

  • 相关阅读:
    Tempter of the Bone
    CODE[VS]1160 蛇形矩阵
    CODE[VS] 1205 单词翻转
    CODE[VS] 1204 寻找子串位置
    a little sweet~
    我多喜欢你,你会知道
    P1474 货币系统 Money Systems
    P1096 Hanoi双塔问题
    P1209 [USACO1.3]修理牛棚 Barn Repair
    下一秒
  • 原文地址:https://www.cnblogs.com/GeniusZ/p/12539679.html
Copyright © 2020-2023  润新知