JS模块化规范管理

一、理解

1.1 什么是模块化

  • 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起

  • 块的内部数据/实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信

  • 模块化的进化史

    • 最早

      JS模块化规范管理

      JS模块化规范管理

    • 简单封装:Namespace模式

      JS模块化规范管理

      JS模块化规范管理

    • 匿名闭包:IIFE模式

      JS模块化规范管理

      JS模块化规范管理

    • 再增强一点:引入依赖

      JS模块化规范管理

      JS模块化规范管理

1.2 为什么要模块化

JS模块化规范管理

1.3 模块化的好处

  • 避免命名冲突(减少命名空间污染)
  • 更好的分离, 按需加载
  • 更高复用性
  • 高可维护性

1.4 页面引引入script

JS模块化规范管理

问题:

  • 请求过多
  • 依赖模糊
  • 难以维护

二、模块化规范

2.1 CommonJS

2.1.1 规范

2.1.1.1 说明

  • http://wiki.commonjs.org/wiki/Modules/1.1
  • 每个文件都可当作一个模块
  • 在服务器端: 模块的加载是运行时同步加载的
  • 在浏览器端: 模块需要提前编译打包处理

2.1.1.2 基本语法

  • 暴露模块

    module.exports = value

    exports.xxx = value

    问题: 暴露的模块到底是什么?

  • 引入模块:require(xxx)

    第三方模块:xxx为模块名

    自定义模块: xxx为模块文件路径

2.1.1.3 module.exports和exports的区别

Node.js:模块化思想中一个Javascript文件分析以及exports 和 module.exports的区别

2.1.2 实现

2.1.2.1 服务器端实现

Node.js
http://nodejs.cn/

JS模块化规范管理

2.1.2.2 浏览器端实现

Browserify
http://browserify.org/
也称为CommonJS的浏览器端的打包工具

  • 打包处理JS命令

    browserify 源文件 -o 目标文件

    browserify js/src/app.js -o js/dist/bundle.js		// out
    
  • 打包处理后直接引入目标文件即可

    JS模块化规范管理

2.1.2.3 区别Node与Browserify

  • Node.js运行时动态加载模块(同步)
  • Browserify是在转译(编译)时就会加载打包(合并)require的模块

2.2 AMD

2.2.1 规范

2.2.1.1 说明

Asynchronous Module Definition(异步模块定义)
https://github.com/amdjs/amdjs-api/wiki/AMD
专门用于浏览器端, 模块的加载是异步的

2.2.1.2 基本语法

  • 定义暴露模块

    //定义没有依赖的模块
    
    define(function(){
    	return 模块
    })
    
    //定义有依赖的模块
    
    define(['module1', 'module2'], function(m1, m2){
    	return 模块
    })
    
  • 引入使用模块

    require(['module1', 'module2'], function(m1, m2){
    	使用m1/m2
    })
    

2.2.2 实现(浏览器端)

Require.js
http://www.requirejs.cn/
http://www.ruanyifeng.com/blog/2012/11/require_js.html

  • 如果没有AMD等,原生引入

    JS模块化规范管理

  • 自定义模块

    JS模块化规范管理

  • 第三方模块

    JS模块化规范管理注意:由于jQuery在源码中支持了AMD规范,并且自定义了名称,因此只能使用jquery

    JS模块化规范管理

    注意Plus:有些第三方库需要进行额外配置,例如angular.js

    JS模块化规范管理

2.3 CMD

2.3.1 规范

2.3.1.1 说明

Common Module Definition(通用模块定义)
https://github.com/seajs/seajs/issues/242
专门用于浏览器端, 模块的加载是异步的
模块使用时才会加载执行

2.3.1.2 基本语法

  • 定义暴露模块

    //定义没有依赖的模块
    define(function(require, exports, module){
    	exports.xxx = value
    	module.exports = value
    })
    
    //定义有依赖的模块
    
    define(function(require, exports, module){
    	//引入依赖模块(同步)
    	var module2 = require('./module2')
    	//引入依赖模块(异步)
      	require.async('./module3', function (m3) {
        	})
    	//暴露模块
    	exports.xxx = value
    })
    
  • 引入使用模块

    define(function (require) {
    	var m1 = require('./module1')
    	var m4 = require('./module4')
    	m1.show()
    	m4.show()
    })
    

2.3.2 实现(浏览器端)

Sea.js
http://www.zhangxinxu.com/sp/seajs/

JS模块化规范管理

2.4 ES6

2.4.1 规范

2.4.1.1 说明

http://es6.ruanyifeng.com/#docs/module
依赖模块需要编译打包处理

2.4.1.2 语法

导出模块: export
引入模块: import

2.4.2 实现(浏览器端)

  • 常规暴露:分别暴露和统一暴露,引入的时候需要使用解构的方式

    JS模块化规范管理

  • 默认暴露:可以暴露任意数据类型,暴露什么数据就接收什么数据

    JS模块化规范管理

在根目录下创建.babelrc文件,并添加一下内容

{
  "presets": [
    "es2015"
  ]
}

JS模块化规范管理

使用Babel将ES6编译为ES5代码

  • babel 源文件夹 -d 目标文件夹

    babel js/src -d js/lib
    

使用Browserify将CommonJS规范打包编译为浏览器可识别的代码

  • browserify 源文件 -o 目标文件

    browserify js/lib/main.js -o js/dist/bundle.js
    
  • browserify必须创建文件夹,babel可以自动创建文件夹

使用Browserify编译打包js

2.4.3 注意

  • 在采用分别暴露或统一暴露(常规暴露)的时候,是引入的时候,必须使用解构赋值的方式

三、扩展阅读

  • https://github.com/seajs/seajs/issues/588(前端模块化开发那点历史)
  • http://zccst.iteye.com/blog/2215317(CommonJS,AMD,CMD区别)
  • http://www.zhihu.com/question/20351507/answer/14859415(AMD和CMD 的区别)
  • http://www.ruanyifeng.com/blog/2012/10/javascript_module.html(Javascript模块化编程)
上一篇:【Node.js】学习系列2-commonJS的模块规范


下一篇:[ JavaScript ] require中 exports 和 module.exports 的区别