最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Babel的奇妙冒险 babel-plugin-transform-modules-*

    正文概述 掘金(NickNa)   2020-11-29   799

    模块化的背景

    早期 Javascript 程序很小,大多被用来执行独立的脚本任务,提供一定交互。现在有了运行大量 Javascript 脚本的复杂程序,还有一些被用在其他环境(例如 Node.js)。因此,有必要开始考虑提供一种将 JavaScript 程序拆分为可按需导入的单独模块的机制。

    Javascript中的模块需要解决的问题是: 如何将一段代码封装到一个有用的单元中,以及如何注册其函数/为模块导出值,如何引用其他代码单元。

    Babel模块化相关插件

    • babel-plugin-transform-modules-amd
    • babel-plugin-transform-modules-commonjs
    • babel-plugin-transform-modules-umd

    传统方法

    以Jquery为例,以前是如何定义代码段的?

    // Jquery 示例
    (function(window,undefined){
        window.$ = window.JQuery;
        var JQuery = function(selector){
        }
    })(window)
    
    • 通过立即函数调用表达式(IIFE)定义
    • 对依赖关系的引用是通过通过HTML脚本标记加载的全局变量名称完成的。
    • 依赖关系的描述非常微弱:开发人员需要知道正确的依赖关系顺序。例如,包含Backbone的文件不能在jQuery标记之前。
    • 它需要额外的工具才能将一组脚本标签替换为一个标签,以优化部署。
    • 在大型项目上,这可能很难管理,尤其是当脚本开始以可能重叠和嵌套的方式具有许多依赖关系时。手写脚本标签的伸缩性不是很高,因此无法按需加载脚本。

    CommonJS

    CommonJS 原先叫做ServerJS,是js在服务端的规范,node使用的就是这种规范。根据CommonJS规范,一个单独的文件就是一个模块,require用来加载一个模块,exports用来向外部暴露该模块里的方法或属性,加载模块是同步的。

    CommonJS规范

    AMD (异步模块定义 Asynchronous Module Definition)

    AMD规范制定了定义模块的规则,这样模块和模块的依赖可以被异步加载。这和浏览器的异步加载模块的环境刚好适应(浏览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。

    AMD规范只定义了一个函数 "define",它是全局变量。函数的描述为:

    define(id?, dependencies?, factory);
    

    id是模块的名字,dependencies是依赖模块数组,工厂方法 factory 为模块初始化要执行的函数或对象

    • 通过调用define()来注册工厂函数,而不是立即执行它。
    • 将依赖项作为字符串值数组传递,不要获取全局变量。
    • 仅在加载并执行了所有依赖项后,才执行工厂函数。
    • 将相关模块作为参数传递给工厂函数。
    // 全局函数 define 应该实现绑定 amd 属性,防止与现有的定义了define函数但不遵从AMD编程接口的代码相冲突
    define.amd = {};
    
    // 判定当前页面是否有 AMD 模块加载器
    if (typeof define === "function" && define.amd) {
        // ...
    }
    

    requirejs

    requireJS是基于AMD模块加载规范,使用回调函数来解决模块加载的问题。

    requireJS是使用创建script元素,通过指定script元素的src属性来实现加载模块的。

    CMD (通用模块定义 Common Module Definition)

    CMD规范中,一个模块就是一个文件

    define('hello', ['jquery'], function(require, exports, module) {
    // require
      // require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口
      // require.async 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调。callback 参数可选
      // require.resolve 使用模块系统内部的路径解析机制来解析并返回模块路径。该函数不会加载模块,只返回解析后的绝对路径
    // exports
      // exports 是一个对象,用来向外提供模块接口
      // 也可以使用 return 直接向外提供接口
      // exports 仅仅是 module.exports 的一个引用。在 factory 内部给 exports 重新赋值时,并不会改变 module.exports 的值。因此给 exports 赋值是无效的,不能用来更改模块接口
    //module
      // module 是一个对象,上面存储了与当前模块相关联的一些属性和方法
      // module.uri String 根据模块系统的路径解析规则得到的模块绝对路径
      // module.dependencies 是一个数组,表示当前模块的依赖
      // module.exports 当前模块对外提供的接口
      // module.exports 的赋值需要同步执行,不能放在回调函数里
    });
    
    // 判定当前页面是否有 CMD 模块加载器
    if (typeof define === "function" && define.cmd) {
    }
    

    seajs

    SeaJS是一个遵循 CMD 规范的模块加载器。

    UMD(通用模块定义Universal Module Definition)

    UMD提供了支持多种风格的通用模式,在兼容CommonJS和AMD规范的同时,还兼容全局引用的方式

    // babel UT output code
    
    (function (global, factory) {
      if (typeof define === "function" && define.amd) {
        // 判断是否支持AMD
        define(["exports"], factory);
      } else if (typeof exports !== "undefined") {
        // 否支持 Node.js 模块格式
        factory(exports);
      } else {
        var mod = {
          exports: {}
        };
        factory(mod.exports);
        global.input = mod.exports;
      }
    })(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports) {
      "use strict";
    
      Object.defineProperty(_exports, "__esModule", {
        value: true
      });
      _exports.default = void 0;
      var _default = {};
      _exports.default = _default;
    });
    

    ES6 模块

    • ES6 模块是通过静态分析编译时加载
    • 不需要UMD模块格式,将来服务器和浏览器都会支持 ES6 模块格式。
    • 将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者navigator对象的属性。
    • 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。

    ES6 模块

    浏览器支持模块

    最新的浏览器开始原生支持模块功能了,浏览器能够最优化加载模块,使它比使用库更有效率:使用库通常需要做额外的客户端处理。

    • html 使用 type="module" 的 script 标签
    • 原生JavaScript模块,使用 .mjs 扩展名, MIME-typejavascript/esm导入文件
      • 比较清晰,这可以指出哪些文件是模块,哪些是常规的 JavaScript。
      • 这能保证你的模块可以被运行时环境和构建工具识别,比如 Node.js 和 Babel
    • export import 语法和ES6一致
    • import 模块文件的路径是相对于站点根目录的相对路径,或者使用点语法意味当前路径
    • 通过本地加载Html 文件 (比如一个 file:// 路径的文件), 会遇到 CORS 错误,因为Javascript 模块安全性需要,要通过一个服务器来测试。
    • 模块自动采用严格模式,不管你有没有在模块头部加上"use strict";
    • 加载一个模块脚本时不需要使用 defer 属性,模块会自动延迟加载。

    动态加载模块

    将import()作为函数调用, 返回一个 promise, 模块对象为参数

    import('/modules/myModule.mjs')
      .then((module) => {
        // Do something with the module.
      });
    

    参考

    webpack 模块

    webpack 模块能够以各种方式表达它们的依赖关系,几个例子如下:

    • ES2015 import 语句
    • CommonJS require() 语句
    • AMD define 和 require 语句
    • css/sass/less 文件中的 @import 语句。
    • 样式(url(...))或 HTML 文件(<img src=...>)中的图片链接(image url)

    起源地下载网 » Babel的奇妙冒险 babel-plugin-transform-modules-*

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元