前端模块化

  1. 前端模块化
    1. 模块化的进程
    2. CommonJS
    3. AMD
    4. CMD
    5. ES6模块

前端模块化

模块化的进程

图 5

CommonJS

  • 介绍:用于node服务端的模块引入,一般是同步的
  • 基本语法
    • 导出:module.exports = xxx或者 module.exports.x = xxx
    • 引入:var xxx = requrie('xx.js')
  • 特点
    • 引入的是对象的浅拷贝
    • 作用域是在模块文件内部,不污染全局
    • 可以多次加载,但是只运行一次
    • 加载顺序,跟代码顺序一致
  • 应用场景
    • 服务器
    • 浏览器需要借助Browserify

AMD

  • 介绍:主要用于浏览器,比CommonJS在浏览器实现早,可以用require.js库,实现异步加载,底层是通过script节点插入脚本方式异步加载模块

  • 基本语法

    • 导出

      // 定义没有模块依赖的导出模块
      define(function(){
        // ...操作  
        var x = 1
        return 
      })
      // 定义有模块依赖的导出模块
      define([m1,m2],function(m1,m2) {
        // ...操作
        var x = 1
        return {x}
      })
    • 引入

      require([m1,m2], function() {
        // ...操作 
      })
  • 特点

    • 可以异步加载模块
    • 依赖和引入以数组形式传入
    • 回调形式执行加载后模块

CMD

  • 介绍:CommonJS和AMD的结合,也是通过script加载

  • 导出:

    // 定义没有模块依赖的导出模块
    define(function(require, exports, module) {
      exports.x = 'x'
      // module.exports.x = 'x'
      // return {x}
    })
    define({ "foo": "bar" }) // JSON 数据模块
    define('I am a template. My name is {{name}}.') // 字符串模板模块
    
    // 定义有模块依赖的导出模块
    define('id', ['jquery'], function(require, exports, module) { 
      // 模块代码
    })
    
  • 引入

    define(function(require, exports, module){
      //引入依赖模块(同步)
      var m1 = require('./m1')
      //引入依赖模块(异步)
        require.async('./m2', function (m2) {
          // ···操作
        })
      //暴露模块
      exports.xxx = value
    })
  • 应用

ES6模块

  • 介绍:ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。它设计思想是尽量静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

  • 导出

    // 单个特性
    export let a = 0, b = 1, c = 2
    export function f() {}
    
    // 列表
    export {a, b , c}
    export {a as A}
    
    // 默认导出
    export default let a = 0, b = 1
    export default function f() {}
    
    // 列表选择一个默认
    export {a as default ,...}
    
    // 导出模块合集
    export * from …
    export { name1, name2, …, nameN } from …
    export { default } from …
  • 引入

    // 默认导入
    import defaultExport from "module-name";
    import * as name from "module-name";
    
    // 列表导入
    import { export } from "module-name";
    import { export as alias } from "module-name";
    import { export1 , export2 } from "module-name";
  • 特点:

    • 加载多次执行一次

    • 动态引入,不是值的拷贝,模块的变量绑定其模块,即使导出也如此

      /** import 动态引入 */
      // lib.js
      export let counter = 3;
      export function incCounter() {
        counter++;
      }
      // main.js
      import { counter, incCounter } from './lib';
      console.log(counter); // 3
      incCounter();
      console.log(counter); // 4
      
      /** CommonJS 类似于值的拷贝*/
      var obj = {
        add: function() {
          this.val++
        },
        val: 0
      }
      var { val } = obj
      console.log('val-1', val++)
      console.log('val-2', val++)
      obj.add()
      obj.add()
      console.log('val-3', val) // 如果为动态引用此时输出应该为 4
      // 输出
      // val-1 0
      // val-2 1
      // val-3 2
  • 与CommonJS差异

    • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
    • ES6 模块是编译时输出接口, CommonJS 模块是运行时加载
  • 应用

    • 浏览器,可以用ES6-Babel和Browserify,实际上就是先转es5(但包含CommonJS语法)再用Browserify编译打包

参考


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1249118795@qq.com