新年新氣象,2020 開篇之做html
Node API
文檔中明確寫到,process.exit()
方法以退出狀態 code
指示 Node.js
同步地終止進程。 若是省略 code
,則使用成功代碼 0
或 process.exitCode
的值(若是已設置)退出。node
用於從模塊名取到絕對路徑。webpack
readline
模塊提供了一個接口,用於一次一行地讀取可讀流(例如 process.stdin
)中的數據。git
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('你如何看待 Node.js 中文網?', (answer) => {
// TODO:將答案記錄在數據庫中。
console.log(`感謝您的寶貴意見:${answer}`);
rl.close();
});
複製代碼
打開 import-local 下 index.js
文件,代碼量十分的少。github
// 當前文件所在項目的跟目錄,根據 package.json 來判斷項目的根目錄所在位置
const globalDir = pkgDir.sync(path.dirname(filename));
// 返回 filename 相對於 globalDir 的路徑
const relativePath = path.relative(globalDir, filename);
const pkg = require(path.join(globalDir, 'package.json'));
// 找到本地模塊路徑
const localFile = resolveCwd.silent(path.join(pkg.name, relativePath));
// 若是本地模塊路徑與 filename 不一致,則使用本地模塊
return localFile && path.relative(localFile, filename) !== '' ? require(localFile) : null;
複製代碼
process.argv
屬性返回一個數組,其中包含當啓動 Node.js
進程時傳入的命令行參數。第一個參數爲 process.execPath
啓動 Node.js
進行的可執行文件的絕對路徑名,第二個參數爲正在執行的 JavaScript
文件的路徑,剩餘元素是任何其餘命令行參數。web
process.cwd()
方法返回 Node.js
進程的當前工做目錄。數據庫
yargs
解決如何處理命令行參數,其提供 argv
對象,用來讀取命令行參數。npm
#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('hello ', argv.name);
複製代碼
使用時,下面兩種用法均可以。json
$ hello --name=tom
hello tom
$ hello --name tom
hello tom
複製代碼
usage
設置命令的提示的使用方法。api
help
設置幫助信息,添加 --help
,可是沒有 -h
,須要手動添加。
alias
設置別名,好比指定 name
是 n
的別名。
#!/usr/bin/env node
var argv = require('yargs')
.alias('h', 'help')
.argv;
複製代碼
version
添加版本顯示參數 --version
,不過不添加縮寫參數。
options
批量設置參數。
require('yargs')
.options({
'run': {
alias: 'r', // 別名
describe: 'run your program', // 描述
demandOption: true // 是否必填
},
'path': {
alias: 'p',
describe: 'provide a path to file',
demandOption: true
}
})
.help()
.argv
複製代碼
設置完成後,當你打印幫助信息時。
path.relative()
方法根據當前工做目錄返回 from
到 to
的相對路徑。 若是 from
和 to
各自解析到相同的路徑(分別調用 path.resolve()
以後),則返回零長度的字符串。
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb');
// 返回: '../../impl/bbb'
複製代碼
你們可能並不陌生,當咱們在執行 webpack XX
,會去本地項目文件的 node_modeles/bin
文件下查找 webpack
命令。因此,首先打開 node_modeles/bin
下的 webpack
文件。 入口文件由 4 個部分組成,分別爲 process.exitCode
、runCommand
、CLI 數組
和 判斷某 CLI 是否安裝
。
process.exitCode
爲 0,表明程序正常運行;非 0,則表明程序報錯。
此函數會啓動一個子進程,並執行輸入命令。
定義了一個 CLI
數組,數組共有 2 項,分別爲 webpack-cli
和 webpack-command
。
webpack-cli
webpack-cli
包含了全部的 webpack
特性,通常推薦使用這個包
webpack-command
webpack-command
只是一個輕量的 webpack
包。
若是兩個 CLI
均未安裝,則會提示必須安裝一個 CLI
。當你輸入 yes
並回車後,會經過上文定義的 runCommand
函數進行安裝。固然,webpack
會判斷當前應該使用 npm
,仍是使用 yarn
。安裝完成後,並 reuqire
進來。
若是隻安裝一個,程序正常執行。這裏以 webpack-cli
舉例。
首先經過 require.resolve
取到 webpack-cli
存放的絕對路徑,好比取到的路徑爲 /Users/XXX/Works/Demo/node_modules/webpack-cli/package.json
,並把包 require
進來。而後根據以前取到的 webpack-cli
路徑執行到 webpack-cli/bin/cli.js
文件,文件內具體邏輯,此處不做講解。
const path = require("path");
const pkgPath = require.resolve(`${installedClis[0].package}/package.json`);
const pkg = require(pkgPath);
require(path.resolve(
path.dirname(pkgPath),
pkg.bin[installedClis[0].binName]
));
複製代碼
若是兩個都安裝,webpack
會提示須要刪除其中一個,才能夠正常運行。
打開 node_modules/webpack-cli/bin/cli.js
文件,咱們首先看到下面這個代碼片斷。webpack
並不會編譯執行全部的命令,它會針對不須要編譯的 cmd
,執行 ./utils/prompt-command
文件方法。
const NON_COMPILATION_CMD = process.argv.find(arg => {
if (arg === 'serve') {
global.process.argv = global.process.argv.filter(a => a !== 'serve');
process.argv = global.process.argv;
}
return NON_COMPILATION_ARGS.find(a => a === arg);
});
if (NON_COMPILATION_CMD) {
return require('./utils/prompt-command')(NON_COMPILATION_CMD, ...process.argv);
}
複製代碼
不須要編譯的 CMD
列表位於文件 ./utils/constants` 下 `NON_COMPILATION_ARGS
數組中。
./utils/prompt-command
文件往外暴露一個方法 promptForInstallation
。方法內部首先會去查詢當前項目是否安裝 @webpack-cli/
+ 外界傳入的 NON_COMPILATION_CMD
,若是未安裝,便提示安裝,安裝後執行 runWhenInstalled
;已安裝,則執行 runWhenInstalled
。
回到 cli.js
文件中,咱們能夠繼續往下看。代碼中引入 yargs
,並定義了幫助信息,並把大部分幫助信息放在 ./config/config-yargs
文件中。進入 ./config/config-yargs
文件,不知你們是否留意到,每一項都設置了 group
分組,group
的值都來自 ../utils/constants
文件。webpack
共有 8 個分組的幫助信息,加上默認的分組,總共有 9 個分組。
繼續往下看,咱們調用yargs.parse
方法,處理命令行參數。第一個參數傳入已去除 process.argv
數組前兩項,也就是傳入全部命令行參數,第二個參數爲一個回調函數。
yargs.parse(process.argv.slice(2), (err, argv, output) => {})
複製代碼
定義變量 options
,此變量存儲了把全部命令轉換成 webpack
配置參數的值。把通過處理的 options
,經過調用 webpack(options)
生成 compiler
。若是命令行參數傳入的是 watch
,則調用 compiler.watch
,不然調用 compiler.run
。