webpack原理篇(五十一):webpack启动过程分析
Posted 凯小默
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack原理篇(五十一):webpack启动过程分析相关的知识,希望对你有一定的参考价值。
说明
玩转 webpack 学习笔记
开始:从 webpack 命令行说起
通过 npm scripts 运行 webpack
- 开发环境:npm run dev
- 生产环境:npm run build
通过 webpack 直接运行
webpack entry.js bundle.js
查找 webpack 入口文件
在命令行运行以上命令后,npm会让命令行工具进入 node_modules\\.bin
目录查找是否存在 webpack.sh
或者 webpack.cmd
文件,如果存在,就执行,不存在,就抛出错误。
实际的入口文件是:node_modules\\webpack\\bin\\webpack.js
分析 webpack 的入口文件:webpack.js
源代码如下:
#!/usr/bin/env node
// @ts-ignore
// 1# 正常执行返回
process.exitCode = 0;
/**
* @param string command process to run
* @param string[] args commandline arguments
* @returns Promise<void> promise
*/
// 2# 运行某个命令
const runCommand = (command, args) =>
const cp = require("child_process");
return new Promise((resolve, reject) =>
const executedCommand = cp.spawn(command, args,
stdio: "inherit",
shell: true
);
executedCommand.on("error", error =>
reject(error);
);
executedCommand.on("exit", code =>
if (code === 0)
resolve();
else
reject();
);
);
;
/**
* @param string packageName name of the package
* @returns boolean is the package installed?
*/
// 3# 判断某个包是否安装
const isInstalled = packageName =>
try
require.resolve(packageName);
return true;
catch (err)
return false;
;
/**
* @typedef Object CliOption
* @property string name display name
* @property string package npm package name
* @property string binName name of the executable file
* @property string alias shortcut for choice
* @property boolean installed currently installed?
* @property boolean recommended is recommended
* @property string url homepage
* @property string description description
*/
/** @type CliOption[] */
// 4# webpack 可用 cli webpack-cli(功能丰富一点) 跟 webpack-command
const CLIs = [
name: "webpack-cli",
package: "webpack-cli",
binName: "webpack-cli",
alias: "cli",
installed: isInstalled("webpack-cli"),
recommended: true,
url: "https://github.com/webpack/webpack-cli",
description: "The original webpack full-featured CLI."
,
name: "webpack-command",
package: "webpack-command",
binName: "webpack-command",
alias: "command",
installed: isInstalled("webpack-command"),
recommended: false,
url: "https://github.com/webpack-contrib/webpack-command",
description: "A lightweight, opinionated webpack CLI."
];
// 5# 判断两个是否都安装了
const installedClis = CLIs.filter(cli => cli.installed);
// 6# 根据安装的数量进行处理
if (installedClis.length === 0)
const path = require("path");
const fs = require("fs");
const readLine = require("readline");
let notify =
"One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:";
for (const item of CLIs)
if (item.recommended)
notify += `\\n - $item.name ($item.url)\\n $item.description`;
console.error(notify);
const isYarn = fs.existsSync(path.resolve(process.cwd(), "yarn.lock"));
const packageManager = isYarn ? "yarn" : "npm";
const installOptions = [isYarn ? "add" : "install", "-D"];
console.error(
`We will use "$packageManager" to install the CLI via "$packageManager $installOptions.join(
" "
)".`
);
const question = `Do you want to install 'webpack-cli' (yes/no): `;
const questionInterface = readLine.createInterface(
input: process.stdin,
output: process.stderr
);
questionInterface.question(question, answer =>
questionInterface.close();
const normalizedAnswer = answer.toLowerCase().startsWith("y");
if (!normalizedAnswer)
console.error(
"You need to install 'webpack-cli' to use webpack via CLI.\\n" +
"You can also install the CLI manually."
);
process.exitCode = 1;
return;
const packageName = "webpack-cli";
console.log(
`Installing '$packageName' (running '$packageManager $installOptions.join(
" "
) $packageName')...`
);
runCommand(packageManager, installOptions.concat(packageName))
.then(() =>
require(packageName); //eslint-disable-line
)
.catch(error =>
console.error(error);
process.exitCode = 1;
);
);
else if (installedClis.length === 1)
const path = require("path");
const pkgPath = require.resolve(`$installedClis[0].package/package.json`);
// eslint-disable-next-line node/no-missing-require
const pkg = require(pkgPath);
// eslint-disable-next-line node/no-missing-require
require(path.resolve(
path.dirname(pkgPath),
pkg.bin[installedClis[0].binName]
));
else
console.warn(
`You have installed $installedClis
.map(item => item.name)
.join(
" and "
) together. To work with the "webpack" command you need only one CLI package, please remove one of them or use them directly via their binary.`
);
// @ts-ignore
process.exitCode = 1;
启动后的结果
webpack 最终找到 webpack-cli (webpack-command) 这个 npm 包,并且执行 CLI。
以上是关于webpack原理篇(五十一):webpack启动过程分析的主要内容,如果未能解决你的问题,请参考以下文章
webpack原理篇(五十七):webpack流程:文件生成
webpack原理篇(五十四):Tapable是如何和webpack进行关联起来的?
webpack原理篇(五十二):webpack-cli源码阅读
webpack原理篇(五十六):webpack流程:模块构建和chunk生成阶段