• 前端模块化发展历程 (-)


    本文将从以下三点来做一个详细讲解:

    1. 模块化产生
    2. 早期模块化解决方案
    3. 模块化规范的产生和差异

    模块化产生

    在早期的前端开发中,并没有模块的概念,模块只在服务端存在,用于处理复杂的业务通信等。 直到 AJAX 被提出,前端能够像后端请求数据,前端逻辑越来越复杂,就出现了许多问题:全局变量,函数名冲突,依赖关系不好处理... 随着业务逻辑的增加,对模块需求越来越大,所以才有了后续一系列 AMD、commonJS、ES6Module 规范。

    早期模块化解决方案

    两种解决方法:

    • 匿名函数自调用(闭包): 形成私有变量; 栈内存处理 
    • 基于对象进行分组 堆内存处理; “单例模式思想” : 基于单独的实例, 来实现信息分组, 避免全局变量的污染

    下面一个简单的例子

    // 新闻板块
    let newMOdel = (function(){
      let time = new  Date()
      const query = function query() {}
      const handle = function handel() {}
      return {
        query,
        handle
      }
    }())
    // 皮肤板块
    let skinModel = (function() {
      let time = '2021-07-05'
      const hanle = function handel(){ }
      newMOdel.query()
    }())

    最早期的模块编程思想就是这种 高级单例设计模「闭包+对象」的组合 模块块化编程思想:就是各个板块/模块 /功能 拼接成一起的东西 ,提出公共的模块。

    带来的好处?

    公用&复用性、提供开发效率、方便管理、团队协作开发 ; 问题:需要自己构建、根据模块间的依赖关系,需要明确导出顺序。 所以就产生了一些其他的模块化规范。

    模块化规范 - AMD

    AMD 即 Asynchronous Module Definition:异步模块加载,代表 require.js

    RequireJS是一个遵守AMD规范的工具库,用于客户端的模块管理。它通过 define 方法,将代码定义为模块;通过 require 方法,实现代码的模块加载,使用时需要下载和导入项

     文件目录

    ├── AMD  
        ├── moduleA.js  
        ├── moduleB.js  
        ├── main.js  
        └── require.min.js 

    简单实现一个require.js

    let factories = {}
    function define(moduleName,factory) {
      factories[moduleName] = factory
    }
    function require(modules,callback) {
      modules = modules.map(function(item){
        let factory = factories[item];  // 定义好每一个 然后把它执行
        return factory() // 执行之后返回的东西 放到modules
      });
      callback(...modules) // 然后回掉函数执行这些modules
    }
    /**使用AMD */
    define('moduleA', function() {
      return {
        fn() {
          console.log('moduleA')
        }
      }
      
    });
    define('moduleB', function() {
      return {
        fn() {
          console.log('moduleB')
        }
      }
      
    });
    require(['moduleB','moduleA'],function(moduleB,moduleA) {
      moduleB.fn()
      moduleA.fn()
    })

    模块化规范 - CMD

    CMD即 Common Module Definition : 通用模块加载。

    CMD(Sea.js )& CommonJs规范(Node.js)。

    问题:CommonJs只能在 node 环境下支持,客户端/浏览器不支持  CommonJS 规范

    那如何让浏览器支持CommonJs规范? 所以有了 Sea.js  ,也就产生了CMD规范(Sea.js 就是Commonjs规范直接搬到浏览器上 )

    AMD、CMD 区别

    AMD 是 RequireJS 在推广过程中对模块定义的规范化产出 CMD是SeaJS在推广过程中对模块化定义的规范化产出

    区别:

    • 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
    • CMD 推崇依赖就近,AMD 推崇依赖前置

    模块化规范 - ES6Module

     ModuleA.js

    const sum =  function sum(...args){
      let len = args.length
      let firstItem = args[0]
      if(len === 0) return 0;
      if(len === 1) return firstItem;
      return args.reduce((total,item) => {
        return total + item
      })
    }
    
    export default { sum }

    moduleB.js

    import A from './a.js'
    const average = function average(...args) {
      let len = args.length
      let firstItem = args[0]
      if(len === 0) return 0;
      if(len === 1) return firstItem;
      return (A.sum(...args) / args.length).toFixed(2)
    }
    
    export default  { average }

    main.js

    import A from './a.js'
    import B from './b.js'
    console.log(A.sum(1,2,3))
    console.log(B.average(1,2,3))

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <script type="module" src="./main.js"></script>
    </body>
    </html>

    注意:

    • es6Module 不需要引入外部依赖,浏览器可以直接运行,但要告诉浏览器我是esModule规范,type='module'   <script type="module" src="./main.js"></script>
    • es6Module 浏览器不支持file协议,要在本地起一个服务,可以在vscode上装一个live serve插件,给本地一个服务。

    ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案

    特点:webpack 支持、浏览器也支持.        

    CommonJS、ES6Module差异

    • CommonJs输出的是一个值的拷贝,ES6输出的是值的引用
    • CommonJs是运行时加载,ES Module是编译时就确认了依赖关系

    第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

     

  • 相关阅读:
    菜鸟nginx源码剖析数据结构篇(十一) 共享内存ngx_shm_t[转]
    菜鸟nginx源码剖析数据结构篇(十) 自旋锁ngx_spinlock[转]
    菜鸟nginx源码剖析数据结构篇(九) 内存池ngx_pool_t[转]
    菜鸟nginx源码剖析数据结构篇(八) 缓冲区链表ngx_chain_t[转]
    菜鸟nginx源码剖析数据结构篇(七) 哈希表 ngx_hash_t(下)[转]
    菜鸟nginx源码剖析数据结构篇(六) 哈希表 ngx_hash_t(上)[转]
    菜鸟nginx源码剖析数据结构篇(五) 基数树 ngx_radix_tree_t[转]
    菜鸟nginx源码剖析数据结构篇(四)红黑树ngx_rbtree_t[转]
    菜鸟nginx源码剖析数据结构篇(三) 单向链表 ngx_list_t[转]
    菜鸟nginx源码剖析数据结构篇(二) 双向链表ngx_queue_t[转]
  • 原文地址:https://www.cnblogs.com/imMeya/p/15011834.html
Copyright © 2020-2023  润新知