请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

亿仁网

 找回密码
 立即注册

扫一扫,访问微社区

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 4867|回复: 0

ES Module 是语言层面的模块化方案

[复制链接]
  • TA的每日心情
    奋斗
    2019-3-14 22:24
  • 签到天数: 160 天

    [LV.7]常住居民III

    1074

    主题

    1139

    帖子

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    18046
    发表于 2018-10-22 21:43:51 | 显示全部楼层 |阅读模式

    ES Module 是语言层面的模块化方案,由 ES 2015 提出,其规范与 CommonJS 比之 ,导出的值<span data-type="color" style="color:rgb(26, 26, 26)"><span data-type="background" style="background-color:rgb(255, 255, 255)">都可以看成是一个具备多个属性或者方法的对象</span></span>,可以实现互相兼容;但写法上 ES Module 更简洁,与 Python 接近;

    1. import fs from 'fs';
    2. import color from 'color';
    3. import service, { getArticles } from '../service';

    4. export default service;
    5. export const getArticles = getArticles;
    复制代码

    主要差异在于:

    • ES Module 会对<span data-type="color" style="color:rgb(26, 26, 26)"><span data-type="background" style="background-color:rgb(255, 255, 255)">静态代码分析,即在代码编译时进行模块的加载,在运行时之前就已经确定了依赖关系(可解决循环引用的问题);</span></span>
    • ES Module 关键字:import export 以及独有的 default  关键字,确定默认的导出值;
    • <span data-type="color" style="color:rgb(26, 26, 26)"><span data-type="background" style="background-color:rgb(255, 255, 255)">ES Module 中导入模块的属性或者方法是强绑定的,包括基础类型;</span></span>

    通过一层自执行函数来兼容各种模块化规范的写法,兼容 AMD / CMD / CommonJS 等模块化规范,贴上代码胜过千言万语,需要特别注意的是 ES Module 由于会对静态代码进行分析,故这种运行时的方案无法使用,此时通过 CommonJS 进行兼容;

    1. (function (global, factory) {
    2.   if (typeof exports === 'object') {   
    3.     module.exports = factory();
    4.   } else if (typeof define === 'function' && define.amd) {
    5.     define(factory);
    6.   } else {
    7.     this.eventUtil = factory();
    8.   }
    9. })(this, function (exports) {
    10. ​ // Define Module
    11.   Object.defineProperty(exports, "__esModule", {
    12.     value: true
    13.   });
    14.   exports.default = 42;
    15. });
    复制代码

    构建工具中的实现,为了在浏览器环境中运行模块化的代码,需要借助一些模块化打包的工具进行打包( 以 webpack 为例),定义了项目入口之后,会先快速地进行依赖的分析,然后将所有依赖的模块转换成浏览器兼容的对应模块化规范的实现;

    模块化的基础,从上面的介绍中,我们已经对其规范和实现有了一定的了解;在浏览器中,要实现 CommonJS 规范,只需要实现 module / exports / require / global 这几个属性,由于浏览器中是无法访问文件系统的,因此 require 过程中的文件定位需要改造为加载对应的 JS 片段(webpack 采用的方式为通过函数传参实现依赖的引入)。webpack 打包出来的代码快照如下,注意看注释中的时序;

    1. (function (modules) {
    2.   // The module cache
    3.   var installedModules = {};
    4.   // The require function
    5.   function __webpack_require__(moduleId) {}
    6.   return __webpack_require__(0); // ---> 0
    7. })
    8. ({
    9.   0: function (module, exports, __webpack_require__) {
    10.     // Define module A
    11.     var moduleB = __webpack_require__(1); // ---> 1
    12.   },
    13.   1: function (module, exports, __webpack_require__) {
    14.     // Define module B
    15.     exports = {}; // ---> 2
    16.   }
    17. });
    复制代码

    实际上,ES Module 的处理同 CommonJS 相差无几,只是在定义模块和引入模块时会去处理 __esModule 标识,从而兼容其在语法上的差异。

    异步和扩展

    1、浏览器环境下,网络资源受到较大的限制,因此打包出来的文件如果体积巨大,对页面性能的损耗极大,因此需要对构建的目标文件进行拆分,同时模块也需要支持动态加载;webpack 提供了两个方法 require.ensure() 和 import() (推荐使用)进行模块的动态加载,至于其中的原理,跟上面提及的 AMD & CMD 所见略同,import() 执行后返回一个 Promise 对象,其中所做的工作无非也是动态新增 script 标签,然后通过 onload / onerror 事件进一步处理。

    2、由于 require 函数是完全自定义的,我们可以在模块化中实现更多的特性,比如通过修改 require.resolve 或 Module._extensions 扩展支持的文件类型,使得 css / .jsx / .vue / 图片等文件也能为模块化所使用;



    造物之前,必先造人。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|亿仁网 ( 粤ICP备16098737  

    GMT+8, 2020-8-12 06:01 , Processed in 0.181488 second(s), 24 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表