了解前端模块化系列内容:
三、了解前端模块化系列(1)——模块化的理解
三、了解前端模块化系列(2)——模块化规范-CommonJS
三、了解前端模块化系列(3)——模块化规范-AMD
三、了解前端模块化系列(4)——模块化规范-CMD & ES6
三、了解前端模块化系列(5)——模块化规范-UMD & 总结(CommonJS AMD CMD ES6 UMD)
三、模块化规范
3.3 CMD(Common Module Definition)
3.3.1 概念
- CMD 专用 浏览器端
- 异步加载模块
- 使用时加载执行模块
- CMD 整合 CommonJS 和 AMD 的特点。
- Sea.js——JS 模块遵循 CMD 模块定义规范。
3.3.2 基本语法
-
模块定义:
无依赖CMD定义
define(function (require, exports, module) { // 无依赖 CMD ——定义 exports.xxx = value module.exports = value })有依赖CMD定义
define(function (require, exports, module) { // 有依赖 CMD ——定义 var module2 = require('./module2') //引入(同步)依赖模块 require.async('./module3', function (m3) {}) //引入(异步)依赖模块 exports.xxx = value //暴露模块 }) -
模块使用:
引入/使用CMD 模块
// CMD ——引入/使用 define(function (require) { var m1 = require('./module1') var m4 = require('./module4') m1.show() m4.show() })
3.3.3 CMD 实现
-
下载 sea-2.2.3.js ,并引入。
-
创建项目结构
|-js |-libs |-sea.js |-modules |-module1.js |-module2.js |-module3.js |-module4.js |-main.js |-index.html -
定义 modules 目录下的模块代码
js/modules/module1.js
// module1.js文件 define(function (require, exports, module) { var data = 'djsz3y.com' //内部变量数据 function show() { console.log('module1 show() ' + data) } //内部函数 exports.show = show //向外暴露 })js/modules/module2.js
// module2.js文件 define(function (require, exports, module) { module.exports = { msg: 'I am djsz3y' } })js/modules/module3.js
// module3.js文件 define(function (require, exports, module) { const API_KEY = 'abcd1234' exports.API_KEY = API_KEY //向外暴露 })js/modules/module4.js
// module4.js文件 define(function (require, exports, module) { var module2 = require('./module2') //引入(同步)依赖模块 function show() { console.log('module4 show() ' + module2.msg) } //内部函数 exports.show = show //向外暴露 require.async('./module3', function (m3) { console.log('异步引入依赖模块3 ' + m3.API_KEY) }) //引入(异步)依赖模块 // console.log("--------与上面相反一下--------"); // var module3 = require("./module3"); //引入(同步)依赖模块 module3 // function show2() { // console.log("module4 show2() " + module3.API_KEY); // } //内部函数 // exports.show2 = show2; //向外暴露 // require.async("./module2", function (m2) { // console.log("异步引入依赖模块2 " + m2.msg); // }); //引入(异步)依赖模块 module2 })js/modules/main.js
// main.js文件 define(function (require) { var m1 = require('./module1') var m4 = require('./module4') m1.show() m4.show() // m4.show2(); })index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Modular Demo(CMD-seajs)</title> </head> <body> <script type="text/javascript" src="js/libs/sea.js"></script> <script type="text/javascript"> seajs.use('./js/modules/main') </script> </body> </html> -
效果:
module1 show() djsz3y.com module4 show() I am djsz3y 异步引入依赖模块3 abcd1234
3.3.4 AMD VS CMD
AMD VS CMD 区别,在于两个方面:
- 处理依赖
- AMD 依赖前置:依赖数组,提前声明模块依赖
- CMD 依赖就近:require 方法,动态引入
- 处理模块输出
- AMD 输出:return 返回值
- CMD 输出:赋值 module.exports
AMD
// AMD
//【1.处理依赖】——AMD 依赖前置:依赖数组,提前声明模块依赖
define(['Module1'], function (module1) {
var result1 = module1.exec()
return {
result1: result1
} //【2.处理模块输出】——AMD 输出:return 返回值
})
CMD
// CMD
define(function (requie, exports, module) {
var module1 = require('Module1') //【1.处理依赖】——CMD 依赖就近:require方法,动态引入
var result1 = module1.exec()
module.exports = {
result1: result1
} //【2.处理模块输出】——CMD 输出:赋值 module.exports
})
3.4 ES6 模块化
3.4.1 概念
| ES6 模块 (设计思想:静态化) | CommonJS 模块 | AMD 模块 | |
|---|---|---|---|
| 1.何时确定 依赖关系 | 编译时 | 运行时 | 运行时 |
| 2.何时确定 输入输出 | 编译时 | 运行时 | 运行时 |
| 3.比如 | 对象, 输入时必须查找对象属性 | ||
| 4.本质区别 | 输出值引用;编译时输出接口( 静态定义,生成在代码静态解析阶段)。 | 输出值拷贝;运行时加载( 加载对象:module.exports 属性,生成在脚本运行完后)。 |
3.4.2 基本使用
-
统一暴露,引用名称
- 定义模块——export 对外暴露:统一暴露
- 引用模块——import 对内输入:引用时,知道加载变量名、函数名
// 1.定义 math.js var basicNum = 0 var add = function (a, b) { return a + b } export { basicNum, add } // 1.定义模块——export 对外暴露:统一暴露// 2.引用 import { basicNum, add } from './math' // 2.引用模块——import 对内输入:引用时,知道加载变量名、函数名 function test(ele) { ele.textContent = add(99 + basicNum) } -
默认暴露,自定义名称
- 定义模块——export default 对外暴露:默认暴露
- 引用模块——import 对内输入:引用时,自定义名称
// 1.定义 export-default.js export default function () { console.log('foo') } // 1.定义模块——export default 对外暴露:默认暴露// 2.引用 import-default.js import customName from './export-default' // 2.引用模块——import 对内输入:引用时,自定义名称 customName() // 'foo' -
对 3.4.1 中
本质区别举例:【与 CommonJS 的不同】:ES6 动态引用,不会缓存值;模块内变量 绑定所属模块
// lib.js export let counter = 3 export function incCounter() { counter++ } // main.js import { counter, incCounter } from './lib' // 【与 CommonJS 的不同】:ES6 动态引用,不会缓存值;模块内变量 绑定所属模块 console.log(counter) // 3 incCounter() console.log(counter) // 4
3.4.3 ES6 实现
使用 Babel : 1.ES6 编译为 ES5; 2.Browserify 编译打包 js。
-
npm init & 定义 package.json
package.json
{ "name": "es6-babel-browserify", "version": "1.0.0", "description": "ES6 实现", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "djsz3y", "license": "ISC" } -
安装
-
全局安装
babel-cli&browserify:
npm install babel-cli browserify -g。我怕电脑卡,我局部安装
babel-cli&browserify:
npm install babel-cli browserify --save-dev。 -
项目局部安装
babel-preset-es2015:
npm install babel-preset-es2015 --save-dev。
-
-
定义 .babelrc
.babelrc
{ "presets": ["es2015"] } -
定义模块
//module1.js文件 // 分别暴露 export function foo() { console.log('foo() module1') } export function bar() { console.log('bar() module1') } //module2.js文件 // 统一暴露 function fun1() { console.log('fun1() module2') } function fun2() { console.log('fun2() module2') } export { fun1, fun2 } //module3.js文件 // 默认暴露 可以暴露任意数据类项,暴露什么数据,接收到就是什么数据 export default () => { console.log('默认暴露') } // app.js文件 import { foo, bar } from './module1' import { fun1, fun2 } from './module2' import module3 from './module3' // import $ from "jquery"; foo() bar() fun1() fun2() module3() // $("body").css("background", "green"); -
编译
使用 Babel : 1.ES6 编译为 ES5; 2.Browserify 编译打包 js。
-
ES6 编译为 ES5
1.1 全局编译: 如果前面全局安装,那么直接根目录编译:
babel js/src -d js/lib。1.2 局部编译: 由于前面项目局部安装——2.安装的1.局部安装
babel-cli&browserify,所以这里——编译方法为法 Ⅰ & 法 Ⅱ。-
法 Ⅰ:
去根目录\node_modules\.bin目录下,
babel ../../js/src -d ../../js/libXXX\es6-babel-browserify\node_modules\.bin>babel ../../js/src -d ../../js/lib // ..\..\js\src\app.js -> ..\..\js\lib\app.js // ..\..\js\src\module1.js -> ..\..\js\lib\module1.js // ..\..\js\src\module2.js -> ..\..\js\lib\module2.js // ..\..\js\src\module3.js -> ..\..\js\lib\module3.js -
法 Ⅱ:
npx babel js/src -d js/lib2XXX\es6-babel-browserify>npx babel js/src -d js/lib2 // js\src\app.js -> js\lib2\app.js // js\src\module1.js -> js\lib2\module1.js // js\src\module2.js -> js\lib2\module2.js // js\src\module3.js -> js\lib2\module3.js -
对比文件一致:法 Ⅰ & 法 Ⅱ 编译结果 lib & lib2 的文件一致。
-
法 Ⅰ & 法 Ⅱ 思路的参考链接:
【建议改成】读完这篇你还不懂 Babel 我给你寄口罩
-
-
Browserify 编译打包 js :
2.1 全局编译:
browserify js/lib/app.js -o js/lib/bundle.js。2.2 局部编译: 同理。
-
法 Ⅰ:
去根目录\node_modules\.bin目录下,browserify ../../js/lib/app.js -o ../../js/lib/bundle.jsXXX\es6-babel-browserify\node_modules\.bin>browserify ../../js/lib/app.js -o ../../js/lib/bundle.js -
法 Ⅱ:
npx browserify js/lib2/app.js -o js/lib2/bundle.jsXXX\es6-babel-browserify>npx browserify js/lib2/app.js -o js/lib2/bundle.js
-
-
-
引入 index.html
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Modular Demo(es6-babel-browserify)</title> </head> <body> <script type="text/javascript" src="js/lib/bundle.js"></script> </body> </html> -
效果,输出
foo() module1 bar() module1 fun1() module2 fun2() module2 默认暴露 -
引入第三方库
-
安装依赖
npm install jquery@1 -
app.js 文件中引入
//... import $ from 'jquery' //... $('body').css('background', 'green') -
编译
-
法 Ⅰ:
XXX\es6-babel-browserify\node_modules\.bin>babel ../../js/src -d ../../js/lib // ..\..\js\src\app.js -> ..\..\js\lib\app.js // ..\..\js\src\module1.js -> ..\..\js\lib\module1.js // ..\..\js\src\module2.js -> ..\..\js\lib\module2.js // ..\..\js\src\module3.js -> ..\..\js\lib\module3.js XXX\es6-babel-browserify\node_modules\.bin>browserify ../../js/lib/app.js -o ../../js/lib/bundle.js -
法 Ⅱ:
XXX\es6-babel-browserify>npx babel js/src -d js/lib2 XXX\es6-babel-browserify>npx browserify js/lib2/app.js -o js/lib2/bundle.js测试法 Ⅱ 的话,要修改 index.html :
<script type="text/javascript" src="js/lib2/bundle.js"></script>刷新浏览器 index.html ,结果确实变绿。
-
-
-
目录结构:
es6-babel-browserify
|-js |-lib |-app.js |-bundle.js |-module1.js |-module2.js |-module3.js |-lib2 |-app.js |-bundle.js |-module1.js |-module2.js |-module3.js |-src |-app.js |-module1.js |-module2.js |-module3.js |-node_modules |-.babelrc |-index.html |-package.json