三、了解前端模块化系列(1)——模块化的理解

181 阅读3分钟

了解前端模块化系列内容:
三、了解前端模块化系列(1)——模块化的理解
三、了解前端模块化系列(2)——模块化规范-CommonJS
三、了解前端模块化系列(3)——模块化规范-AMD
三、了解前端模块化系列(4)——模块化规范-CMD & ES6
三、了解前端模块化系列(5)——模块化规范-UMD & 总结(CommonJS AMD CMD ES6 UMD)

一、目标

  1. 前端模块化发展历程

  2. 掌握现代前端开发模块化的实现及实战

二、模块化的理解

  1. 模块化规范: JS 方面用来管理 web2.0 时代广泛应用 Ajax 技术、jQuery 等前端库而日益膨胀的前端代码。

  2. 已发展十余年的模块化,不同工具和轮子层出不穷,主要解决了:

    1. 外部模块管理;
    2. 内部模块组织;
    3. 模块源码&目标代码 的 编译&转换;
  3. 工具框架的诞生时间:

    生态诞生时间(年)
    Node.js2009
    NPM2010
    requireJS(AMD)2010
    seaJS(CMD)2011
    browserify2011
    webpack2012
    grunt2012
    gulp2013
    react2013
    vue2014
    angular2016
    redux2015
    vite2020
    snowpack2020

2.1 什么是模块

web304-前端模块化-3.1什么是模块.png

2.2 模块化的进化过程

2.2.1 全局 function 模式

web304-前端模块化-3.2.1全局 function 模式.png

举例:

function m1() {
  //...
}
function m2() {
  //...
}

2.2.2 namespace 模式

web304-前端模块化-3.2.2namespace 模式.png

举例:

let myModule = {
  data: 'www.baidu.com',
  foo() {
    console.log(`foo() ${this.data}`)
  },
  bar() {
    console.log(`bar() ${this.data}`)
  }
}
myModule.data = 'other data' //能直接修改模块内部的数据
myModule.foo() // foo() other data

2.2.3 IIFE 模式

匿名函数自调用(闭包)

  1. 作用:
    ① 数据私有
    ② 外部只能通过暴露方法操作
  2. 编码:
    ① 函数内部封装:数据&行为
    window添加 myModule属性,向外暴露接口 foo,bar
  3. bug:
    当前模块依赖另一个模块,怎么办?

举例:

index.html

<script type="text/javascript" src="module.js"></script>
<script type="text/javascript">
  myModule.foo() // 【1.作用】——②外部只能通过暴露方法操作
  myModule.bar() // 【1.作用】——②外部只能通过暴露方法操作
  console.log(myModule.data) //undefined 不能访问模块内部数据
  myModule.data = 'xxxx' //不是修改的模块内部的data
  myModule.foo() //没有改变
</script>

module.js

;(function (window) {
  let data = 'www.xianzao.com' // 【1.作用】——①数据私有
  //操作数据的函数
  function foo() {
    //用于暴露有函数
    console.log(`foo() ${data}`)
  }
  function bar() {
    //用于暴露有函数
    console.log(`bar() ${data}`) // 【2.编码】——①函数内部封装:**数据**&行为
    otherFun() //内部调用
  }
  function otherFun() {
    //内部私有的函数
    console.log('otherFun()') // 【2.编码】——①函数内部封装:数据&**行为**
  }
  //暴露行为
  window.myModule = { foo, bar } //ES6写法  // 【2.编码】——②**window**添加myModule**属性**,向外**暴露接口** foo,bar
})(window)
// 【3.bug】——当前模块依赖另一个模块,怎么办?

结果:

foo() www.xianzao.com
bar() www.xianzao.com
otherFun()
undefined
foo() www.xianzao.com

2.2.4 IIFE 模式增强

web304-前端模块化-3.3.4IIFE模式增强.png

现代模块实现的基石。

  1. jQuery 页面背景改红
  2. 先引入 jQuery 库
  3. 库当作参数传入
  4. 保证模块的独立性
  5. 模块之间依赖关系变得明显

举例:

module.js

;(function (window, $) {
  let data = 'www.baidu.com'
  //操作数据的函数
  function foo() {
    //用于暴露有函数
    console.log(`foo() ${data}`)
    $('body').css('background', 'red') // 1. jQuery页面背景改红
  }
  function bar() {
    //用于暴露有函数
    console.log(`bar() ${data}`)
    otherFun() //内部调用
  }
  function otherFun() {
    //内部私有的函数
    console.log('otherFun()')
  }
  //暴露行为
  window.myModule = { foo, bar }
})(window, jQuery)

index.html

<!-- 引入的js必须有一定顺序 -->
<script type="text/javascript" src="jquery-1.10.1.js"></script> // 2. 先引入jQuery库
<script type="text/javascript" src="module.js"></script> // 3. 库当作参数传入
<script type="text/javascript">
  myModule.foo()
</script>
// 4. 保证模块的独立性
// 5. 模块之间依赖关系变得明显

2.3 模块化的优点&缺点

  1. 优点
    1. 避免命名冲突(减少命名空间污染)
    2. 更好分离,按需加载
    3. 更高复用性
    4. 高可维护性
  2. 缺点——引入多个 <script> 标签后:
    1. 请求过多(多模块 -> 多请求)
    2. 依赖模糊(加载先后顺序出错)
    3. 难以维护(1+2=3)
  3. 解决缺点——通过模块化规范:
    1. common.js 规范
    2. AMD 规范
    3. ES6 规范
    4. CMD 规范

友情链接