理解模块化


什么是模块

  1. 将一个复杂的程序 拆分 成单个文件,最终 组合 在一起
  2. 拆分的 文件 就是模块,模块内部数据是私有,只是向外部暴露一些方法与其他模块通信

模块、库、包 的区别

模块(Module): javascript文件
库(Library):使用模块实现的一些 功能的统称,概念性的称呼(jQuery库,就是用于实现DOM操作)
包(Package):是依据包规范,对库功能实现的代码集合

为什么要模块化

  1. 降低复杂度,提高解耦性
  2. 避免命名冲突
  3. 更高的分离,按需加载
  4. 更高复用性,高可维护性

模块化带来的问题

  1. 请求过多
    • 需要引入过多的文件
  2. 依赖模糊
    • 引入文件的顺序不明确(依赖)
  3. 难以维护

模块化规范

应用范围

  • CommonJS
    • node:可以写服务端模块化代码
    • browser:可以写浏览器端模块化代码
  • ES6
    • browser:只能写浏览器端模块化代码

模块的特性

  1. 引入模块时,接收的暴露数据是常量
  2. 多个模块组合在一起,相当于组合成一个JS文件
  3. 同一个组合中,对某一个模块的不同引用,获取的是同一个数据(不同组合对同一模块的引用各自独立)
  4. 引入模块语句,会被提升到代码的开始(CommonJS规范除外,用的是 require()函数
  5. 引入模块,会先执行模块中所有代码,然后接收暴露数据

CommonJS


规范

  1. 官网:http://wiki.commonjs.org/wiki/Modules
  2. 每个文件都是一个模块
  3. CommonJS 模块化的代码既可以在服务端运行,也可以在浏览器端运行
  4. 服务端:模块化的代码可以直接运行
  5. 浏览器端:模块化的代码要经过 Browserify(http://borwserify.org)编译

暴露原理

  1. exportsmodule.exports 在node服务端,默认都是指向同一个 空对象
  2. 可以为 exportsmodule.exports 指向一个 新对象
  3. 也可以为 exportsmodule.exports 默认指向的空对象 定义属性
    1. module.exports.xxx = value
    2. exports.xxx = value
  4. exportsmodule.exports 指向的对象,可以用 require() 函数在其他JS文件中返回 暴露对象
  5. 如果 exportsmodule.exports 指向不同的对象,require() 引入暴露对象,以 module.exports 为准

基本语法

  1. 暴露语法:
    1. 方法一:module.exports = value
    2. 方法二:exports.xxx = value
  2. 引入语法:
    1. 引入自定义模块:require(xxx),xxx 为模块文件路径
    2. 引入第三方模块:require(xxx),xxx 为模块名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 暴露新对象
module.exports = {
xxx:123
}
exports = {
yyy:123
}
// 暴露任意类型数据
exports.xxx = 456
module.exports.yyy = 456
//------------------------------------

// 引入暴露对象
var exobj = require("./module")

浏览器端使用

原理

CommonJS规范 转换为浏览器可以运行的代码(转换后的代码中实现了 require() 函数)

使用方式

  1. 全局安装 Browserify
    • npm i browserify -g
  2. 转换 CommonJS规范
    1. 只需要转换 汇总 的那个 JS文件
    2. browserify ./app.js -o ./xxx.js
      • browserify [JS文件地址] -o [输出文件名和地址]
  3. HTML中引入转换后的 JS文件

ES6


规范

  1. 每个JS文件都是一个模块
  2. 引入模块语句,会被提升到代码的开始
  3. 引入模块,会先执行模块中所有代码,然后接收暴露数据
  4. 浏览器如果不支持ES6语法,要借助 BabelBrowserify 依次编译代码,才能在浏览器端运行
  5. Babel 中文官网: https://www.babeljs.cn

暴露原理

ES6规范暴露的数据与CommonJS规范不同,暴露的不是对象,使用引入的语法引入的也不是一个对象,只是规定语法(虽然底层确实是对象,但是给到开发人员的并不是对象)
因此 import {xxx, yyy} from "./module" 其中 {xxx, yyy} 不是解构赋值


使用方式

使用ES6模块化代码有两种方式

  1. 浏览器支持ES6代码
    • HTML引入JS文件时,script标签的type属性值必须为module <script type="module" src="./app.js"></script>
  2. 浏览器不支持ES6
    • 将ES6模块化代码转换为ES5代码,script标签的type属性值就可以为text/javascript <script type="text/javascript" src="./app.js"></script>

浏览器不支持ES6,想要使用 ES6 模块化代码,需要先准备相关依赖包

  1. 全局安装 babel-cliBrowserify
    • npm i babel-cli browserify -g
  2. 局部安装 babel ES6转ES5依赖包 babel-preset-es2015
    • npm i babel-preset-es2015 -S
  3. 定义 babel 配置文件 .babelrc
    1. 根目录添加文件 .babelrc
    2. 配置 .babelrc 文件内容
      1
      2
      3
      {
      "presets": ["es2015"]
      }

浏览器不支持ES6,ES6模块化代码需要先使用依赖包进行编译,才能运行

  1. 使用 Babel 将ES6编译为ES5代码
    1. 进入目录
    2. 编译指定目录(自动编译目录中的所有JS文件,包括子目录中JS文件)
    3. 指定输出目录(编译完成的文件存放目录)
    • babel ./src -d ./build
  2. 使用 Browserify 将ES5汇总JS文件进行编译
    • browserify [JS文件地址] -o [输出文件名和地址]
    • ES6转ES5,模块化编程相关代码,被转成了CommonJS规范代码,需要再次编译

基本语法

  1. 暴露模块:
    1. 分别暴露:export 暴露内容
      • 必须在 声明语句 前添加 export
    2. 统一暴露:export { 暴露内容1,暴露内容2 }
      • 暴露内容 ({…}中内容)必须是 标识符
      • 暴露的 标识符 可以使用 as 进行 重命名 之后暴露
    3. 默认暴露:export default 暴露内容
      • 模块中只能有 一个 默认暴露
      • 只能暴露 标识符任意类型数据
  2. 引入模块:
    1. 方法一:import {xxx, yyy} from "./module"
      • 适用于 分别暴露统一暴露 的数据
      • 暴露数据可以配置别名 { xxx as 别名,yyy as 别名 }
      • 打包引入:暴露的数据作为整体引入 import * as 别名 from "./module"
    2. 方法二:import module3 from "./module3"
      • 适用于 默认暴露 的数据
  3. 混合暴露
    1. 模块中使用不同方式进行暴露
    2. 引入:
      1. import moduledefault,{xxx, yyy, aaa, bbb} from "./module"
      2. import moduledefault,* as zt from "./module"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 分别暴露
export var a = 123
export var b = 123
// 统一暴露
var c = 456
var d = 789
export {c,d}
// 默认暴露
export default { e:111 }

// 统一引入
// defex:默认暴露的数据
// {a,b,c,d}:分别暴露,统一暴露的数据
import defex, {a as aaa,b,c,d} from "./module"
import defex,* as ty from "./module" // 分别暴露和统一暴露的数据作为整体引入

注意事项

引入 json 文件

如果引入一个 json 文件,会对 json 文件中的内容作为对象进行 默认暴露