模块化
js 模块化历史
- 早期的 Javascript 是没有模块化的概念,如果想利用 Javascript 构建一个大型项目,就会有很多问题。例如 1.命名冲突;2.变量私有;2.依赖关系的管理等问题。
- 我们所知道的一些模块规范有 AMD、CMD、UMD、CommonJS 。CommonJS 用于服务器,AMD 用于浏览器。目前比较主流的有 UMD、CommonJS。
- CommonJS 模块系统是同步加载的.
- node 使用的模块化系统就是基于 CommonJS 规范的。反言之,我们讲的大部分的 CommonJS 规范都是基于node的模块。
- requirejs 是 AMD 规范的一种实现.
- UMD规范是 AMD + CommonJS + Global Variable 的风格组合产物。有了UMD之后,我们的代码就可以在 node 和浏览器上同时运行了。
CommonJS 语法 (运行时)
// 导出 export.js 不显式地导出时,默认是一个空对象就相当于下面的代码
module.exports = {}
// 单独导出
module.exports.name = 'export'
module.exports.age = 123456
exports.height = '300'
// 整体导出,整体导出时不可以使用 exports, exports 本身是 module.exports 的一个引用,在赋值之后即失去了当前的引用而成为了模块中的一个变量了。
module.exports = { name: 'export', age: 123456, height: '300' }
exports = { name: 'export', age: 123456, height: '300' } // 这样写是错误的
// 导入
const $obj = require('./export')
$obj.name
ESM (编译时)
- ESM 是 es6 推出的 javascript 模块规范。在这之前由于没有规范,所以社区推出了 CommonJS 规范、 require.js 等。
- ESM 的语法是静态的、导出是绑定的。
- 静态的语法意味着可以在编译时确定导入和导出,更加快速的查找依赖,可以使用lint工具对模块依赖进行检查,可以对导入导出加上类型信息进行静态的类型检查。
- 在标签中引入模块:
<script type="module" src="..."></script>
// 导出 foo.js
// 默认导出
// 导入 main.js
import height, { Person, age, name as bname, sum } from "./foo.js"
export const name = "why";
export const age = 18;
export function sum(a, b) {
return a + b;
}
export class Person {
constructor(name) {
this.name = name;
}
}
const aaa = 'aaa'
export { aaa as baaa} // 导出方式二:整体导出,起别名
export default aaa
// 导入导出
export { age, sum } from "./foo.js"
export * from "./foo.js"
// 动态加载
import('./foo.js').then(foo => {
console.log(foo.sum)
})
浏览器异步加载
<script src="xxx.js" defer></script>
<script src="xxx.js" async></script>
- defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;
- async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>