前端模块化

752 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

前端模块化

首先理解前端工程化中一个很重要的概念:模块化。一起聊聊模块化是何物以及JS模块化包括哪些解决方案。当然CJSESM这两种模块规范是重点回顾对象。

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler) 。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph) ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle


模块化的演变

js最初的设计是实现一些简单的浏览器交互效果,随着技术发展,网络和用户设备的不断升级,前端项目不断膨胀,早期的js非模块管理的方式已经不适应了,基于此,js引入了模块化的概念,它包括CJS、AMD、CMD、UMD以及ESmodel的ESM。


使用模块化能给前端工程带来什么样的好处?

 ~解决命名冲突 ~:隔离作用域

 ~提供复用性 ~:可以抽离公共代码

 ~提高可维护性 ~:使代码更加高内聚


模块化方案

模块化方案有很多种 企业微信截图_16535556028635.png


最常用的两种模块化方案的对比

CJSESM有何细微不同。

-ESMcjs
语法类型静态动态
关键声明export、importrequire、module.export
加载方式编译时加载运行时加载
加载行为异步加载同步加载
书写位置顶部位置任何位置
指针指向this指向underfindthis指向当前模块
执行顺序引用时生成只读引用
执行是才正式取值
首次引用时加载模块
再次引用时读取缓存
属性应用所有类型属于动态只读引用基本类型属于复制不共享
引用类型属于浅拷贝且共享
属性修改工作空间不可修改引用的值
但可以通过引用的方法修改
工作空间可修改引用的值
node变量不支持支持 例如:__filename


接下来我们深入分析

静态  ~| ~| ~ 动态
我们都知道javascript是一门JIT语言,v8引擎拿到js代码后会边编译边执行,在编译的时候v8就给import导入的模块建立静态的引用,并且不能在运行时不能更改。所以import都放在文件开头,不能放在条件语句里。
require导入模块是在运行时才对值进行拷贝,所以require的路径可以使用变量,并且require可以放在代码的任何位置。
基于这个差异,ESM比CJS好做tree-shaking。


异步  ~| ~| ~ 同步
ESM是顶层await的设计,而require是同步加载,所以require无法导入ESM模块,但是可以通过import()导入。


引用  ~| ~| ~ 拷贝
CJS模块require导入的是值的拷贝,而ESM导入的是值的引用。


让我们回到打包工具

 ~Webpack ~Webpack 作为一个模块打包工具,本身就可以解决模块化代码打包的问题,将零散的 JavaScript 代码打包到一个或多个 JS 文件中。

对于有环境兼容问题的代码,Webpack 可以在打包过程中通过 Loader 机制对其实现编译转换,然后再进行打包

对于不同类型的前端模块类型,Webpack 支持在 JavaScript 中以模块化的方式载入任意类型的资源文件,例如,我们可以通过 Webpack 实现在 JavaScript 中加载 CSS 文件,被加载的 CSS 文件将会通过 style 标签的方式工作。

除此之外,Webpack 还具备代码拆分的能力,它能够将应用中所有的模块按照我们的需要分块打包。这样一来,就不用担心全部代码打包到一起,产生单个文件过大,导致加载慢的问题。我们可以把应用初次加载所必需的模块打包到一起,其他的模块再单独打包,等到应用工作过程中实际需要用到某个模块,再异步加载该模块,实现增量加载,或者叫作渐进式加载,非常适合现代化的大型 Web 应用。

当然,除了 Webpack,其他的打包工具也都类似,总之,所有的打包工具都是以实现模块化为目标,让我们可以在开发阶段更好的享受模块化带来的优势,同时又不必担心模块化在生产环境中产生新的问题。


 ~Vite ~Vite 旨在利用生态系统中的新进展解决上述问题:浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。



小结

最后,让我们一起加油吧!

gg.jpg

都看到这了,不如顺手点个赞再走 ( *ˇωˇ* )