webpack打包流程

文章类型:webpack

发布者:hp

发布时间:2023-05-19

Webpack 是一个用于打包前端资源的工具,它提供了模块化管理、代码分割、静态资源优化等功能,负责将项目中的各种资源打包成最终可部署的静态文件

一:流程

  1. 配置文件:创建一个名为 webpack.config.js 的配置文件,其中定义了打包的入口、输出目录、加载器、插件等相关配置。
  2. 入口解析:根据配置文件中指定的入口(entry)开始解析打包的模块依赖关系。
  3. 加载器处理: 在解析模块时,根据配置文件中定义的加载器(loaders)对不同类型的文件进行处理。加载器可以将文件转换为模块,。
  4. 插件应用:通过配置文件中的插件来实现各种优化和扩展功能。插件可以用于压缩代码、优化静态资源、生成 HTML 文件、提取公共模块等。
  5. 依赖图构建: 会递归地构建整个项目的依赖图,并根据模块之间的依赖关系进行合并和拆分。这样可以确保所有模块都正确地按照依赖顺序进行打包。
  6. 代码分割:支持代码分割,可以将代码拆分成多个块,实现按需加载。通过配置文件中的代码分割策略,会根据依赖关系将代码拆分成多个块,并生成对应的文件。
  7. 模块解析:打包过程中会解析模块的路径和依赖,根据配置文件中的解析规则来查找模块。它会根据配置文件中的 resolve 字段来决定如何解析模块的路径和扩展名。
  8. 优化和压缩:打包过程中会应用一系列的优化策略,对生成的代码进行压缩,减小文件体积,提高加载速度。
  9. 输出结果: 将打包生成的文件输出到指定的输出目录中。输出的文件可以是 JavaScript、CSS、图片等各种静态资源。
  10. 构建完成:打包过程完成后,会输出打包结果的统计信息,根据这些信息来优化打包配置和性能

二:代码演示

1:安装依赖

npm install webpack webpack-cli lodash --save-dev

2:创建入口文件

import _ from 'lodash';

function component() {
  const element = document.createElement('div');
  element.innerHTML = _.join(['Hello', 'Webpack'], ' ');
  return element;
}

document.body.appendChild(component());

3:创建配置文件,配置相关信息

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

4:执行打包命令

npx webpack

三:图解

四:编译原理过程

1:初始化阶段:主要是产生一个最终的配置

此阶段,webpack会将Cli参数,配置文件、默认配置进行一个融合,形成一个最终完整的配置对象

采用三方库yargs完成对配置的融合,为接下来编译阶段做准备

2:编译阶段

需要读取文件进行分析,所以这也是webpack在node中执行原因

第一步:创建chunk,在内部构建过程中的一个概念,说白了就是一个块,通过入口来分析所有的依赖关系的文件都是chunk

默认情况下,只有一个chuank,(常说main),有两个参数name和id

name:就是chuank文件名,默认就是main

id:唯一编号,开发环境跟name相同,生产环境时一个数字从0开始

第二步:构建所有的依赖模块,根据入口模块进行开始构建,通过递归的方式,进行遍历查找所有依赖关系,形成一个列表,对应名称和文件内容(转换后代码)

并且针对文件进行读取变成抽象语法树进行比较,是否存在,保存在dependencies数组中

第三步:产生chunk,构建资源assets,会根据配置为chunk生成一个资源列表,也就是说的最终的文件的文件名和文件内容

chunk hash是根据chunk assets内容生成的一个hash字符串

第四步:合并chunk,进行输出,将多个chunk的assets合并到一起,产生一个总的hash


3:输出阶段(emit),利用node中的fs模块,根据编译产生总的assets,来创建对应的文件写入

五:代码演示编译过程

第一步:从入口文件进行分析,读取,根据入口文件,判断当前这个模块是否加载过,在所谓的列表里面是否有记录,

//模块名:
./src/index.js (未加载状态)

//模块内容:
console.log("index");
require("./a");
require("./b");

第二步:如果没有,则进行下一步,进行加载,如果有,则说明加载过了,有记录

检查 ./src/index.js 模块,发现该模块并未加载过

第三步:读取文件的内容,内容其实就是js代码,但是node读取出来是字符串

//读取内容(字符串)
console.log("index");
require("./a");
require("./b");

第四步:对模块进行语法分析,,遍历找到所有的依赖,最后生成AST抽象语法树

第五步:将分析出来的依赖记录到dependencies数组中,只是记录依赖文件位置

标识入口文件依赖了下面的文件

["./src/a.js","./src/b.js"]

第六步:替换依赖函数,就是把依赖的地方全部变成一种代码格式,把依赖的模块变成内置的模块id

console.log("index");
_webpack_require("./src/a.js");
_webpack_require("./src/b.js");

第七步:将替换后的代码转换为模块代码,保存到模块记录表中

第八步:因为入口文件依赖其他文件,就进行递归循环查找比对,如果有,则跳过,没有则添加,

第九步:当所有依赖都构建完成后,接下来就根据模块资源列表,转换成文件列表



六:总结

1:术语:

module:模块,分割代码单元,webpack中可以是任何的文件,不限于js

chunk:内部构建的快,一个chunk包含多个模块,主要是通过入口模快通过依赖分析得来

bundle:chunk构建模块后生成的资源清单,也叫捆的概念,可以认为是最终生成的文件

hash:最终的资源清单所有内容联动生成的hash值,(会生成一个固定的长度的字符串,只要内容不变,hash值就不变,内容变化后才会变)

chunkhash:内容联合生成的hash值

chunkname:名称,如果没有配置默认main

id:通常指chunk唯一的编号,开发环境跟name相同,生产环境时一个数字从0开始

2:图解