Skip to content

模块化

模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等

实现方式

一、自执行函数、namespace命名空间模式

  • 自执行函数,在单独的函数中执行代码,隔离作用域,防止变量污染: 这种模式通常是一个独立的模块,没有依赖,通过传入参数实现功能。
javascript
  (function(){
      const a = {}
  })()
  • namespace命名空间,减少全局变量,但是数据会被篡改
js
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

假设我们通过script的标签加载这些模块,当模块之间的依赖变得复杂之后,依赖关系就会变得模糊,就非常容易导致在浏览器中加载顺序出错 所以有了下面这些模块管理的规范:

二、AMD规范

浏览器端模块化:require.js

  • 提前声明依赖
  • 异步加载依赖模块,加载完成后触发回调

引入:

javascript
require([moduleA,moduleB],function(A,B){
 //使用A、B
})

定义:

javascript
//无依赖
define(function(){
 return module
})

//有依赖
define([moduleA,moduleB],function(A,B){
 return module
})

三、CMD规范

浏览器端模块化:sea.js

  • 动态引入模块
  • 异步加载依赖模块,加载完成后触发回调

引入、定义:

javascript
define(function(require, exports, module) {
  // 同步
  var a = require('./a')

  //异步
  require.async('./b',function(b){

  })

  //定义
  exports.xxx = value
  module.exports = value
})

四、CommonJS规范:NodeJS

浏览器端模块化:webpack

  • node:同步加载,任意文件
  • 浏览器:提前编译打包

引入:

javascript
var a = require('a')

定义:

javascript
module.exports = a
exports.a = a

五、ES Modules

浏览器端模块化:babel

  • 浏览器和服务端适用
  • 目前需要工具将es6代码转为es5
  • 依赖需要提前声明

引入:

javascript
import a from 'a'

定义:

javascript
export default {}
export const a = b

关于commonJses module之间更详细说明的区别,可以查看这篇文章

什么是 UMD

所谓 UMD (Universal Module Definition),就是一种javascript通用模块定义规范,让你的模块能在javascript所有运行环境中发挥作用。

模块化的管理

同一个项目

当我们的公共模块在同一个项目时,可以放置在项目中自行管理,通过上述的实现方式复用,简单清爽。

多个项目

但是当我们的模块需要在多个项目中重复使用时,如何统一管理这些模块?

假设仍使用同一个项目的管理方式,会有下面这些问题:

  1. 需要使用模块的时候只能找到之前的项目,把需要用的模块手动复制进去,ctrl+cctrl+v
  2. 没有版本管理,每个项目都有可能新增或者修改,我到底该用哪个项目的?

在多个项目中使用模块,推荐的管理方式:

使用npm仓库,将package统一管理起来 - 有业务逻辑的情况下可以搭建私有模块化仓库:如verdacciogit module - 出现模块之间复杂依赖的情况考虑使用lernapnpm等包管理工具