[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 https://registry.npm.taobao.org for faster installation?

然后选择 Yes 后,发现在用户的根目录中出现了一个 .vuerc文件,内容如下:

{"useTaobaoRegistry": true
}

本文从源码设计角度看一下背后的实现:

在新版本 Vue CLI 中目录结构变动了,我们找到了如下几个文件:

@vue/cli/lib/util/shouldUseTaobao.js

这个文件的函数只会执行一次:设置了变量 checkedresult

let checked
let 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 个映射关系,里面就有官方 registrytaobao

const registries = {npm: 'https://registry.npmjs.org',yarn: 'https://registry.yarnpkg.com',taobao: 'https://registry.npm.taobao.org'}module.exports = registries

我们看一下最核心的 ping 函数:

使用了 @vue/cli-shared-utilsrequest 方法

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 requireconst request = require('request-promise-native')const reqOpts = {method: 'GET',resolveWithFullResponse: true,json: true,uri}return request(reqOpts)}}

第三步:写入一个 .vuerc 文件

定义了 save 函数,代码实现如下:

const save = val => {result = valsaveOptions({ 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 thatreturn 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 文件已经写入了内容,所以第一步就返回了

本文原创来自微信公众号:前端新视野

扩展链接:

https://developer.mozilla.org...

https://www.npmjs.com/package...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/277391.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ajax 页面无刷新

<!-- 使用原生Ajax 和 $.ajax 实现局部刷新的过程 --><!-- 封装通用XMLHttpRequest对象 --><!DOCTYPE html><html lang"en"><head> <meta charset"UTF-8"> <title>创建XMLHttpRequest</title> <style&…

php7安装详解_,PHP7 redis扩展安装详解

1、安装redis(1)下载&#xff1a;https://github.com/phpredis/phpredis/tree/php7 或下载http://pan.baidu.com/s/1i5DFrjn用samba挂载导进去(2)yum -y install m4 autoconf # 安装依赖(3)unzip phpredis-php7.zip # 解压(4)cd ./phpredis-php7 # 进入目录(5)phpize #用php…

python之_init_函数的简介

1、每个package中都必须包含一个_init_.py文件除了不需要加载模块的 它方便在外部统一调用&#xff0c;和在内部互相调用&#xff0c;它可以为空&#xff0c;当为空时&#xff0c;作用是将这个文件夹下的内容当作包执行&#xff0c;便于解释器区分执行。 2、定义类的时候&#…

22. Generate Parentheses

题目描述&#xff1a; Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. For example, given n 3, a solution set is: ["((()))","(()())","(())()","()(())","()()…

es6中的块级作用域

块级作用域 凡是带{}都是块级作用域&#xff0c;if(){} for(){} 对象{} 1.在块级作用域下&#xff0c;var 和function跟在window下一样&#xff0c; function有个特殊的一点&#xff0c;在块级作用域下会提前声明&#xff0c;不会提前定义 2.在块级作用域下 let和const声明的变…

php图片地址参数错误,图片上传时一直显示请求地址错误怎么办

1、出现“请求地址错误”的直接原因&#xff1a;图中$action null2.根本原因&#xff1a;url美化那一节课程&#xff0c;去掉 index.php的.htaccess 文件修改的时候&#xff0c;没有按照老师的来写&#xff0c;所以美化url以后获取不到地址栏参数&#xff0c;导致$action值为n…

C#写的WebServices可运行于树莓派

阅读目录 Raspkate - 基于.NET的可运行于树莓派的轻量型Web服务器Raspkate项目演示回到目录Raspkate - 基于.NET的可运行于树莓派的轻量型Web服务器 最近在业余时间玩玩树莓派&#xff0c;刚开始的时候在树莓派里写一些基于wiringPi库的C语言程序来控制树莓派的GPIO引脚&#x…

[导入]Ms XmlDom 异步装载Xml文件

Ms XmlDom 异步装载Xml文件文章来源:http://blog.csdn.net/net_lover/archive/2004/07/07/36015.aspx 转载于:https://www.cnblogs.com/zhaoxiaoyang2/archive/2004/07/07/816151.html

Django的View(视图)

Django的View&#xff08;视图&#xff09; 一个视图函数&#xff08;类&#xff09;&#xff0c;简称视图&#xff0c;是一个简单的Python 函数&#xff08;类&#xff09;&#xff0c;它接受Web请求并且返回Web响应。 响应可以是一张网页的HTML内容&#xff0c;一个重定向&am…

设计模式之--原型模式

1.原型模式定义 原型模式非常简单&#xff0c;定义如下&#xff1a; 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象 2.通用类图 原型模式的核心是实现Cloneable接口&#xff0c;此接口为JDK提供的一个标识接口&#xff0c;只有实现了此接口的类才…

搜索目录里所有文件(包括子目录)

搜索目录里所有文件(包括子目录&#xff09; 资料来源&#xff1a;http://www.cnblogs.com/jjwwww/archive/2004/09/04/39559.aspx 用到两个函数ParseDirectory 和CreatePathListvoidParseDirectory(stringpath, stringfilter) { strin…

一张图理解buffer与cache

转载于:https://blog.51cto.com/11193863/2169166

oracle服务器不识别tc服务,记一次ORACLE无法启动登陆事故

打开XSHELL 登陆ORACLE用户1.sqlplus scott/scott 提示登陆失败2.sqplus / as sysdba 启动数据库提示3.查找日志操作日志&#xff1a;$ORACLE_HOME/startup.log启动日志&#xff1a;$ORACLE_BASE/diag/rdbms/ora11g/ora11g/trace/alert_ora11g.log (ora11g为SID值)启动日志如果…

BMP位图之8位位图(三)

起始结构 typedef struct tagBITMAPFILEHEADER { WORD bfType; //类型名&#xff0c;字符串“BM”&#xff0c; DWORD bfSize; //文件大小 WORD bfReserved1; //保留字 WORD bfReserved2; //保留字 DWORD bfOffBits; //实际位图数据的偏移字节数&#xff0c;即前三个部分长度之…

Node.js 事件循环

Node.js 事件循环 Node.js 是单进程单线程应用程序&#xff0c;但是因为 V8 引擎提供的异步执行回调接口&#xff0c;通过这些接口可以处理大量的并发&#xff0c;所以性能非常高。 Node.js 几乎每一个 API 都是支持回调函数的。 Node.js 基本上所有的事件机制都是用设计模式中…

android天气查询(二)之网络json数据的获取

前面一篇文章介绍了如何使用ksoap获取天气信息&#xff0c;但是使用的网络资源受到了限制&#xff0c;所以我们这里会采用第二种方法&#xff0c;可以无限制的获取。http://m.weather.com.cn/data/101010100.html 但是对应的101010100(北京)我们怎么获取呢&#xff0c;还有就是…

累.....

今天我真的蔫了&#xff0c;好累&#xff0c;脑子也好浊&#xff0c;但是还好&#xff0c;最终达到了预期的目的。我终于把henry的dataGrid实现了&#xff0c;犯了低级错误&#xff0c;和好多人讨论&#xff0c;但最终还是henry解决的。那一刻&#xff0c;真的好爽&#xff0c;…

linux cp 时 略过文件,CentOS下执行cp命令式提示略过文件夹

今天在CentOS下复制一个文件夹到另一个文件夹的时候cp ./res /usr 的时候出现了问题&#xff0c;提示我的是&#xff1a;cp略过了文件夹后来我找了一下在网上search了一下CP命令的用法&#xff1a;CP命令该命令的功能是将给出的文件或目录拷贝到另一文件或目录中&#xff0c;同…

hibernate详解

Hibernate原理与应用 主要内容 1、引入 2、安装配置 3、基本概念和CURD 4、HQL和Criteria 5、关联映射 6、继承映射 7、集合映射 8、懒加载 9、缓存 10、事务 11、其他 12、Hibernate不适合的场景 13、与JPA的集成(annotation方式) 14、最佳实践 1、引入 模型不匹配(阻抗不匹配…

Android Studio 环境搭建参考,jdk10javac命令提示不是内部或外部命令

https://blog.csdn.net/qq_33658730/article/details/78547789 win10下Android Studio和SDK下载、安装和环境变量配置 http://yanmin99.com/ android-0基础从入门到精通 环境变量ANDROID_HOMEE:\Program Files (x86)\Android\SdkJAVA_HOMEE:\Program Files\Java\jdk1.8.0_161TO…