前端模块化
CommonJS
// math.js
function add (a,b){
return a + b;
}
module.exports = {
add,
};
// logic.js
const { add } = require('./math');
add(2,3);
ES6 Module
// math.js
const add = (a,b) =>{
return a + b;
};
const minus = (a,b) =>{
return a - b;
}
export default add;
export { add,minus };
// logic.js
import { minus, /* add */ } from './math';
import add from './math';
add(2,3);
两者的比较:
- 1、require运行时同步加载,import编译时前置加载
- 2、require会缓存用到的模块,import则不会
- 3、require是值拷贝,import是值引用,如果导出的值使用了对应模块内部变化可能会影响到import出的值的变化,可以通过在模块内部使用setTimeout改变值,并且导出这个值进行验证
node是用的是commonjs,虽然现在实验性的加入了ES6 Module需要在package.json中写上
{
"type":"module"
}
node --experimental-moduels index.js
在服务器端,模块文件存在本地磁盘或者内存缓存中,读取速度非常快。在浏览器端由于网络的限制,更合理的方案是采用异步加载
AMD和require.js
AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调中,等加载完成后,回调才会运行。
<!-- 首先引入require.js以及入口文件main.js,main.js中配置require.config规定项目中用到的基础模块 -->
<script src="./require.js" data-main="./main.js"></script>
// main.js 入口文件
require.config({
baseUrl:'js/lib',
paths:{ // 依赖前置
'jquery':'jquery.min.js', // 去./js/lib/juery.min.js
}
});
require(['jquery'],$ => {
// doSomething
})
// 在AMD中如果定义的某个模块需要引用其他模块
// math.js 这是一个没有其余依赖的自定义模块
define(() => {
const add = (a,b) =>{
return a + b;
};
return {
add,
};
});
// 该模块依赖于jquery
define(['jquery','math'],($,math) => {
$('#app').textContent = `${ math.add(1,2) }`;
});
CMD和sea.js
// math.js
define((require,exports,module)=>{
const a = require('./a'); //依赖就近
a.doSomething();
});
// 加载模块
seajs.use(['math.js'],(math)=>{
// doSomething
})
两者的比较:
- AMD推崇依赖前置,require.config即可看出
- CMD推崇依赖就近,在做自定义模块时,依赖另一模块时可以看出