《从0到1手写可插拔前端框架》3.构建编译:现代前端构建方案

692 阅读4分钟

该小节主要知识点:

  • ⭐️ 模块化的发展史
  • Treeshaking 基本原理
  • ⭐️ Webpack、Rollup、Vite、Esbuild、Babel、Tsc、Swc 有什么不同 ?
  • ⭐️ 什么是 Bundle、Bundless、No-Bundle

给大家抛出一个问题:

上一小节我们使用 tsc 将 我们的 ts代码 全部 转换成了 js、js.map、d.ts的代码
请问 这是 打包 吗?为什么

在正式解答什么是 Bundle、Bundless、No-Bundle 之前,先带大家回顾一下模块化的发展史

模块化的发展史

在那个HTML文件里面写所有的JS、CSS代码,刀耕火种的年代,**工程化**逐渐兴起

优秀的前辈们开始了对 工程化 以及 模块化 的探索之路

一.无模块化标准阶段

1.文件划分

问题:命名冲突,script标签顺序管理困难,变量全部定义在全局-调试困难

2.命名空间

优化命名冲突:每个文件都是引入一个大的对象,解决了大对象下的变量命名冲突

3.LIFE(立即执行函数)

目的是为了解决变量命名冲突

二.模块化标准阶段

1.CJS-CommonJs

特点:只支持 node 环境,同步,导出变量可以修改

2AMD(Asynchronous Module Definition,异步模块加载机制)

代表:requirejs

3.CMD和UMD

CMD:与AMD一样解决异步问题

UMD:一直兼容CJS和AMD的方案

4.ESM(浏览器原生和服务端支持异步)-ESModule

在 node端 如何使用 ESModule呢?

1.package.json中 type 改为 module
2.文件名后缀为 mjs

特点:双端支持,异步,导出变量为引用,无法修改

在 浏览器端 如何使用 ESModule呢

script标签中设置 type='module' 即可

CJS与ESM的差异-- Treeshaking 基本原理

ESModule 模块依赖关系是确定的,和运行时的状态无关

可以进行可靠的⭐️ 静态分析 也就是 不执行里面的js代码 就可以分析得到 依赖图谱

CommonJs require 执行之后 我们 才可以知道 这个模块引用了其他的哪些模块

Webpack、Rollup、Vite、Esbuild、Babel、Tsc、Swc 有什么不同

第一类叫做 Bundle 型

Webpack - Bundle

特点:

通过构建依赖图谱 最终将产物放到 main.js

对于除 js 之外的其他资源 bundle、transform 能力也同样优异

Rollup - Bundle

特点:

通过构建依赖图谱 最终将产物打包到 main.js

大力支持ESModule

第二类叫做 No-Bundle 型

Vite:

development 阶段:- No-Bundle

使用 ESbuild 对 ts、tsx、jsx 文件 进行 transform 进行平行编译之后 不Bundle

而是通过浏览器原生支持 ESModule 的特点,使用 script标签 type = ’module‘ 引入

production 阶段: - Bundle

使用Rollup进行全量Bundle 将产物打包到 main.js

第三类叫做 Bundless 型 有些开源库作者也喜欢叫 Transform

TSC - typescript compiler

Esbuild

Babel

Swc

他们的 特点是什么:编译生成 js 代码

比如我们上一小节中 将 ts 代码编译成了 js 代码

实际上 上面四个都可以完成代码的编译/转换 达到我们想要的效果

但是他们的能力 仅限于 例如 ts js jsx tsx ... 而不包括其他资源例如:css、图片、字体 ...

所以什么是Bundless?

Bundless文件到文件的构建模式,它不对依赖做任何处理,只对源码平行编译输出 -- (引自辟起老师)

以下是示例:

└── src
    ├── index.less
    ├── index.ts
    └── test.js

它会被编译成

└── src
    ├── index.d.ts
    ├── index.js
    ├── index.less
    └── test.js	

还记得本小节开头的问题吗?

上一小节我们使用 tsc 将 我们的 ts代码 全部 转换成了 js、js.map、d.ts的代码

请问这是 打包 吗?

答案是 -- 不是

这是 Bundless 的方案

所以 什么是 Bundle、Bundless、No-Bundle?

相信你看到这里,对于三种模式已经有了自己的理解了 如果还是一知半解 建议反复观看前面举的例子

总结一下:

Bundle 就是通过 分析依赖图谱 将所有文件打入一个文件 里面去使用

Bundless 就是只对 所有源文件 进行 平行编译/transform 不会去分析依赖关系进行打包

No-Bundle 例如Vite 就是 利用Bundless 编译/transform 之后通过 浏览器原生支持ESModule 的特性使用 script标签引入 type = 'module' 做 development 开发

小结:

本小节我们

1.首先带大家系统回顾了一下模块化发展的过程,引出了我们现在最常用的CommonJs、ESModule、LIFE、UMD

2.主要介绍了这个 Treeshaking 优异的能力,它是通过 ESModule 静态分析 的特点来实现的

3.通过举例当前工程化领域流行的几个工具,为大家介绍了他们的异同指出它们的特点,让大家自行体会什么是Bundle、Bundless、No-Bundle

4.总结了什么是Bundle、Bundless、No-Bundle,即 Bundle--通过 分析依赖图谱 将所有文件打入一个文件Bundless--只对 所有源文件进行 平行编译/transform 不会去分析依赖关系进行打包,No-Bundle--利用 Bundless 编译/transform 之后通过浏览器原生支持ESModule的特性使用 script标签引入 type = 'module'

下一小节将带着大家将我们的第一个 npm 包发布到 npm 仓库中 ~

小节思考:

你能自己表述出来 什么是 Bundle、Bundless、No-Bundle 吗?