<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                >[success] # webpack 啟動做了什么 ~~~ 1.在使用webpack 的時候我們,我們一般會在'npm scripts' 配置好一些執行指令,在我們 執行這些指令的時候webpack做了什么?我們可以看一下不是簡寫的運行指令 '.\node_modules\.bin\webpack' 2.指令輸入后進入'node\_modules\.bin' 目錄 查找是否存在 webpack.sh 或者 webpack.cmd 文件, 如果存在,就執行,不 存在,就拋出錯誤 3.我是windows 系統來一下看一下' webpack.cmd'里面寫了什么 @IF EXIST "%~dp0\node.exe" ( "%~dp0\node.exe" "%~dp0\..\webpack\bin\webpack.js" %* ) ELSE ( @SETLOCAL @SET PATHEXT=%PATHEXT:;.JS;=;% node "%~dp0\..\webpack\bin\webpack.js" %* ) 4.發現他還會接著去執行'node_modules\webpack\bin\webpack.js',因此這里才是文件的實際入口 ~~~ >[info] ## webpack.js 文件做了什么 ~~~ 1.整個文件打開后發現整個代碼可以分為六大塊 ~~~ ~~~ js // node_modules/webpack/bin/webpack.js // 1.正常執行返回 process.exitCode = 0; // 2.運行某個命令 const runCommand = (command, args) => {...} // 3.判斷某個包是否安裝 const isInstalled = packageName => {...} // 4.webpack可用的CLI:webpacl-cli和webpack-command const CLIs = {...} // 5.判斷是否兩個CLI是否安裝了 const installedClis = CLIs.filter(cli=>cli.installed); // 6.根據安裝數量進行處理 if (installedClis.length === 0) {...} else if (installedClis.length === 1) {...} else {...} ~~~ >[danger] ##### 第一塊process.exitCode 分析 ~~~ 1.process.exitCode 為 0,代表程序正常運行;非 0,則代表程序報錯。 注:Node API 文檔中明確寫到,process.exit() 方法以退出狀態 code 指示 Node.js 同步地終止進程。 如果省略 code,則使用成功代碼 0 或 process.exitCode 的值 (如果已設置)退出。 ~~~ >[danger] ##### runCommand 運行某個命令 ~~~ 1.通過源碼發現整個'runCommand' 方法有兩個參數, 1.1.'command' 要運行的進程在這個入口文件源碼里指的是用'yarn' 還是'npm',當我們看到 '安裝處置'這里的邏輯時候就會發現里面有一段參數'const packageManager = isYarn ? "yarn" : "npm";' 1.2.'args' 這個參數是數組,當我們看到 '安裝處置'這里的邏輯時候會發現實際他參數是 'const installOptions = [isYarn ? "add" : "install", "-D"];' 2.其實通過這兩個參數我們能發現,這個就是幫我們拼接安裝包指令的方法,具體他會安裝什么包還要往下看 3.現在這段代碼中'require("child_process")' 是整個安裝過程核心,這個方法是做什么的? 這是一個提供了衍生子進程模塊,下面代碼中用到的'spawn'方法第一個 參數'要運行的命令', 第二個參數'字符串參數的列表' ,第三個參數'是一些配置項',具體的以后研究 注:相當于會拼成 一個'npm install -D 報名' ~~~ [nodejs 文檔對child_process說明](http://nodejs.cn/api/child_process.html) [spawn方法的說明](http://nodejs.cn/api/child_process.html#child_process_child_process_spawn_command_args_options) ~~~ /** * @param {string} command process to run * @param {string[]} args commandline arguments * @returns {Promise<void>} promise */ 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(); } }); }); }; ~~~ >[danger] ##### isInstalled 判斷某個包是否安裝 ~~~ 1.這里需要知道的api'require.resolve',這個方法主要做了? 1.1.使用內部的 require() 機制查詢模塊的位置,此操作只返回解析后的文件名,不會加載該模塊。 如果找不到模塊,則會拋出 MODULE_NOT_FOUND 錯誤。 這里要注意的是如果你寫的只是一個名稱,他是從'node_modules' 開始找的 2.因此這個方法將會幫我們判斷某個包是否出現在'node_modules',也就是是否安裝嘍 ~~~ [node對這個api的解釋](http://nodejs.cn/api/modules.html#modules_require_resolve_request_options) [別人文章里的解釋](https://www.jb51.net/article/111869.htm) * 這里我寫了一個小例子做說明 ![](https://img.kancloud.cn/6d/8e/6d8ecd0dcc6156d7b60e847f13d53150_876x322.png) ~~~ /** * @param {string} packageName name of the package * @returns {boolean} is the package installed? */ const isInstalled = packageName => { try { require.resolve(packageName); return true; } catch (err) { return false; } }; ~~~ >[danger] ##### CLIs webpack可用的CLI ~~~ 1.這里其實就是調用'isInstalled' 來查到底安沒安裝webpack 腳手架 ~~~ ~~~ /** * @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[]} */ 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." } ]; ~~~ >[danger] ##### installedClis判斷是否兩個CLI是否安裝了 ~~~ 1.這個就很簡單一個filter 過濾方法 ~~~ ~~~ const installedClis = CLIs.filter(cli => cli.installed); ~~~ >[danger] ##### 根據安裝數量進行處理 ~~~ 1.整個代碼的最后執行,如果你'webpack-command'和'webpack-cli'任意一個都沒安裝, 那么就會讓你選擇安裝一個 2.如果安裝其中一個,就正常運行 3.如果兩個都安裝了,那就提示刪除一個才能運行 4.path.resolve總是返回一個以相對于當前的工作目錄(working directory)的絕對路徑。 關于這個api'https://blog.csdn.net/iconhot/article/details/89257576' 5.fs.existsSync 判斷文件是否存在 ~~~ ~~~ if (installedClis.length === 0) { // 如果你'webpack-command'和'webpack-cli'任意一個都沒安裝 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) { // 循環帶有'webpack-command'和'webpack-cli' 這配置項的數組 if (item.recommended) {// 可以發現默認讓你安裝的其實是'webpack-cli',他的這個屬性才是true notify += `\n - ${item.name} (${item.url})\n ${item.description}`; } } console.error(notify); // 查詢你根目錄是否有yarn.lock 來決定是用yarn 還是 npm // path.resolve總是返回一個以相對于當前的工作目錄的絕對路徑。 // fs.existsSync 判斷文件是否存在 // process.cwd() 方法會返回 Node.js 進程的當前工作目錄 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; } ~~~ >[danger] ##### 總結 圖片來自下面的參考文章 ~~~ 1.webpack 最終找到 webpack-cli (webpack-command) 這個 npm 包,并且 執行 CLI ~~~ ![](https://img.kancloud.cn/51/4d/514d3a6394d12f79d5a5ecd1d27b9a8d_634x305.png) >[danger] ##### 參考的文章 [Webpack 進階之源碼分析(一)](https://segmentfault.com/a/1190000021469703)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看