vite 5.0.12
当在命令行输入 vite
,就可以在当前目录下启动 Vite 开发服务器。
在vite的 package.json 文件中,有
"bin": {
"vite": "bin/vite.js"
}
vite 命令对应的可执行文件为 bin 子目录下的 vite.js。Npm会寻找这个文件,在node_modules/.bin/
目录下建立符号链接。在上面的例子中,vite.js会建立符号链接node_modules/.bin/vite
。由于node_modules/.bin/
目录会在运行时加入系统的PATH变量,因此在运行npm时,就可以不带路径,直接通过命令来调用脚本。这个被调用的脚本就是 vite/bin/vite.js
通过 vite --debug
命令,开启调试,进入vite/bin/vite.js,会走到start函数
// vite/bin/vite.js
function start() {
return import('../dist/node/cli.js')
}
进入 cli.js这个文件
// /vite/dist/node/cli.js
class CAC extends EventEmitter {
parse(){
this.runMatchedCommand();
}
runMatchedCommand() {
return command.commandAction.apply(this, actionArgs);
}
}
const cac = (name = "") => new CAC(name);
const cli = cac('vite');
// dev相关命令
cli
.command('[root]', 'start dev server') // default command
.alias('serve') // the command is called 'serve' in Vite's API
.alias('dev') // alias to align with the script name
.option('--host [host]', `[string] specify hostname`, { type: [convertHost] })
.option('--port <port>', `[number] specify port`)
.option('--open [path]', `[boolean | string] open browser on startup`)
.option('--cors', `[boolean] enable CORS`)
.option('--strictPort', `[boolean] exit if specified port is already in use`)
.option('--force', `[boolean] force the optimizer to ignore the cache and re-bundle`)
.action(async (root, options) => {
// 回调
// 调用command.commandAction触发此回调
const { createServer } = await import('./chunks/dep-9A4-l-43.js').then(function (n) { return n.A; });
try {
const server = await createServer({
root,
base: options.base,
mode: options.mode,
configFile: options.config,
logLevel: options.logLevel,
clearScreen: options.clearScreen,
optimizeDeps: { force: options.force },
server: cleanOptions(options),
});
}
// 启动服务器
await server.listen();
// ...
}
//...
cli.parse();
在命令行执行 vite,会执行cli.parse(),在parse()里面执行this.runMatchedCommand()
,
runMatchedCommand() {
return command.commandAction.apply(this, actionArgs);
}
command.commandAction就是传入action的回调,在回调里面创建server,启动监听
createServer
// /vite/dist/node/chunks/dep-9A4-l-43.js
function createServer(inlineConfig = {}) {
return _createServer(inlineConfig, { ws: true });
}
async function _createServer(inlineConfig = {}, options) {
const middlewares = connect$1();
const httpServer = await resolveHttpServer(serverConfig, middlewares, httpsOptions);
let server = {
httpServer,
// 监听启动
async listen(port, isRestart) {
// 调用 startServer,监听启动
await startServer(server, port);
return server;
},
}
return server
}
async function resolveHttpServer({ proxy }, app, httpsOptions) {
if (!httpsOptions) {
const { createServer } = await import('node:http');
return createServer(app);
}
}
async function startServer(server, inlinePort) {
const httpServer = server.httpServer;
// 调用 httpServerStart
const serverPort = await httpServerStart(httpServer, {
port,
strictPort: options.strictPort,
host: hostname.host,
logger: server.config.logger,
});
}
async function httpServerStart(httpServer, serverOptions) {
let { port, strictPort, host, logger } = serverOptions;
return new Promise((resolve, reject) => {
// node:http 创建的httpServer启动listen
httpServer.listen(port, host, () => {
httpServer.removeListener('error', onError);
resolve(port);
});
});
}
参考
原文链接:https://juejin.cn/post/7338614904393924659 作者:陵南