前言
为什么 webpack 总是那么难掌握?
是它太难了?
答案都不是
大多数人用的都是浮于表面之上的 cli,像是 vue-cli cra(create-react-app) 之类的工具包,甚至还有 umi 这种专门对项目开发做的封装。
这类脚手架把大多数我们要做的事情给做了,再者就是如果有什么特殊需求,webpack 本身的插件也能帮我们做,我们几乎都不需要动手来写配置。
这才是原因,用的少自然难以掌握
还是那句核心的话。
熟能生巧。
学习一样东西的本质就是重复。
编程的本质就是减少重复提升效率。
这篇文章不会讲什么 webpack 的配置,而是从另外的视角来看 webpack
正文
在 webpack 之类打包工具之前
让我们回到上古年代,互联网诞生不就,网络水管还在很小
我们的电脑访问网页只能获取一个文件,那就是
html 文件
里面有 html,css,js 三个东西让网页运行。
随着时间的推进,技术得到了进步,数据交互变得复杂,网络得到了提升。
现在可以网络请求可以拓展到多个文件,但是还是不多。
html 一个文件,从几千行代码,变成了几万行,甚至几十万行。
人们觉得从 html 分化出 css 文件,js 文件,在 html 文件里面引入它们可以获得一样的效果
自此一气化三清,我们请求一个完整的网页需要三个文件 html,css,js
由于需要的功能太多了,有一些大神就开始把自己的代码封装成 js 文件让别人引用,这样能提升效率。
于是人们就给 html 接入多个 js 文件,css 文件,因为引用的文件太多,所以每次请求都要加载非常多,网络请求文件最多 5 6 个,使用体验非常差。
这时大家为了优化就想到一个办法,不如把多个 js 文件合并成一个,css 文件合并成一个。
css 文件合并成一个没有问题,但是 js 就有问题
名字冲突怎么办
好在 js 有神奇的闭包解决了这个问题
大家开始把不同闭包,称为模块,包
后面推出了 javascript 运行时 nodejs,nodejs 让网页应用真正有了工程化的能力。
有人开始提出要对包管理做规范的发包,引入包
于是诞生了多个模块化的处理方式,requirejs,commonjs 之类解决方案
有人就写出了 Gulp、Grun 这类将 js,css 文件合并成一个文件的工具
人们把它们叫做打包工具。
好景不长,厂商们开始了浏览器大战,大家都想维护自己的标准。
导致不同浏览器的 js,css 有了不同的标准
社区更是吸取其他语言的优点让 js 更强大,但是浏览器还没有更新到这种地步。
于是又有人仿造神话之中的巴别塔 babel 让不同浏览器标准的 js 和 先进的语法 全部转换成兼容所有环境的 js。
但是这些工具,都是在各自的领域做的很好,那么有没有一个全能的工具把这些都做了呢?
webpack!
webpack 到底在干什么
前面说了这么多,其实也是 web 开发的发展史,写这个故事的意义是让大家不要恐惧 webpack 这个东西,因为它就是如此诞生的。
这也和程序员最爱干的事情有关,划分模块,分层。
因为要复用功能,所以我们把不同功能的代码,叫做模块,包,把它们划分成一个文件最好,这样好维护。
多个文件无疑会增加网络的压力,为了更快的体验,就需要把它们变成几个文件,甚至一个文件。
这就是打包工具要做的事情,把不同包里面的代码结合在一个或者几个文件之中。
又由于多个浏览器的标准,es6 的先进语法,无法稳定的用在浏览器上面。
于是利用 babel 来转义新语法,向前兼容。
这只是打包的流程的一环。
但是 web 应用的资源多种多样,图片,字体,特定的方式优化之后,重新出入到代码之中
不过打包工具不可能把事情都做了,于是有了一个概念叫做 loader,专门处理各种资源。
js 就用 babel 的 loader 转换成老语法,其他资源类似。
webpack 就做了一件事,把不同的资源整合在少数几个文件之中
再来看看 webpack 这张图
webpack 就像一个分类漏斗,把所有资源都倾斜进去。
最后出来的只有 js,css,jpg(其他资源)
分层分模块好维护(成千上万个模块),易复用,适合开发环境。
但是由于生产环境不需要分层分模块,打包成一个文件或者几个文件性能更好。
这就是打包的意义。
webpack 怎么做的打包
其实相信到了这里,如果你接触过 webpack 一点基础内容,那么你一定知道怎么做的打包了。
如果你没接触过过,那么没关系,且听我给你慢慢说。
其实就三步
处理资源的依赖关系 -> 整合打包 -> 输出
处理资源的依赖关系
不同 js 来自不同的包,它们之间相互引用,甚至还有图片,字体,css 引用
形成了复杂的关系图。
如果没有关系图我们直接打包进去,会出现什么问题?
谁先执行,谁后执行?
前端程序执行是线性,有一个队列来排队谁先做谁后做,需要顺序对了才能得到要得效果
所以形成关系图,按照关系图来进行打包。
又因为资源种类多种多样,需要特殊的处理,那么 webpack 出现了 loader 的能力,让第三方开发者能拓展 webpack 对各种资源的处理。
当处理依赖关系的时候,每遇到一个依赖就通过特定的规则匹配 loader 处理资源
整合打包
当依赖处理完之后,就开始对代码进行
- 优化
- 混淆
- 压缩
输出
输出到文件上面
webpack 辅助
诶,你肯定要问 plugin 去那了。
没错 plugin 其实处于各个阶段,可以理解 plugin 就是在 webpack 各个生命周期的地方增强 webpack 的能力
比如有优化代码的 plugin,压缩代码的 plugin
最后输出的时候是怎么输出,输出到什么文件里面。
总结
- 打包工具的流程
- 依赖收集,资源处理
- 转换整合优化混淆代码
- 输出到文件之中
- webpack 打包就是把不同的资源整合到少数几个文件之中
- loader 是处理各种资源
- plugin 是帮助 webpack 干活的小帮手