[Vue CLI 3] 原始碼系列之useTaobaoRegistry
透過下列方式可以安裝最新版本的 Vue CLI(註釋:sudo 自行選擇)
sudo npm install -g @vue/cli
然後透過下列命令建立專案:
vue create demo
這時候,會詢問你是否使用 taobao 的 registry
Your connection to the default npm registry seems to be slow. Use for faster installation?
然後選擇 Yes 後,發現在使用者的根目錄中出現了一個 .vuerc
檔案,內容如下:
{ "useTaobaoRegistry": true}
本文從原始碼設計角度看一下背後的實現:
在新版本 Vue CLI 中目錄結構變動了,我們找到了如下幾個檔案:
@vue/cli/lib/util/shouldUseTaobao.js
這個檔案的函式只會執行一次
:設定了變數 checked
、result
let checkedlet result
在函式內部一上來就會判斷
if (checked) return result
第一步:需要在命令列以詢問方式:
一般多會採用 inquirer
這個工具包,先載入:
const inquirer = require('inquirer')
然後呼叫 prompt
方法,注意這裡設定了 type confirm
的方式
然後用 chalk
這個工具包來在命令列改變字顏色
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 的速度
定義一個變數 faster
let faster
這裡使用了 Promise.race
函式(返回一個 promise,一旦迭代器中的某個promise 解決或拒絕,返回的 promise就會解決或拒絕。)
try { faster = await Promise.race([ ping(defaultRegistry), ping(registries.taobao) ]) } catch (e) {}
這裡的變數就是:
const registries = require('./registries')
如上,來自一個同級的 registries.js
檔案
const defaultRegistry = registries.npm
registries 在 @vue/cli/lib/util/registries.js
原始碼內容如下:維護了 3 個對映關係,裡面就有官方 registry
和 taobao
的
const registries = { npm: '', yarn: '', taobao: ''}module.exports = registries
我們看一下最核心的 ping
函式:
使用了 @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
看一下原始碼:
對外暴露了 get 方法,內部依賴 request-promise-native 工具包(uses native ES6 promises),傳入了一個物件:
method 方法為 'GET'
resolveWithFullResponse
json
uri 請求地址
核心程式碼如下:
exports.request = { get (uri) { // lazy require const request = require('request-promise-native') const reqOpts = { method: 'GET', resolveWithFullResponse: true, json: true, uri } return request(reqOpts) } }
第三步:寫入一個 .vuerc 檔案
定義了 save 函式,程式碼實現如下:
const save = val => { result = val saveOptions({ useTaobaoRegistry: val }) return val }
saveOptions 在 @vue/cli/lib/options.js 中定義:
exports.saveOptions = toSave => { // 實現在下面}
在裡面定義了一個 defaults 的物件,裡面預設設定了 useTaobaoRegistry 為 undefined:
exports.defaults = { useTaobaoRegistry: undefined }
核心是採用了 fs.writeFileSync 往指定目錄寫檔案:
註釋:關於寫入路徑可以看一下 rcPath.js 檔案提供的 getRcPath
const rcPath = exports.rcPath = getRcPath('.vuerc')
注意:下面的 JSON.stringify 的第三個引數,也是透過 try catch 的方式:
fs.writeFileSync(rcPath, JSON.stringify(options, null, 2))
那如果使用者本地已經設定了呢,先獲取本地的設定:
核心是使用了 execa 這個工具包:
const execa = require('execa')
定義了一個引數 userCurrent ,傳入了命令和引數:
(await execa(`npm`, ['config', 'get', 'registry'])).stdout
比較兩個路徑:
if (removeSlash(userCurrent) !== removeSlash(defaultRegistry)) { // user has configured custom regsitry, respect that return save(false) }
removeSlash 的實現如下:
function removeSlash (url) { return url.replace(//$/, '') }
第三個問題:使用者第一次設定之後,後面的建立專案操作是如何處理的呢?
在 @vue/cli/lib/util/shouldUseTaobao.js 內部,會呼叫 loadOptions 函式(下面會提到)
const saved = loadOptions().useTaobaoRegistry
@vue/cli/lib/options.js
會定義一個變數:
let cachedOptions
對外暴露了 loadOptions 函式:
exports.loadOptions = () => { }
在 loadOptions 函式內部:
第一步:會先看 cachedOptions 是否有值:
if (cachedOptions) { return cachedOptions }
然後會讀取配置檔案內容:透過 fs.readFileSync 方法,然後用 JSON.parse 轉成物件
// 判斷配置檔案是否存在if (fs.existsSync(rcPath)) {}
內部使用 try catch
,給 cacheOptions
賦值
JSON.parse(fs.readFileSync(rcPath, 'utf-8'));
所以第二次這裡因為 .vuerc
檔案已經寫入了內容,所以第一步就返回了
作者:dailyvuejs
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2310/viewspace-2815571/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [Vue CLI 3] @vue/cli-plugin-eslint 原始碼分析VuePluginEsLint原始碼
- [Vue CLI 3] 外掛解析之 @vue/cli-plugin-bVuePlugin
- [Vue CLI 3] 配置之filenameHashing使用和原始碼設計Vue原始碼
- Vue3 原始碼之 reactivityVue原始碼React
- [Vue CLI 3] 配置解析之 parallelVueParallel
- vue-loader 原始碼解析系列之 selectorVue原始碼
- Vue3原始碼分析之compositionApiVue原始碼API
- [Vue CLI 3] 多頁應用實踐和原始碼設計Vue原始碼
- vue原始碼分析系列之入口檔案分析Vue原始碼
- vue-cli原始碼分析(試探篇)Vue原始碼
- [Vue CLI 3] 配置解析之 css.extractVueCSS
- VUE 全家桶 vue-cli 2 | vue-cli 3Vue
- VUE CLI 3 配置Vue
- vue原始碼分析系列之入debug環境搭建Vue原始碼
- D3原始碼解讀系列之Chord原始碼
- D3原始碼解讀系列之Dispatches原始碼
- D3原始碼解讀系列之Force原始碼
- D3原始碼解讀系列之Hierarchies原始碼
- D3原始碼解讀系列之Path原始碼
- D3原始碼解讀系列之Quadtrees原始碼
- D3原始碼解讀系列之Requests原始碼
- D3原始碼解讀系列之Selections原始碼
- D3原始碼解讀系列之Shape原始碼
- webpack-chain原始碼 vue-cli配置webpackWebAI原始碼Vue
- Vue 原始碼分析系列一:new Vue()Vue原始碼
- 【原始碼系列#01】vue3響應式原理(Proxy)原始碼Vue
- 【原始碼系列#02】Vue3響應式原理(Effect)原始碼Vue
- 【原始碼系列#05】Vue3響應式原理(Ref)原始碼Vue
- 【原始碼系列#04】Vue3偵聽器原理(Watch)原始碼Vue
- vue原始碼分析系列之響應式資料(三)Vue原始碼
- vue原始碼分析系列之響應式資料(二)Vue原始碼
- VUE-CLI3配置Vue
- vue3原始碼學習之reactive實現Vue原始碼React
- 【vue-系列】vue-router原始碼分析Vue原始碼
- 【原始碼系列#03】Vue3計算屬性原理(Computed)原始碼Vue
- vue 快速入門 系列 —— vue-cli 下Vue
- vue 快速入門 系列 —— vue-cli 上Vue
- Vue原始碼分析系列三:renderVue原始碼