likes
comments
collection
share

webpack 4 源码主流程分析(一):前言及总流程概览

作者站长头像
站长
· 阅读数 135

原文首发于 blog.flqin.com。如有错误,请联系笔者。分析码字不易,转载请表明出处,谢谢!

前言

此系列文章作为笔记,用于记录分析 webpack 源码主流程的过程。

概览

目录

根据 webpack 构建流程及相关,本系列文章一共分为以下章节:

流程图

webpack 构建流程图:

webpack 4 源码主流程分析(一):前言及总流程概览

本系列代码环境

  "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

//launch.json
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "debug"],
      "port": 5858,
      "console": "externalTerminal",
      "skipFiles": ["<node_internals>/**/*.js"]
    }
  ]

这些配置是怎么来的?

配置 npm script

  "scripts": {
    "debug": "node --inspect-brk=5858 ./node_modules/.bin/webpack"
  },

了解 webpack 的插件架构

webpack 从配置初始化到打包完成定义了一个生命周期,在这个生命周期中的每一个阶段定义一些不同的功能。webpack 的流程同样也是一个事件驱动的架构,利用插件系统 tabpable,通过 发布订阅事件 来实现所有内部的,外部扩展的功能。

了解 webpack 的核心模块

webpack 的构建是通过 Compiler 控制构建流程,Compilation 解析,ModuleFactory 生成模块,Parser 解析源码,Template 渲染代码,最后输出打包后的文件。

了解 tapable

tabpable 本质就是一个事件发布订阅机制,支持同步异步,使用xxx.tap之类的来事件订阅,使用xxx.call之类的来进行事件发布。 相关文档查阅:

demo 准备

npm 安装

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 的打包主流程。

//src/a.js
import { add } from 'Src/b';
import('./c.js').then(m => m.sub(2, 1));
const a = 1;
add(3, 2 + a);
//src/b.js
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;
}
//src/c.js
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);
}
//src/d.js
export function mul(a, b) {
  const d = 10000;
  return a * b + d;
}
//webpack.config.js
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'
          }
        ]
      }
    ]
  }
};
//babel.config.js
module.exports = {
  presets: ['@babel/env']
};

一颗坚定且耐操的心

为什么要阅读它?

  • 因为可以让我们更好的理解海量配置,知道每一个配置在打包的具体哪个环节
  • 在对构建流程进行优化时能更清楚的根据过程思考优化点
  • 还可以学习下在这种大型项目里,如何实现稳定的架构和良好的扩展性
  • 对自定义开发一些 pluginloader 有更深刻的理解
  • 了解它的一些代码设计方式能给我们的日常搬砖带来一些新的启发

最重要的还是想满足自己的好奇欲,想知道在这犀利的打包背后,到底是怎么实现的。

webpack 里包含数不清的变量和钩子,海量插件,这些足以让你怀疑人生,请务必保持一颗耐操的心。 一切准备就绪后,进入 vscode 的调试模式!

转载自:https://juejin.cn/post/6844904047221145613
评论
请登录