模块化
模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等
实现方式
一、自执行函数、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
关于commonJs
和 es module
之间更详细说明的区别,可以查看这篇文章
什么是 UMD
所谓 UMD (Universal Module Definition)
,就是一种javascript
通用模块定义规范,让你的模块能在javascript
所有运行环境中发挥作用。
模块化的管理
同一个项目
当我们的公共模块在同一个项目时,可以放置在项目中自行管理,通过上述的实现方式复用,简单清爽。
多个项目
但是当我们的模块需要在多个项目中重复使用时,如何统一管理这些模块?
假设仍使用同一个项目的管理方式,会有下面这些问题:
- 需要使用模块的时候只能找到之前的项目,把需要用的模块手动复制进去,
ctrl+c
!ctrl+v
! - 没有版本管理,每个项目都有可能新增或者修改,我到底该用哪个项目的?
在多个项目中使用模块,推荐的管理方式:
使用npm
仓库,将package
统一管理起来 - 有业务逻辑的情况下可以搭建私有模块化仓库:如verdaccio
、git module
- 出现模块之间复杂依赖的情况考虑使用lerna
、pnpm
等包管理工具