js 模块化

77 阅读2分钟
js幼年期:
1、需要的js即页面中增加简单的js:动画,表单,格式化
2、多种js文件被分在不同的文件=》文件分离是模块化的第一步
3、不同的文件又被不同的模板引用
问题:
污染全局作用域=》不利于多人开发共建

js成长期: IIFE
const iifeModule = (
    ()=>{
        let count = 0;
        return {
            increase: ()=> ++count;
            reset: ()=>count = 0;
        }
    }
)();
iifeModule.increase();
iifeModule.reset();
依赖其他模块的IIFE
iifeModule(dependencyModule1, dependencyModule2);


成熟期:CJS-Common.js
node.js制定(里面的函数)
**module+exports 对外暴露接口**
**require 调用其他模块**
// 引入模块
const dependencyModule1 = require(./dependencyModule1);
//业务逻辑
let count = 0;
const increase = ()=> ++count;
const reset = ()=> count = 0;
// 暴露接口
exports.increase = increase;
exports.reset = reset;
module.exports = {
    increase, reset
}
// 实际原理
(function(thisValue, exports, require, module){
    const dependencyModule1 = require(./dependencyModule1);
    // 业务逻辑
}).call(thisValue, exports, require, module);
优点:CommonJS率先走服务端实现了,从框架层面解决依赖,全局变量污染的问题
缺点:主要针对服务端,没有解决异步依赖。

AMD规范
通过异步加载+允许制定回调函数,经典实现框架require.js
// params:模块名,依赖模块,回调函数(工厂模式)
**define(id, [depends], callback);定义一个函数**
**require([modules],callback);调用一个函数**
define('amdModule', ['dependencyModule1', 'dependencyModule2'],(dependencyModule1, dependencyModule2)=>{
    let count = 0;
    const increase = ()=> ++count;
    const reset = ()=> count =0;
    return {
        increase, reset
    }
})
require('amdModule', amdModule=>{
    amdModule.increse();
}
//兼容commonJs/AMD =》UMD
(define('module', [], (require, export, module)=>{
    // 导入
    const dependencyModule1 = require(./dependencyModule1);
    // 处理业务逻辑
    let count = 0;
    const increase = ()=> ++count;
    const reset = ()=> count=0;
    //导出
    export.increase = increase;
    export.reset = reset;
}))(
    typeof module  === 'object'
    && module.exports
    && define !== 'function'
    ? // 是 CJS
    factory => module.exports = factory(require, export, module)
    : // 是AMD
        define
)
优点:解决了异步加载,可以并行加载多个模块(define函数是宏任务)

CMD规范
优点:按需加载,依赖就近 主要应用框架sea.js
define('module', (require, exports, module)=>{
    let $ = require('jquery');
    let dependencyModule1 = require('./depencyModule1');
    
    const increase = ()=>{};
    module.exorts = {
        increase,
    }
})

ES6模块化:
引入关键字=>import
导出关键字=>export
import dependencyModule1 from './dedenpencyModule1.js'
// 实现代码逻辑
let count = 0;
// 1种导出
export const increase = ()=>++count;
// 2种导出
export default{
    increase,
}
使用中:
import { increase, reset } from './esModule.js'
increase();
reset();
import esModule from './esModule.js'
esModule.increase();
esModule.reset();
// 动态模块 export+promise
import('./esModule.js').then(dynamicEsModule=>{
    dynamicEsModule.increase();
})
优点:(重要性)通过一种最终统一的形态整合了js模块化
缺点:(局限性)本质上还是运行时的依赖分析

/工程化 组件化 设计模式

前端工程化
根本问题: 运行时依赖分析
解决方案:glup webpack
工程化实现:
1、扫描依赖关系
{
    a: ['b', 'c'],
    b: ['d'],
    e: []
}
2、重新生成依赖数据模板
<!doctype html>
<script src="main.js"></script>
<script>
require.config({
    'deps': {
        a: ['b', 'c'],
        b: ['d'],
        e: [],
    }
})
</script>
<script>
require(['a', 'e'], ()=>{
    // 业务处理
})
</script>
</html>
3、执行工具,采用模板化方案解决依赖
define('a', ['b', 'c'], ()=>{
    // 执行代码
    export.run = ()=>{}
})

优点:
1、构建时生成配置,运行时执行
2、最终转化成执行处理依赖
3、可以拓展