前言

在目前前端快速发展的情况下,以前就是简单地会去使用别人的脚手架来搭建项目,然后在项目中进行业务的开发,但是慢慢地,随着业务的正常发展,会发现
原本的脚手架好像已经不能够满足当前的业务,需要在目前项目上进行一个优化工作,但是基本上大部分都是不清楚脚手架里面都有什么配置,也不知道项目中
的配置都用来干嘛,都有什么用途,那么怎能够去站在这个脚手架的上面,来理解并优化项目的架构呢?

如果连基本的关于webpack知识点都不清楚,不能弄懂其中的原理,又怎能去满足日益曾长的业务发展,来打造适合项目业务的完美方案呢?

本文以黄金圈规则来简单阐述,用以告诫自己也顺便提醒自己学习webpack的一个初衷!!!

webpack流程

🤔什么是webpack

webpack是一个现在静态模块打包工具,针对js应用程序(任何使用js来编写的项目,比如react、vue、react-native、普通js、electron等等),
当webpack处理应用程序时,它会在内部从一个或者多个入口点开始,将入口文件所引用到的资源依赖”变成”一棵依赖树,树的根就时入口文件,从根出发,
所依赖的每一个模块就当作时树上的”枝叶”,将这些模块组合成为一个或者多个bundles,而webpack原本只有支持js+json打包的,但是项目中一般都会
使用到其他的资源(比如图片、css等等),这个时候,则需要借助于loader了,loader对象定义在配置文件的module属性中,以rule作为关键词的一个
数组,其目的时告诉webpack在遇到符合类型的文件的时候,将采用loader定义的加载器来加载对应的文件,然后再使用公共的require/import的方式来加载
到对应的依赖,而其中所提供的所提供的plugin插件,就是用来辅助打包,并控制打包过程、打包结果的对象。

根据官网文档对应编写了1⃣️简单的webpack入门项目(如下所示):
webpack例子

针对上述例子,执行对应的命令:

webpack
则会自动寻找对应的webpack.config.js文件进行解析
webpack例子原理解析

🤔为什么要学习webpack

如果我们平时正常使用传统方式来开发web应用程序的话,随着项目越来越大,单纯通过手动部署,覆盖文件进行部署的方式的话,估计想死的❤️都🈶️了,而且也无法享受到
模块编程,针对任何资源的模块编程、一键盘部署、对项目的架构进行高度定制化的服务,一旦我们使用了webpack,我们便可以更好的来管理自己的项目,将那些繁琐的、
又臭又长的逻辑操作,都交给webpack来做,将工作的中心放到业务的实现与跟进上来。
只有从根本上理解了webpack的工作原理,甚至于,我们还可以开发自定义的Loader或者Plugin,来满足项目业务需求!!!

  1. commonJS引入了require机制,它允许我们在当前文件中加载和使用某个模块,导入需要的每个模块,帮助我们解决了作用域问题。
  2. npm + node.js + modules = 大规模分发模块

🤔如何来学习webpack

✨ 既然webpack是一个工具,那么对应的学习方式肯定是线上工具/文档的学习,通过对其工作原理、代码分析,从使用到源码解读,了解关于webpack中所涉及的相关概念、
API、Loader、Plugin的配合,来深入学习如何使用webpack来打包自己的项目,一步步地优化项目的打包工作,提供工作开发效率!!!
webpack成员

相关的概念:

模块(Modules)

在模块化编程中,开发者将程序分解为功能离散的chunk,并称之为模块
每个模块都拥有小于完整程序的体积,使得验证、调试以及测试变得轻而易举,精心编写的模块提供了可靠的抽象和封装界限

🤔 关于chunk的理解,可以这样子简单地来理解:项目中使用的每个文件都是一个chunk,通过chunk的互相引用,这些chunk会形成一个图数据结构,
而在打包的过程中,chunk会被合并成为chunk组,并形成一个通过模块互相链接的图。比如有以下一个配置文件:

1
2
3
4
 // webpack.config.js
module.exports = {
entry: './index.js'
};

针对👆的配置文件,通过webpack工具打包出来的chunk应该是怎样的呢?

👉 此时会创建一个名为main的chunk组(因为main是入口起点的默认名称),此chunk组包含./index.js模块,然后随着webpack的parser解析器在处理./index.js内部的import时,
新的chunk模块就会被添加到这个chunk组中

这里也同时说明了一个情况:如果在使用之前没有做任何的额外的动作的话,一个chunk组中可能有多个chunk,这个时候我们可以使用SplitChunksPlugin插件来将一个chunk拆分为一个或者多个chunk

✨ 通过对上述中chunk组的理解,应该可以是在日常的编程中,如果想要优化打包出来的js过大的其中一个小点,可以考虑将入口所形成的chunk/chunk组所形成的bundle图给进行缩减,将资源调整为按需加载,
或者是动态加载,也就是在还未使用到的时候,不采用静态导入加载的方式,才是采用在需要的时候才来导入调用,在不影响到交互以及业务的情况下!!!!

🌟 chunk有两种形式:

  1. initial(初始化):也就是上述的入口起点的main chunk,此chunk包含为入口起点指定的所有模块以及其依赖模块
  2. non-initial(延迟加载的chunk):延迟加载的chunk,比如动态导入或者是拆分模块导入

比如有👇的一个简单例子,例子中的依赖关系如下:

index.js -> foo.js -> xx.css
-> bar.js

这里对于foo.js以及bar.js的引用机制不一样的,foo.js采用的静态依赖,而bar.js采用的动态依赖,因此生成的chunk.js中,index.js + foo.js + xx.css = main-chunk所在的组中,而bar.js属于单独的一个chunk组

webpack中的chunk依赖

manifest与runtime

在使用webpack构建的典型应用程序或者站点中,有三种主要的代码类型:

  1. 团队所编写的源码;
  2. 依赖的第三方的库或者vendor代码
  3. webpack的runtime和manifest,管理所有模块的交互

runtime(chunk加载逻辑以及解析逻辑代码)

runtime以及伴随的manifest数据,主要指的是在浏览器运行过程中,webpack用来连接模块化应用程序所需的所有代码(chunk),包含有以下几个逻辑动作:

  1. 在模块交互时,连接模块所需的加载和解析逻辑;
  2. 已经加载到浏览器中的连接模块逻辑
  3. 尚未加载模块的待延迟加载逻辑

manifest(保留的所有chunk的标识符)

一旦通过浏览器打开*.html的时候,它会自动去加载bundle以及其他的通过依赖来关联的chunk,这些chunk是已经通过打包、压缩、延迟加载等操作的细小的chunk,与源代码中的文件结构已经
完全没有半毛钱关系了,manifest就是管理打包后的chunk与打包前的源代码模块之间的一个关联关系

🤔课题预留:如何根据学习的webpack来优化自己目前的项目

  1. 从0⃣️开始搭建自己的vue项目基础框架
  2. 从0⃣️开始搭建自己的ejs + webpack静态生成页面基础框架
  3. 从0⃣️开始搭建生成静态html页面基础框架