[Vue CLI 3] 源码系列之useTaobaoRegistry
通過(guò)下列方式可以安裝最新版本的 Vue CLI(注釋:sudo 自行選擇)
sudo npm install -g @vue/cli然后通過(guò)下列命令創(chuàng)建項(xiàng)目:
vue create demo這時(shí)候,會(huì)詢問(wèn)你是否使用 taobao 的 registry
Your connection to the default npm registry seems to be slow.Use https://registry.npm.taobao.org for faster installation?然后選擇 Yes 后,發(fā)現(xiàn)在用戶的根目錄中出現(xiàn)了一個(gè) .vuerc文件,內(nèi)容如下:
{"useTaobaoRegistry": true }本文從源碼設(shè)計(jì)角度看一下背后的實(shí)現(xiàn):
在新版本 Vue CLI 中目錄結(jié)構(gòu)變動(dòng)了,我們找到了如下幾個(gè)文件:
@vue/cli/lib/util/shouldUseTaobao.js
這個(gè)文件的函數(shù)只會(huì)執(zhí)行一次:設(shè)置了變量 checked、result
let checked let result在函數(shù)內(nèi)部一上來(lái)就會(huì)判斷
if (checked) return result第一步:需要在命令行以詢問(wèn)方式:
一般多會(huì)采用 inquirer 這個(gè)工具包,先加載:
const inquirer = require('inquirer')然后調(diào)用 prompt 方法,注意這里設(shè)置了 type confirm 的方式
然后用 chalk 這個(gè)工具包來(lái)在命令行改變字顏色
const chalk = require('chalk')最核心的代碼片段如下:
定義了 name、type 和 message 字段:
const { useTaobaoRegistry } = await inquirer.prompt([{name: 'useTaobaoRegistry',type: 'confirm',message: chalk.yellow(` Your connection to the default npm registry seems to be slow.\n` +` Use ${chalk.cyan(registries.taobao)} for faster installation?`)}])第二步:判斷 register 的速度
定義一個(gè)變量 faster
let faster這里使用了 Promise.race 函數(shù)(返回一個(gè) promise,一旦迭代器中的某個(gè)promise 解決或拒絕,返回的 promise就會(huì)解決或拒絕。)
try {faster = await Promise.race([ping(defaultRegistry),ping(registries.taobao)])} catch (e) {}這里的變量就是:
const registries = require('./registries')如上,來(lái)自一個(gè)同級(jí)的 registries.js 文件
const defaultRegistry = registries.npmregistries 在 @vue/cli/lib/util/registries.js
源碼內(nèi)容如下:維護(hù)了 3 個(gè)映射關(guān)系,里面就有官方 registry 和 taobao 的
const registries = {npm: 'https://registry.npmjs.org',yarn: 'https://registry.yarnpkg.com',taobao: 'https://registry.npm.taobao.org'}module.exports = registries我們看一下最核心的 ping 函數(shù):
使用了 @vue/cli-shared-utils 的 request 方法
async function ping (registry) {await request.get(`${registry}/vue-cli-version-marker/latest`)return registry}去 @vue/cli-shared-utils/lib/request.js 看一下源碼:
對(duì)外暴露了 get 方法,內(nèi)部依賴 request-promise-native 工具包(uses native ES6 promises),傳入了一個(gè)對(duì)象:
- method 方法為 'GET'
- resolveWithFullResponse
- json
- uri 請(qǐng)求地址
核心代碼如下:
exports.request = {get (uri) {// lazy requireconst request = require('request-promise-native')const reqOpts = {method: 'GET',resolveWithFullResponse: true,json: true,uri}return request(reqOpts)}}第三步:寫(xiě)入一個(gè) .vuerc 文件
定義了 save 函數(shù),代碼實(shí)現(xiàn)如下:
const save = val => {result = valsaveOptions({ useTaobaoRegistry: val })return val}saveOptions 在 @vue/cli/lib/options.js 中定義:
exports.saveOptions = toSave => {// 實(shí)現(xiàn)在下面}在里面定義了一個(gè) defaults 的對(duì)象,里面默認(rèn)設(shè)置了 useTaobaoRegistry 為 undefined:
exports.defaults = {useTaobaoRegistry: undefined}核心是采用了 fs.writeFileSync 往指定目錄寫(xiě)文件:
注釋:關(guān)于寫(xiě)入路徑可以看一下 rcPath.js 文件提供的 getRcPath
const rcPath = exports.rcPath = getRcPath('.vuerc')注意:下面的 JSON.stringify 的第三個(gè)參數(shù),也是通過(guò) try catch 的方式:
fs.writeFileSync(rcPath, JSON.stringify(options, null, 2))那如果用戶本地已經(jīng)設(shè)置了呢,先獲取本地的設(shè)置:
核心是使用了 execa 這個(gè)工具包:
const execa = require('execa')定義了一個(gè)參數(shù) userCurrent ,傳入了命令和參數(shù):
(await execa(`npm`, ['config', 'get', 'registry'])).stdout比較兩個(gè)路徑:
if (removeSlash(userCurrent) !== removeSlash(defaultRegistry)) {// user has configured custom regsitry, respect thatreturn save(false)}removeSlash 的實(shí)現(xiàn)如下:
function removeSlash (url) {return url.replace(/\/$/, '')}第三個(gè)問(wèn)題:用戶第一次設(shè)置之后,后面的創(chuàng)建項(xiàng)目操作是如何處理的呢?
在 @vue/cli/lib/util/shouldUseTaobao.js 內(nèi)部,會(huì)調(diào)用 loadOptions 函數(shù)(下面會(huì)提到)
const saved = loadOptions().useTaobaoRegistry@vue/cli/lib/options.js
會(huì)定義一個(gè)變量:
let cachedOptions對(duì)外暴露了 loadOptions 函數(shù):
exports.loadOptions = () => {}在 loadOptions 函數(shù)內(nèi)部:
第一步:會(huì)先看 cachedOptions 是否有值:
if (cachedOptions) {return cachedOptions}然后會(huì)讀取配置文件內(nèi)容:通過(guò) fs.readFileSync 方法,然后用 JSON.parse 轉(zhuǎn)成對(duì)象
// 判斷配置文件是否存在if (fs.existsSync(rcPath)) {}內(nèi)部使用 try catch,給 cacheOptions 賦值
JSON.parse(fs.readFileSync(rcPath, 'utf-8'));所以第二次這里因?yàn)?.vuerc 文件已經(jīng)寫(xiě)入了內(nèi)容,所以第一步就返回了
本文原創(chuàng)來(lái)自微信公眾號(hào):前端新視野擴(kuò)展鏈接:
https://developer.mozilla.org...
https://www.npmjs.com/package...
總結(jié)
以上是生活随笔為你收集整理的[Vue CLI 3] 源码系列之useTaobaoRegistry的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: STM32程序下载电路分析
- 下一篇: 前端小知识点(8):作者为什么设计原型