"webpack"命令启动过程

954 阅读2分钟

执行webpack命令,发生了什么?

想要了解当我们在终端中输入webpack的时候,到底做了什么?首先我们可以回顾下这篇文章 npm scripts 使用指南。 从文章中我们知道,我们可以直接在终端执行webpack命令,意味着我们在项目根目录下的node_modules/bin下能找到webpack.js

image.png

这里以Mac为例,node_modules/binwebpack.js是一个软链,源路径是在node_modules/webpack/bin/webpack.js。配置webpack命令的入口文件在node_modules/webpack目录下的package.json


"bin": {

    "webpack": "bin/webpack.js"

  }

意味着终端输入webpack命令执行的文件是"bin/webpack.js"。这个文件的起始行是:#!/usr/bin/env node表示这个脚本是node的解释程序。

执行过程如下:

  1. 创建一个cli对象

        const cli = {
    
            name: "webpack-cli",
    
            package: "webpack-cli",
    
            binName: "webpack-cli",
    
            installed: isInstalled("webpack-cli"),
    
            url: "https://github.com/webpack/webpack-cli"
    
        };
    
  2. 判断cli是否安装,从当前目录下的node_modules开始遍历查找webpack-cli目录,直到根目录。如果找到,返回true。否则返回false。

        const isInstalled = packageName => {
            const path = require("path");
            const fs = require("graceful-fs");
            let dir = __dirname;
            do {
                if (fs.statSync(path.join(dir, "node_modules", packageName)).isDirectory()) return true
            } while (dir !== (dir = path.dirname(dir)));
            return false;
        };
    
  3. 如果已经安装webpack-cli,则执行runCli(cli),这个函数就是找到webpack-cli/package.json中的bin配置,并执行该入口文件:

        "bin": {
            "webpack-cli": "bin/cli.js"
        },
    
     const runCli = cli => {
    
        const path = require("path");
    
        const pkgPath = require.resolve(`${cli.package}/package.json`);
    
        const pkg = require(pkgPath);
    
        require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
    
        };
    
    
  4. 否则命令行会提示,Do you want to install 'webpack-cli' (yes/no):

    • 如果输入y,会调用runCommand自动安装webpack-cli包,安装成功后,执行runCli(cli)
    • 否则会报错,让你自己安装并结束运行脚本。
  5. 安装webpack-cli包,runCommand函数中传入的是npm install -D或者yarn add -D,通过启动一个子进程来执行命令。runCommand执行成功后会执行runCli

        const runCommand = (command, args) => {
    
            const cp = require("child_process");
    
            return new Promise((resolve, reject) => {
    
                const executedCommand = cp.spawn(command, args, {
    
                    stdio: "inherit",
    
                    shell: true
    
                });
                resolve()
            })
       })
    

本文是针对我所了解的执行webpack命令的基本流程,本文之后会继续更新runCli的具体执行过程以及webpack-cli又做了什么。

文章中如有不妥之处,欢迎指正。