JS 模块化的发展史(一)

143 阅读1分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

序言

最近在学习 rollup 相关的内容,发现自己对打包的意义理解甚浅,主要原因在于对 JS 模块化不够了解,不清楚打包的目的,所以本着查漏补缺的原则,今天好好的来了解一下 JS 模块化的前身今世,以便我们可以明白打包的目的和选择格式。

为什么需要模块化

  1. 网站正在变成网络应用程序。
  2. 页面到程序的转变意味着代码量和代码结构的复杂程度大幅度上升。
  1. 需要解耦 JS 文件之间的关系。
  2. 部署一些在 HTTP 调用中优化代码。

模块化的雏形

模块化的基本在于如何控制文件中代码的作用域问题,模块之间的导入导出引用的问题,所以想要模块化得从这两个方面进行研究。

封装

起初我们的代码都写在一个文件内,作用域为全局,容易变量污染和冲突。

  1. 命名空间形式的封装
const coolFish = {
  age: 18,
  like: 'computer game'
}
coolFish.age;

减少了了全局下面的变量,但是本质为对象,不够安全。

  1. IIFE模式 ,匿名闭包
var Module = (function(){
    var private = "coolFish";
    var foo = function(){
        console.log(private)
    }

    return {
        foo: foo
    }
})()

Module.foo();
Module.private; // undefined

函数是 JS 唯一的块级作用域。

  1. 引入依赖问题
var Module = (function(depend){
    var _dependBody = $("body");     // we can use jQuery now!
    var foo = function(){
        console.log(_dependBody);    // 特权方法
    }

    // Revelation Pattern
    return {
        foo: foo
    }
})(jQuery)

Module.foo();

小结:以上是最初的模块化雏形,通过原生 JS 的方法,解决了模块之间的作用域封装,和依赖的导入问题。

导入

在 JS 中常见的导入方式就是通过 script 标签进行导入。

<body>
</body>
<script src="jquery.js"></script>
<script src="coolFish.js"></script>

但是这种形式是以 DOM 加载顺序来决定文件加载顺序的,而且当内容过多的时候,一个页面几十个 script 标签,非常非常难维护,加载顺序也无法控制稳妥,并且会有过多的 HTTP 请求调用。于是运势而出了 LABjs。

LABjs

LAB.js 以链式调用的形式来控制文件的的引入,并且支持并行加载。下面是简单的示例。

script(src="LAB.js" async)

$LAB
.script( [ "script1.js", "script2.js", "script3.js"] )
.wait(function(){ // wait for all scripts to execute first
    script1Func();
    script2Func();
    script3Func();
});

该插件名为脚本加载器,大大的解决了 script 标签串行引入文件导致的堵塞,文件加载顺序,文件管理等问题。