20211226 JS模块化详解

直播课地址:

网上参考资料:[https://www.cnblogs.com/lvdabao/p/js-modules-develop.html]

早期无模块化的js项目

js的作用域很模糊,只有函数作用域,没有花括号块级作用域,可能导致多人协同开发时,如果重复命名,会用变量污染

1全局变量的污染

2,函数名称的污染

3,文件的依赖关系只能通过script标签层级引用

最早的模块化

(使用立即执行函数封装)


const  lifeModule = (() => {

 let  count = 0;

 return {

 add: () => {

 count++

    },

 reset: () => {

 count = 0

    }

  }

})()

jQuery风格的匿名自执行函数

(function(window){ //代码 window.jQuery = window.$ = jQuery;//通过给window添加属性而暴漏到全局 })(window);

通过window挂载变量或者暴露接口到全局,如果有插件,则挂到名称空间JQuery上。

更加优雅,但是没有根本解决模块化问题。

模块依赖通过传参的方式

((dependency1,dependency2,...)=>{

.......

})(dependency1,dependency2,...)

缺点:模块的命名在全局暴露,依然会有污染风险

node孵化的时候,因为是服务器语言,需要模块化规范,于是发明了commonJs

规范特征:

通过exports方法对外暴露接口

通过require方法调用依赖模块

commonJS

优点:服务端解决了模块依赖,模块思想,全局污染的规范问题

缺电:因为是在服务端实现的规范,服务端1是同步加载模块文件的,不存在异步加载的先后问题,2是服务端代码是先编译后执行的,在离线编译的时候,模块之间的依赖关系都确认了。浏览器端的代码执行环境和服务端不一样。

AMD方式:AMD(Asynchronous Module Definition)

通过异步加载+允许定制回调函数

经典:require.js

requirejs中有专门define方法来定义模块,以解决模块异步加载问题

requirejs会等待所有模块依赖加载完毕,然后再执行模块

define(‘mymodule’,[dependency1,dependency2],(dependency1,dependency2)=>{

.......

})

AMD中使用revealing

define(id,[],(requie,export,module)=>{

const depen1=require('./otherModule')

export.func=()=>{

.......

}

})

优点:适合在浏览器端异步加载模块,可是并行加载多个模块

缺点:不能按需加载,会等待加载完引入的全部模块

CMD方式:

解决AMD不能按需加载的痛点

经典:sea.js

实现:CMD实现按需加载需要依赖打包工具,在打包编译阶段就按需加载对应模块内容

ES6,模块化

通过export关键字导出模块功能(暴露api)

通过import关键字导入模块(或者部分功能)

---otherModule.js

export.func1=()=>{...}

export.func2=()=>{...}


import{func1,func2} from './otherModule.js'

优点:官方统一了模块化规范和语法

缺点:还是没有从本质上解决例如异步,按需加载等需求

ES11

解决模块动态(异步)加载

类似promise语法。统一一个then方法,加载成功后调用then方法

由于以上模块化几乎全部在运行时进行,具有局限性

解决模块化新思路:前端工程化

离线打包(编译)

1,解析原始依赖,形成依赖树配置

2,运行时,这个依赖会发送到浏览器端

3,运行时根据依赖树加载依赖(如AMD方式)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容