了解前端模块化系列内容:
三、了解前端模块化系列(1)——模块化的理解
三、了解前端模块化系列(2)——模块化规范-CommonJS
三、了解前端模块化系列(3)——模块化规范-AMD
三、了解前端模块化系列(4)——模块化规范-CMD & ES6
三、了解前端模块化系列(5)——模块化规范-UMD & 总结(CommonJS AMD CMD ES6 UMD)
三、模块化规范
3.1 CommonJS
3.1.1 概念
3.1.2 特点
3.1.3 基本语法
- 暴露模块:
module.exports = value或
exports.xxx = value - 引入模块:
require(第三方模块名)或
require(自定义模块文件路径) - What is CommonJS 暴露的模块?
-
通过 module.exports 输出变量 x 和函数 addX
// example.js var x = 5 var addX = function (value) { return value + x } // 通过 module.exports 输出变量 x 和函数 addX module.exports.x = x module.exports.addX = addX -
加载模块文件:读入并执行一个 JavaScript 文件,返回该模块的 exports 对象;
没有指定模块,报错。var example = require('./example.js') //如果参数字符串以“./”开头,则表示加载的是一个位于相对路径 console.log(example.x) // 5 console.log(example.addX(1)) // 6
3.1.4 模块的加载机制
- CommonJS 模块的加载机制是:
输入的是被输出的值的拷贝。 - 也就是说,
一旦输出一个值,模块内部的变化就影响不到这个值。 - 这与 ES6 模块化有重大差异(下文会介绍)
例子:
lib.js
// lib.js
var counter = 3
function incCounter() {
counter++
}
module.exports = {
counter: counter, // 内部变量counter
incCounter: incCounter // 改写这个变量的内部方法incCounter
}
main.js
// main.js
var counter = require('./lib').counter
var incCounter = require('./lib').incCounter
console.log(counter) // 3
incCounter()
console.log(counter) // 3
// counter是一个原始类型的值,会被缓存。
// 除非写成一个函数,才能得到内部变动后的值。
3.1.5 服务器端实现
-
npm initpackage.json
{ "name": "commonjs-node", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "djsz3y", "license": "ISC" } -
下载第三方模块:
npm install uniq --save // 用于数组去重 -
定义模块代码
//module1.js module.exports = { msg: 'module1', foo() { console.log(this.msg) } } //module2.js module.exports = function () { console.log('module2') } //module3.js exports.foo = function () { console.log('foo() module3') } exports.arr = [1, 2, 3, 3, 2] // app.js文件 // 引入第三方库,应该放置在最前面 let uniq = require('uniq') let module1 = require('./modules/module1') let module2 = require('./modules/module2') let module3 = require('./modules/module3') module1.foo() //module1 module2() //module2 module3.foo() //foo() module3 console.log(uniq(module3.arr)) //[ 1, 2, 3 ] -
node app.js输出:
..\commonJS-node> node app.js module1 module2 foo() module3 [ 1, 2, 3 ]
3.1.6 浏览器端实现
-
npm init& 创建项目结构|-browserify-test |-js |-dist //打包生成文件的目录 |-src //源码所在的目录 |-module1.js |-module2.js |-module3.js |-app.js //应用主源文件 |-index.html //运行于浏览器上 |-package.json { "name": "browserify-test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "djsz3y", "license": "ISC" } -
下载 browserify
- 全局:
npm install browserify -g - 局部:
npm install browserify --save-dev
- 全局:
-
定义模块代码
//module1.js module.exports = { msg: 'module1', foo() { console.log(this.msg) } } //module2.js module.exports = function () { console.log('module2') } //module3.js exports.foo = function () { console.log('foo() module3') } exports.arr = [1, 2, 3, 3, 2] // app.js文件 // 引入第三方库,应该放置在最前面 // let uniq = require('uniq') let module1 = require('./module1') let module2 = require('./module2') let module3 = require('./module3') module1.foo() //module1 module2() //module2 module3.foo() //foo() module3 // console.log(uniq(module3.arr)) //[ 1, 2, 3 ] -
打包编译 app.js (借助 browserify )
browserify js/src/app.js -o js/dist/bundle.js -
页面使用引入 bundle.js
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title></title> </head> <body></body> <script type="text/javascript" src="js/dist/bundle.js"></script> </html> -
浏览器打开 index.html
输出:
bundle.js:15 module1 bundle.js:20 module2 bundle.js:24 foo() module3