常见模块化规范有CommonJS
,AMD
,CMD
,ES6模块化
。CommonJS
核心思想是通过require
方法来同步加载依赖的其他模块,通过module.exports导出需要暴露的接口,通过require引入模块,同步执行。AMD
规范主要是为了解决针对浏览器环境的模块化问题,最具代表性的实现是requireJS.
模块化
模块化是指把一复杂的系统分解到多个模块中
CommonJS
CommonJS 是一种使用广泛的javascript
模块化规范,核心思想是通过require
方法来同步加载依赖的其他模块,通过module.exports导出需要暴露的接口,通过require引入模块,同步执行 主要用在node中
用法
1
2
3
4
5// 采用CommonJS来进行导入导出
// 用require方法导入
const moduleA = require('./b.js');
// 用module.exports导出
module.exports = someFunc;原理
1
2
3
4
5
6
7
8
9
10
11
12let fs = require('fs');
let path = reqiure('path');
let b = req('./b.js');
function req(mod){
let filename = path.join(__dirname,mod);
let content = fs.readFileSync(filename, 'utf-8');
let fn = new Function('exports', 'require', 'module', '__dirname', '__filename', content + '\n return module.exports;')
let module = {
exports: {}
}
return fn(module.exports, req, module, __dirname, __filename)
}
AMD
AMD 也是一种Javascript 模块化规范, 与CommonJS 最大的不同在于它采用异步的方式去加载依赖的模块. AMD规范主要是为了解决针对浏览器环境的模块化问题,最具代表性的实现是requireJS.
AMD的优点
- 可在不转换代码的情况下直接在浏览器中运行
- 可加载多个依赖
- 代码可运行在浏览器环境和Node.js 环境下
1
2
3
4
5
6
7
8
9
10
11// 定义一个模块
define('a', [], function(){
return 'a';
})
define('b', ['a'], function(a){
return a + 'b';
})
// 导入和使用
require(['b'], function(b){
console.log(b)
})
CMD
一个文件最为一个模块,使用define来定义模块,modules.exports对外导出模块, 使用require来加载一个模块,代表是SeaJS, 尽可能懒执行1
2
3
4
5
6
7
8
9// 通过 define 来定义模块
define(function(require, exports, module){
// 通过 require 引入模块
var $ = require('jquery')
// 通过 exports 对外提供接口
exports.doSomething = ...
// 通过 module.exports 提供整个接口
module.exports = ...
})
ES6模块化(ES Module)
ES6 模块化是ECMA
提出的javascript
模块化规范,它在语言的层面上实现了模块化.浏览器厂商和Node.js
都宣布要原生支持该规范,它将逐渐取代CommonJS
和AMD
规范,成为浏览器和服务器通用的模块化解决方案.
ES6模块目前还无法直接运行在javascript环境下,必须通过工具转换成ES5后才能正产运行1
2
3
4// 使用export导出
export const name = 'asd'
// 使用import导入
import {name} = from 'xxx.js'
ConmmonJS与ES6 Module的区别
- ConmmonJS的require的模块路径可以根据if判断条件动态指定加载那个文件。ES6 Module导入和导出的路径不支持表达式,导入导出的语句必须位于顶层作用域,不能放在if等判断语句中
- 在导入模块时CommonJS获取的是一份值拷贝,对导出的值修改,不会影响源文件的值。而ES6 Module则是值的动态映射,对导出的值进行修改,会影响源文件的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31/* ES6 Module */
// add-content.js
var count = 0
const add = function () {
count += 1
}
export { count, add }
// index.js
import { count, add } from './add-content.js'
console.log(count)
add()
console.log(count)
count += 1 // 直接修改会报错
// connot set property count of #<Object> which has only e getter
/* ConmmonJS */
// add-content.js
var count = 0
module.exports = {
count: count,
add: function () {
count += 1
}}
}
// index.js
var count = require('./add-content.js').count
var add = require('./add-content.js').add
console.log(count) // 0
add()
console.log(count) // 0
count += 1
console.log(count) // 1
自动化构建
把源代码转换成在线上可执行的 Javascript、CSS、HTML代码。包括如下内容
- 代码转换: Ecmascript6 变异成 Ecmascript5, less编译成css等
- 文件优化: 压缩Javascript、CSS、HTML代码,图片压缩与合并。
- 代码分割: 提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
- 模块合并:使用构建工具将多个模块与文件合并成一个文件。
- 自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。
- 代码校验:检验代码是否符合规范,以及单元测试是否通过。
- 自动发布:更新完代码后,自动打包代码并发布到服务器上。
前端工程化
前端工程化 是指将前端开发的流程规范化,标准化,包括开发流程,技术选型,代码规范,构建发布等