前言 此系列文章作为笔记,用于记录分析 webpack
源码主流程的过程。
概览 目录 根据 webpack
构建流程及相关,本系列文章一共分为以下章节:
配置初始化
编译前的准备
reslove 前的准备
reslove 流程
构建 module(上)
构建 module(下)
生成 chunk
优化 chunk
资源的构建
文件的生成
打包后文件解析
watch
webpack 优化
流程图 webpack
构建流程图:
本系列代码环境 1 2 3 4 5 6 7 8 9 10 11 "devDependencies": { "@babel/core": "^7.7.5", "@babel/preset-env": "^7.7.6", "@fe_korey/test-loader": "^1.0.0", "babel-loader": "^8.0.6", "html-webpack-plugin": "^3.2.0" }, "dependencies": { "webpack": "^4.41.2", "webpack-cli": "^3.3.10" }
版本不同,源码略微有差异。
本项目 demo
开源在github ,欢迎交流学习。
分析源码前的一系列准备工作 采用 vscode 来打断点调试分析。
配置 vscode 1 2 3 4 5 6 7 8 9 10 11 12 13 "configurations": [ { "type" : "node" , "request" : "launch" , "name" : "Launch Program" , "runtimeExecutable" : "npm" , "runtimeArgs" : ["run" , "debug" ], "port" : 5858 , "console" : "externalTerminal" , "skipFiles" : ["<node_internals>/**/*.js" ] } ]
这些配置是怎么来的?
配置 npm script 1 2 3 "scripts": { "debug": "node --inspect-brk=5858 ./node_modules/.bin/webpack" },
了解 webpack 的插件架构 webpack
从配置初始化到打包完成定义了一个生命周期,在这个生命周期中的每一个阶段定义一些不同的功能。webpack
的流程同样也是一个事件驱动的架构,利用插件系统 tapable
,通过 发布订阅事件
来实现所有内部的,外部扩展的功能。
了解 webpack 的核心模块 webpack
的构建是通过 Compiler
控制构建流程,Compilation
解析,ModuleFactory
生成模块,Parser
解析源码,Template
渲染代码,最后输出打包后的文件。
了解 tapable tapable
本质就是一个事件发布订阅机制,支持同步异步,使用xxx.tap
之类的来事件订阅 ,使用xxx.call
之类的来进行事件发布 。 相关文档查阅:
demo 准备 npm 安装 1 2 3 npm i webpack-cli webpack npm i @babel/core @babel/preset-env babel-loader -D npm i @fe_korey/test-loader -D
demo 文件 我们以 development
模式为例,暂时忽略支线剧情,只分析探索 webpack
的打包主流程。
1 2 3 4 5 import { add } from 'Src/b' ;import ('./c.js' ).then((m ) => m.sub(2 , 1 ));const a = 1 ;add(3 , 2 + a);
1 2 3 4 5 6 7 8 import { mul } from '@fe_korey/test-loader?number=20!Src/e' ;export function add (a, b ) { return a + b + mul(10 , 5 ); } export function addddd (a, b ) { return a + b * b; }
1 2 3 4 5 6 import { mul } from 'Src/d' ;import ('./b.js' ).then((m ) => m.add(200 , 100 ));export function sub (a, b ) { return a - b + mul(100 , 50 ); }
1 2 3 4 5 export function mul (a, b ) { const d = 10000 ; return a * b + d; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 var path = require ('path' );module .exports = { entry: { bundle: './src/a.js' , }, devtool: 'none' , output: { path: __dirname + '/dist' , filename: '[name].[chunkhash:4].js' , chunkFilename: '[name].[chunkhash:8].js' , }, mode: 'development' , resolve: { alias: { Src: path.resolve(__dirname, 'src/' ), }, }, module : { rules: [ { test: /\.js$/ , use: [ { loader: 'babel-loader' , }, ], }, ], }, };
1 2 3 4 module .exports = { presets: ['@babel/env' ], };
一颗坚定且耐操的心 为什么要阅读它?
因为可以让我们更好的理解海量配置,知道每一个配置在打包的具体哪个环节
在对构建流程进行优化时能更清楚的根据过程思考优化点
还可以学习下在这种大型项目里,如何实现稳定的架构和良好的扩展性
对自定义开发一些 plugin
和 loader
有更深刻的理解
了解它的一些代码设计方式能给我们的日常搬砖带来一些新的启发
最重要的还是想满足自己的好奇欲,想知道在这犀利的打包背后,到底是怎么实现的。
webpack
里包含数不清的变量和钩子,海量插件,这些足以让你怀疑人生,请务必保持一颗耐操的心。 一切准备就绪后,进入 vscode
的调试模式!