欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vite的createServer啟動源碼解析

 更新時間:2022年09月15日 17:16:05   作者:有人我  
這篇文章主要為大家介紹了Vite的createServer啟動源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

啟動Vite的createServer

為了能夠了解vite里面運行了什么,通過執(zhí)行單步調(diào)試能夠更加直觀的知道Vite具體內(nèi)容。所以這次我們來試著啟動Vite的createServer,并進行調(diào)試。

通過vite3安裝一個vue的工程

進入工作目錄,運行下面的代碼,項目名稱隨意,語言用Vue。

npm create vite

進入工程目錄安裝依賴

添加斷點并開啟調(diào)試

通過vscode打開剛剛生成的項目,通過上一章的內(nèi)容,可以知道程序的入口是cli.js。所以首先打開node_modules里面vite文件夾下面找到cli.js。找到運行dev時候的主要代碼createServer,并打上斷點。

開啟vsCode的調(diào)試功能,JavaScript Debug Terminal

執(zhí)行Dev命令,便可以運行到斷點位置。

yarn run dev

邊調(diào)試邊理解代碼

進入CreateServer內(nèi)部代碼,稍微加了一點注釋,代碼如下:

async function createServer(inlineConfig = {}) {
    // 獲取config,用戶自定義的vite.config.js/ts,還有vite的默認配置
    const config = await resolveConfig(inlineConfig, 'serve', 'development');
    const { root, server: serverConfig } = config;
    // http相關(guān)的配置
    const httpsOptions = await resolveHttpsConfig(config.server.https);
    // serverConfig就是vite.config里面的server對象,參照上main的代碼,middlewareMode包含html和ssr 2個選項
    const { middlewareMode } = serverConfig;
    const resolvedWatchOptions = resolveChokidarOptions({
        disableGlobbing: true,
        ...serverConfig.watch
    });
    // connect是一個中間件的類庫,https://www.jianshu.com/p/d606c1059c51
    const middlewares = connect();
    const httpServer = middlewareMode
        ? null
        : await resolveHttpServer(serverConfig, middlewares, httpsOptions);
    const ws = createWebSocketServer(httpServer, config, httpsOptions);
    if (httpServer) {
        setClientErrorHandler(httpServer, config.logger);
    }
    // 監(jiān)聽文件變化
    const watcher = chokidar.watch(path$n.resolve(root), resolvedWatchOptions);
    // 創(chuàng)建模塊圖紙,記錄每個模塊之間的依賴關(guān)系
    const moduleGraph = new ModuleGraph((url, ssr) => container.resolveId(url, undefined, { ssr }));
    // 創(chuàng)建PluginContainer
    const container = await createPluginContainer(config, moduleGraph, watcher);
    // 關(guān)系HttpServer的時候的處理
    const closeHttpServer = createServerCloseFn(httpServer);
    let exitProcess;
    // 創(chuàng)建Server對象
    const server = {
        config,
        middlewares,
        httpServer,
        watcher,
        pluginContainer: container,
        ws,
        moduleGraph,
        resolvedUrls: null,
        ssrTransform(code, inMap, url, originalCode = code) {
            return ssrTransform(code, inMap, url, originalCode, server.config);
        },
        transformRequest(url, options) {
            return transformRequest(url, server, options);
        },
        transformIndexHtml: null,
        async ssrLoadModule(url, opts) {
            if (isDepsOptimizerEnabled(config, true)) {
                await initDevSsrDepsOptimizer(config, server);
            }
            await updateCjsSsrExternals(server);
            return ssrLoadModule(url, server, undefined, undefined, opts?.fixStacktrace);
        },
        ssrFixStacktrace(e) {
            if (e.stack) {
                const stacktrace = ssrRewriteStacktrace(e.stack, moduleGraph);
                rebindErrorStacktrace(e, stacktrace);
            }
        },
        ssrRewriteStacktrace(stack) {
            return ssrRewriteStacktrace(stack, moduleGraph);
        },
        async listen(port, isRestart) {
            await startServer(server, port, isRestart);
            if (httpServer) {
                server.resolvedUrls = await resolveServerUrls(httpServer, config.server, config);
            }
            return server;
        },
        // 關(guān)閉server時調(diào)用的函數(shù)
        async close() {
            if (!middlewareMode) {
                process.off('SIGTERM', exitProcess);
                if (process.env.CI !== 'true') {
                    process.stdin.off('end', exitProcess);
                }
            }
            await Promise.all([
                watcher.close(),
                ws.close(),
                container.close(),
                closeHttpServer()
            ]);
            server.resolvedUrls = null;
        },
        printUrls() {
            if (server.resolvedUrls) {
                printServerUrls(server.resolvedUrls, serverConfig.host, config.logger.info);
            }
            else if (middlewareMode) {
                throw new Error('cannot print server URLs in middleware mode.');
            }
            else {
                throw new Error('cannot print server URLs before server.listen is called.');
            }
        },
        async restart(forceOptimize) {
            if (!server._restartPromise) {
                server._forceOptimizeOnRestart = !!forceOptimize;
                server._restartPromise = restartServer(server).finally(() => {
                    server._restartPromise = null;
                    server._forceOptimizeOnRestart = false;
                });
            }
            return server._restartPromise;
        },
        _ssrExternals: null,
        _restartPromise: null,
        _importGlobMap: new Map(),
        _forceOptimizeOnRestart: false,
        _pendingRequests: new Map()
    };
    // vite.config里面申明了transformIndexHtml,在會被調(diào)用。
    server.transformIndexHtml = createDevHtmlTransformFn(server);
    if (!middlewareMode) {
        exitProcess = async () => {
            try {
                await server.close();
            }
            finally {
                process.exit();
            }
        };
        // 進程收到這個信號時候,會調(diào)用exitProcess方法
        process.once('SIGTERM', exitProcess);
        if (process.env.CI !== 'true') {
            process.stdin.on('end', exitProcess);
        }
    }
    const { packageCache } = config;
    const setPackageData = packageCache.set.bind(packageCache);
    packageCache.set = (id, pkg) => {
        if (id.endsWith('.json')) {
            watcher.add(id);
        }
        return setPackageData(id, pkg);
    };
    // 文件發(fā)生變化時處理
    watcher.on('change', async (file) => {
        file = normalizePath$3(file);
        if (file.endsWith('/package.json')) {
            return invalidatePackageData(packageCache, file);
        }
        // invalidate module graph cache on file change
        // 模型關(guān)系圖變化時處理
        moduleGraph.onFileChange(file);
        if (serverConfig.hmr !== false) {
            try {
                await handleHMRUpdate(file, server);
            }
            catch (err) {
                ws.send({
                    type: 'error',
                    err: prepareError(err)
                });
            }
        }
    });
    watcher.on('add', (file) => {
        handleFileAddUnlink(normalizePath$3(file), server);
    });
    watcher.on('unlink', (file) => {
        handleFileAddUnlink(normalizePath$3(file), server);
    });
    if (!middlewareMode && httpServer) {
        httpServer.once('listening', () => {
            // update actual port since this may be different from initial value
            serverConfig.port = httpServer.address().port;
        });
    }
    // apply server configuration hooks from plugins
    // 給plugin配置hook鉤子
    const postHooks = [];
    for (const hook of config.getSortedPluginHooks('configureServer')) {
        postHooks.push(await hook(server));
    }
    // Internal middlewares ------------------------------------------------------
    // request timer
    if (process.env.DEBUG) {
        middlewares.use(timeMiddleware(root));
    }
    // cors (enabled by default)
    const { cors } = serverConfig;
    if (cors !== false) {
        middlewares.use(lib$1.exports(typeof cors === 'boolean' ? {} : cors));
    }
    // proxy
    const { proxy } = serverConfig;
    if (proxy) {
        middlewares.use(proxyMiddleware(httpServer, proxy, config));
    }
    // base
    const devBase = config.base;
    if (devBase !== '/') {
        middlewares.use(baseMiddleware(server));
    }
    // open in editor support
    middlewares.use('/__open-in-editor', launchEditorMiddleware());
    // serve static files under /public
    // this applies before the transform middleware so that these files are served
    // as-is without transforms.
    // 最外層public目錄的配置
    if (config.publicDir) {
        middlewares.use(servePublicMiddleware(config.publicDir, config.server.headers));
    }
    // main transform middleware
    // ??最核心的中間件--重點--javaScript的編譯
    middlewares.use(transformMiddleware(server));
    // serve static files
    // 管理靜態(tài)資源的中間件
    middlewares.use(serveRawFsMiddleware(server));
    middlewares.use(serveStaticMiddleware(root, server));
    // spa fallback
    if (config.appType === 'spa') {
        middlewares.use(spaFallbackMiddleware(root));
    }
    // run post config hooks
    // This is applied before the html middleware so that user middleware can
    // serve custom content instead of index.html.
    // 自定義的中間件,這里運行
    postHooks.forEach((fn) => fn && fn());
    if (config.appType === 'spa' || config.appType === 'mpa') {
        // transform index.html
        middlewares.use(indexHtmlMiddleware(server));
        // handle 404s
        // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
        middlewares.use(function vite404Middleware(_, res) {
            res.statusCode = 404;
            res.end();
        });
    }
    // error handler
    // 處理錯誤
    middlewares.use(errorMiddleware(server, middlewareMode));
    let initingServer;
    let serverInited = false;
    const initServer = async () => {
        if (serverInited) {
            return;
        }
        if (initingServer) {
            return initingServer;
        }
        initingServer = (async function () {
            await container.buildStart({});
            if (isDepsOptimizerEnabled(config, false)) {
                // non-ssr
                await initDepsOptimizer(config, server);
            }
            initingServer = undefined;
            serverInited = true;
        })();
        return initingServer;
    };
    if (!middlewareMode && httpServer) {
        // overwrite listen to init optimizer before server start
        const listen = httpServer.listen.bind(httpServer);
        httpServer.listen = (async (port, ...args) => {
            try {
                await initServer();
            }
            catch (e) {
                httpServer.emit('error', e);
                return;
            }
            return listen(port, ...args);
        });
    }
    else {
        await initServer();
    }
    return server;
}

以上就是Vite的createServer啟動源碼解析的詳細內(nèi)容,更多關(guān)于Vite createServer啟動的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue中v-bind和v-model的區(qū)別詳解

    vue中v-bind和v-model的區(qū)別詳解

    v-bind和v-model是Vue.js中的兩個常用指令,它們在功能和用途上有一些區(qū)別,接下來小編就給大家具有講講vue中v-bind和v-model區(qū)別,感興趣的同學(xué)跟著小編一起來看看吧
    2023-08-08
  • Vue3父子組件相互調(diào)用方法舉例詳解

    Vue3父子組件相互調(diào)用方法舉例詳解

    這篇文章主要給大家介紹了關(guān)于Vue3父子組件相互調(diào)用方法的相關(guān)資料,vue中我們常常用到組件,那么組件中互相調(diào)用也是經(jīng)常遇到的,需要的朋友可以參考下
    2023-08-08
  • Vue表單校驗validate和validateField的使用及區(qū)別詳解

    Vue表單校驗validate和validateField的使用及區(qū)別詳解

    validateField?和?validate?都可以用于表單驗證,但是它們的作用有所不同,下面這篇文章主要給大家介紹了關(guān)于Vue表單校驗validate和validateField的使用及區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • vue-router的鉤子函數(shù)用法實例分析

    vue-router的鉤子函數(shù)用法實例分析

    這篇文章主要介紹了vue-router的鉤子函數(shù)用法,結(jié)合實例形式分析了vue路由鉤子分類及vue-router鉤子函數(shù)相關(guān)使用技巧,需要的朋友可以參考下
    2019-10-10
  • Vue使用PDF.js實現(xiàn)瀏覽pdf文件功能

    Vue使用PDF.js實現(xiàn)瀏覽pdf文件功能

    這篇文章主要為大家詳細介紹了Vue如何使用PDF.js實現(xiàn)瀏覽pdf文件功能,文中的實現(xiàn)步驟講解詳細,具有一定的借鑒價值,需要的可以參考一下
    2023-04-04
  • vue+springboot實現(xiàn)登錄功能

    vue+springboot實現(xiàn)登錄功能

    這篇文章主要為大家詳細介紹了vue+springboot實現(xiàn)登錄功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Vue實現(xiàn)移除數(shù)組中特定元素的方法小結(jié)

    Vue實現(xiàn)移除數(shù)組中特定元素的方法小結(jié)

    這篇文章主要介紹了Vue如何優(yōu)雅地移除數(shù)組中的特定元素,文中介紹了單個去除和批量去除的操作方法,并通過代碼示例講解的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2024-03-03
  • 詳解Vue路由開啟keep-alive時的注意點

    詳解Vue路由開啟keep-alive時的注意點

    這篇文章主要介紹了詳解Vue路由開啟keep-alive時的注意點,非常具有實用價值,有興趣的朋友可以了解一下
    2017-06-06
  • vue項目中做編輯功能傳遞數(shù)據(jù)時遇到問題的解決方法

    vue項目中做編輯功能傳遞數(shù)據(jù)時遇到問題的解決方法

    這篇文章主要介紹了vue項目中做編輯功能傳遞數(shù)據(jù)時遇到問題的解決方法,vue父組件向子組件傳遞數(shù)據(jù)的問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • axios中如何進行同步請求(async+await)

    axios中如何進行同步請求(async+await)

    這篇文章主要介紹了axios中如何進行同步請求(async+await),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09

最新評論