尤大是如何发布vuejs的,学完可以应用到项目

大家好,我是若川。本文是读者@NewName 投稿,看了我推荐的vuejs如何发布的源码(200余行),并成功写了一个小工具。推荐的当晚看到挺晚,这执行力这努力程度超过很多人啊。我本来是打算自己写一篇这个文章的,没想到他写完了。


前言:第一次看源码,感谢我川哥提供合适题材,给予细心指导。感觉学习源码真的很有帮助,我第一次就品尝到甜头了,可以借鉴(抄袭)源码的思想解决实际的问题,真好啊。本人着实菜鸟一枚,也不会写作,把学习的笔记记录一下而已。

1. 准备工作和主要精神

1.源码地址:https://github1s.com/vuejs/vue-next/blob/HEAD/scripts/release.js

2.源码主旨内容:vuejs 是如何发布

3.要思考学完了可以应用的地方:

1.比如学完这个源码,优化自己项目的发布流程 
————真有点想法耶:
我们公司目前的前端发版本流程中有许多的git命令 ,这些git命令我可以用脚本的方式运行,借鉴源码中的run方法:
const run = (bin, args, opts = {}) =>execa(bin, args, { stdio: 'inherit', ...opts })
目前已经写了(CV)一个工具脚本,优化了我们公司前端项目发预发布版本的流程,详见第六部分。

4.读源码特别要注意:

先看懂大局呀~ 主线是main函数  先看懂大概 然后不懂的再查

2. 从main函数开始看

main 函数中主要代码梳理一下,总体流程如下图所示:

先简单看下 vuejs 发布总体流程

2.1 版本号验证相关流程 :40 - 77行

40行:获取版本号

44 -49行 :如果版本号不存在则问是要升级大版本、小版本、 补丁版本 还是自定义

52-59 行 :如果用户选择的自定义则获取自定义的版本

65-67行:检查版本号是否合法

69-73行:问是否确定要发布版本

55-77: 如果选择否 main函数执行结束, 返回

2.2 发布之前的测试:80-86行

2.3 更新依赖的版本号:88-90行

2.4 运行build命令 :93-101行

2.5 运行日志命令 :104行

2.6 提交代码:106-113行

2.7 运行发布命令 :115-119 行

2.8 新的版本push到git:121-125行

2.9 提示跳过更新的包:131-139行

3. 一些变量和函数的定义细节

3.1 发布之前测试:

80-86行:

//如果没有skipTests 跳过测试 并且没有 isDryRun(空跑?)则运行测试
step('\nRunning tests...')if (!skipTests && !isDryRun) {//使用jest , 清除缓存await run(bin('jest'), ['--clearCache'])//yarn test await run('yarn', ['test', '--bail'])} else {console.log(`(skipped)`)}

3.2 构建所有的包

93—101行:

//其实是运行yarn build 命令 
await run('yarn', ['build', '--release'])

3.3 运行日志命令

104行:运行 yarn 的log命令

await run(`yarn`, ['changelog'])
//changelog定义在package.json 的 npm scripts 中:
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",//这里使用到了conventional-changelog,见第五部分:使用的依赖

3.4 提交代码

106-113行:git版本管理相关

//判断文件是否有变化,如果有变化则提交到git
const { stdout } = await run('git', ['diff'], { stdio: 'pipe' })if (stdout) {step('\nCommitting changes...')await runIfNotDry('git', ['add', '-A'])await runIfNotDry('git', ['commit', '-m', `release: v${targetVersion}`])} else {console.log('No changes to commit.')}

3.5 运行发布命令

115-119行: 发布

// publish packagesstep('\nPublishing packages...')for (const pkg of packages) {await publishPackage(pkg, targetVersion, runIfNotDry)}
//publishPackage的定义在175-230行:
async function publishPackage(pkgName, version, runIfNotDry) {// 如果某个包要跳过则直接返回if (skippedPackages.includes(pkgName)) {return}//获取路径和内容const pkgRoot = getPkgRoot(pkgName)const pkgPath = path.resolve(pkgRoot, 'package.json')const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))//如果是私有的则返回if (pkg.private) {return}// For now, all 3.x packages except "vue" can be published as// `latest`, whereas "vue" will be published under the "next" tag.// 定义一下发布的标记 (打tag)let releaseTag = nullif (args.tag) {releaseTag = args.tag} else if (version.includes('alpha')) {releaseTag = 'alpha'} else if (version.includes('beta')) {releaseTag = 'beta'} else if (version.includes('rc')) {releaseTag = 'rc'} else if (pkgName === 'vue') {// TODO remove when 3.x becomes defaultreleaseTag = 'next'}// TODO use inferred release channel after official 3.0 release// const releaseTag = semver.prerelease(version)[0] || null// 执行发布: 运行yarn的发布命令step(`Publishing ${pkgName}...`)try {await runIfNotDry('yarn',['publish','--new-version',version,...(releaseTag ? ['--tag', releaseTag] : []),'--access','public'],{cwd: pkgRoot,stdio: 'pipe'})console.log(chalk.green(`Successfully published ${pkgName}@${version}`))} catch (e) {if (e.stderr.match(/previously published/)) {console.log(chalk.red(`Skipping already published: ${pkgName}`))} else {throw e}}
}

3.6 更新依赖的细节

88-90: 更新所有的依赖

updateVersions(targetVersion)
//updateVersions 是定义的一个更新版本的函数,里面调用了 updatePackage函数
function updateVersions(version) {// 1. update root package.jsonupdatePackage(path.resolve(__dirname, '..'), version)// 2. update all packagespackages.forEach(p => updatePackage(getPkgRoot(p), version))
}
//packages的定义在第16行;
//updatePackag在157行:大概意思是找到路径下的package.json文件然后读取文件内容,转成对象,更新版本,再写回文件。
function updatePackage(pkgRoot, version) {const pkgPath = path.resolve(pkgRoot, 'package.json')const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))pkg.version = versionupdateDeps(pkg, 'dependencies', version)updateDeps(pkg, 'peerDependencies', version)fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
}
//这里用到的updateDeps在 159-173行定义:
function updateDeps(pkg, depType, version) {const deps = pkg[depType]if (!deps) returnObject.keys(deps).forEach(dep => {//大概含义是检查依赖,如果其中有vue则提示并且替换版本。if (dep === 'vue' ||(dep.startsWith('@vue') && packages.includes(dep.replace(/^@vue\//, '')))) {console.log(chalk.yellow(`${pkg.name} -> ${depType} -> ${dep}@${version}`))deps[dep] = version}})
}

4. 总体的流程总结回顾

main 函数中主要代码梳理一下,总体流程如下图所示:

先简单看下 vuejs 发布总体流程

5. 使用的依赖

5.1 minimist

const args = require('minimist')(process.argv.slice(2))

minimist轻量级的命令行参数解析引擎

https://blog.csdn.net/fangxuan1509/article/details/107469465

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

5.2 chalk

const chalk = require('chalk')

chalk是一个颜色的插件

https://blog.csdn.net/sqrtsix/article/details/76615630

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

5.3 semver

const semver = require('semver')

Semver是一个专门分析Semantic Version(语义化版本)的工具,“semver”其实就是这两个单词的缩写。Npm使用了该工具来处理版本相关的工作。

语义化版本扫盲  https://segmentfault.com/a/1190000014405355

https://www.npmjs.cn/misc/semver/

5.4 enquirer

const { prompt } = require('enquirer')

命令行提示的?

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

5.5 execa

const execa = require('execa')

execa是可以调用shell和本地外部程序的javascript封装。会启动子进程执行。支持多操作系统,包括windows。如果父进程退出,则生成的全部子进程都被杀死。

http://abloz.com/tech/2018/08/21/nodejs-execa/

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

5.6 yarn的相关命令

https://yarn.bootcss.com/docs/getting-started/

5.7 conventional-changelog

在约定式提交的基础上来自动生成changelog

https://blog.csdn.net/weixin_34326179/article/details/91382865

https://www.npmjs.com/package/conventional-changelog

6. 应用:优化发“预发布版本”的流程

6.1 问题描述

“预发布版本”是我们发正式版本之前的一个验证版本,目前我们公司前端项目发“预发布版本”的时候要通过如下图所示的流程,这里面有很多操作git的命令,受阅读源码启发,我想写一个工具脚本,把这些命令变成自动执行的方式,需要的信息只需要开发者输入或者选择即可。

其中生成tag的时候需要根据tag命名规范来生成。下图中 12 为固定值 ,20代表年份,30代表是一年中的第几周,01代表第几次发版。

6.2 解决方案

所以我需要写的脚本中就需要做这几件事情:

(1)要获取当前年份,当前第几周:这两个值用JS基本代码就ok,

(2)需要和开发者交互获取第几次发版和服务名:可以使用 release.js 中使用的 依赖:enquirer;

(3)需要运行git命令:release.js 中使用的 依赖:execa,以及定义的 run()方法。

(4)如果控制台中要高亮提示信息则使用依赖:chalk ,当然这个是可选的

6.3 具体实现

6.3.1 首先项目根目录下新建scripts文件夹,然后新建 release.js文件

6.3.2 安装依赖

npm install chalk --save-dev 
npm install execa --save-dev 
npm install enquirer --save-dev 

6.3.3 写代码

const chalk = require('chalk')
const execa = require('execa')
const {prompt
} = require('enquirer')const step = msg => console.log(chalk.cyan(msg))const run = (bin, args, opts = {}) =>execa(bin, args, {stdio: 'inherit',...opts})async function main() {console.log('欢迎使用发版小助手脚本')step('\n验证是否提交代码...')const { yes } = await prompt({type: 'confirm',name: 'yes',message: `确定已经提交代码并将代码push到develop分支了吗?`})if (!yes) {return}// 切换到 develop 分支,拉取最新代码await run('git', ['checkout', 'develop'])await run('git', ['pull', 'origin', 'develop'])// 切换到 release 分支,拉取最新代码await run('git', ['checkout', 'release'])await run('git', ['pull', 'origin', 'release'])// 本地 release 分支合并 develop 分支代码await run('git', ['merge', 'develop'])// 合并完成后,推送到远程 release 分支await run('git', ['push', 'origin', 'release'])// 以下逻辑为拼写tag号,打tag用// 获取当前年份后两位const yearLastTwoBit = getLastTwoBitYear()console.log(yearLastTwoBit)// 获取当前是一年中的第几周const currentWeek = theWeek()console.log(currentWeek)// 本次的版本号const targetVersion = (await prompt({type: 'input',name: 'version',message: '这次是本周第几次发版?(请输入数字)',})).versionconsole.log(targetVersion)// 前端服务名字const serviceName = (await prompt({type: 'input',name: 'serviceName',message: '请输入这个前端服务名字?(例如 fe_beg)',})).serviceNameconsole.log(serviceName)// 拼接tag名 const tagName = `Cloud_R-12.${yearLastTwoBit}.${currentWeek}.${targetVersion > 10 ? targetVersion : `0${targetVersion}`}-${serviceName}`// 拼接注释const comment = `${serviceName}服务${currentWeek}周/迭代第${targetVersion}次版本发布`// 本地打 Tag,生成版本await run('git', ['tag', tagName, '-m', comment])// 推送 Tag 到远程代码库,触发构建await run('git', ['push', '--tags'])console.log('稍等片刻,即可完成预发布环境版本发布,详细查看Jenkins')// 重新切换到develop分支await run('git', ['checkout', 'develop'])
}// 获取当前年份后两位
function getLastTwoBitYear() {const date = new Date()const currentYear = date.getFullYear().toString()return currentYear.substr(currentYear.length - 2, 2)
}function theWeek() {var totalDays = 0;now = new Date();var days = new Array(12);days[0] = 31;days[2] = 31;days[3] = 30;days[4] = 31;days[5] = 30;days[6] = 31;days[7] = 31;days[8] = 30;days[9] = 31;days[10] = 30;days[11] = 31;//判断是否为闰年,针对2月的天数进行计算if (Math.round(now.getYear() / 4) == now.getYear() / 4) {days[1] = 29} else {days[1] = 28}if (now.getMonth() == 0) {totalDays = totalDays + now.getDate();} else {var curMonth = now.getMonth();for (var count = 1; count <= curMonth; count++) {totalDays = totalDays + days[count - 1];}totalDays = totalDays + now.getDate();}//得到第几周var week = Math.round(totalDays / 7);return week;
}
main().catch(err => {console.log(err)
})

6.3.4 然后在package.json 中增加一个npm script:

"release": "node scripts/release.js",

6.3.5 测试

运行命令:

npm run release  

下图为脚本运行效果:

小工具脚本运行还算顺利,只需要运行1次命令,确认1次,输入2次,避免了输入很多git命令。还有就是发完“预发布”之后,我们很容易忘了切回develop分支,这个小工具脚本最后把代码切到了develop分支,可以减少不必要的麻烦。

当然这里,我没有考虑许多的异常case , 健壮性不太好,有待优化。

最后我非常感谢川哥,细心耐心给予我指导,解答我的问题。川哥人好又心善,勤勉又聪慧,实在是我学习的楷模~


最近组建了一个江西人的前端交流群,如果你是江西人可以加我微信 ruochuan12 私信 江西 拉你进群。


推荐阅读

我在阿里招前端,该怎么帮你(可进面试群)
我读源码的经历

在字节做前端一年后,有啥收获~
老姚浅谈:怎么学JavaScript?

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》多篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。
同时,活跃在知乎@若川,掘金@若川。致力于分享前端开发经验,愿景:帮助5年内前端人走向前列。

点击方卡片关注我、加个星标

今日话题

付费课程一定程度上可以帮助到一些自律爱学习的人,同时也确实会节省不少时间。打个可能不是那么恰当的比方。如果说学习是爬山,那么付费学习可以理解为是适当的花钱坐缆车,坐上缆车节省了时间和体力,更容易攀登到更高的山峰,但前提是体力较好。自己走山路上山当然也很好,但如果爬更高的山峰,后续就有可能到达不了最顶峰。欢迎分享、收藏、点赞、在看我的公众号文章~

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

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

相关文章

(转)从零实现3D图像引擎:(6)向量函数库

1. 数学分析 1) 基本定义&#xff1a; 向量由多个分量组成&#xff0c;2D/3D向量表示一条有向线段。下面的ux,uy就是两个分量。 向量u <ux, uy>&#xff0c;如果从点P1(x1, y1)指向点P2(x2, y2)&#xff0c;则&#xff1a; U p2 - p1 (x2-x1, y2-y1) <Ux, Uy> …

chrome黑暗模式_黑暗模式-并非时尚

chrome黑暗模式In this post I’ve shared my research and views on how the extremely popular “Dark Mode” has moved beyond it’s initial label of “The App Design Fad of 2019”.在这篇文章中&#xff0c;我分享了我的研究和看法&#xff0c;探讨了非常受欢迎的“黑…

花了一天精选了20多篇好文,只为与你分享

大家好&#xff0c;我是若川。很多小伙伴因工作繁忙而没有很多自己的时间去学习新知识&#xff0c;更多的是通过一些碎片化的时间来阅读一些他人的技术文章来提升自己的技术视野以及扩展自己的知识储备。这次我精心整理了一批大佬们的优秀文章&#xff0c;感兴趣的可以阅读关注…

matlab判断电话播键音,MATLAB电话拨号音的合成与识别

1.实验目的1.本实验内容基于对电话通信系统中拨号音合成与识别的仿真实现。主要涉及到电话拨号音合成的基本原理及识别的主要方法&#xff0c;利用 MATLAB 软件以及 FFT 算法实现对电话通信系统中拨号音的合成与识别。并进一步利用 MATLAB 中的图形用户界面 GUI 制作简单直观的…

jquery插件之无缝循环新闻列表

一、效果图&#xff1a; tips源码下载&#xff1a;http://files.cnblogs.com/waitingbar/newslist.rar 二、jquery源码: (function($){$.fn.extend({newsList:function(options){var defaults {actName:li, //显示条数名&#xff1b;maxShowNum:6, //最多的显示…

素描的几大基础知识点_2020年让您感到惊奇的5大素描资源

素描的几大基础知识点Sketch is my favorite stand-alone software that I use every day. It is simple, stable, and fast. During my working process, I use other resources that allow me to create UX/UI design faster. These tools have a different direction, but s…

你不知道的 Chrome DevTools 玩法

大家好&#xff0c;我是若川。今天再分享一篇 chrome devtools 的文章。之前分享过多篇。Chrome DevTools 全攻略&#xff01;助力高效开发 前端容易忽略的 debugger 调试技巧‍笔者在前段时间的开发时&#xff0c;需要通过 Chrome DevTools来分析一个接口&#xff0c;调试中发…

排版人员 快速排版_选择排版前应了解的事项

排版人员 快速排版Design is everywhere, and with design comes text and the content that you’re trying to reach the user with. But before creating your design and choosing what font you want to use, there are some things you should know that will help you a…

若川诚邀你加源码共读群,帮助更多人学会看源码~

小提醒&#xff1a;若川视野公众号面试、源码等文章合集在菜单栏中间【源码精选】按钮&#xff0c;欢迎点击阅读&#xff0c;也可以星标我的公众号&#xff0c;便于查找。回复pdf&#xff0c;可以获取前端优质书籍。最近我创建了一个源码共读的前端交流群&#xff0c;希望尝试帮…

imessage_重新设计iMessage以获得更好的用户体验— UX案例研究

imessage体验设计 (EXPERIENCE DESIGN) Communication is a vital part of our everyday lives. We almost don’t even have to think about it. With social media and our devices as prime tools, we’re constantly finding new ways to stay connected. Instant messagin…

mysql 生成时间轴,MYSQL 时间轴数据 获取同一天数据的前3条

创建表数据CREATE TABLE praise_info (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT ID,pic_id varchar(64) DEFAULT NULL COMMENT 图片ID,created_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间,PRIMARY KEY (id),KEY pic_id (pic_id) USING BTREE) ENGINEInn…

【招聘】永辉招前端

大家好&#xff0c;我是若川。这应该招聘第六期。友情帮好友宣传招聘。之前在跟各位读者朋友分享下公众号运营策略 文中提到 公众号主旨是帮助5年内前端小伙伴提升&#xff0c;找到好工作&#xff0c;所以有招聘文。上海 高级前端 本科 25k-50k 16薪岗位职责&#xff1a;1、…

插图 引用 同一行两个插图_插图的目的

插图 引用 同一行两个插图If you’re a designer in tech you’ve likely come across them. Any search for UI or product design on Dribbble will yield at least a few. Amid the sea of pastel blues and pinks, accented neon purples and gamboge yellows, these facel…

VSCode 竟然可以无缝调试浏览器了!

大家好&#xff0c;我是若川。今天周末&#xff0c;分享一篇相对比较简单的文章。学习源码系列、面试、年度总结、JS基础系列。2021-07-16 微软发布了一篇博客专门介绍了这个功能&#xff0c;VSCode 牛逼&#xff01;在此之前&#xff0c;你想要在 vscode 内调试 chrome 或者 e…

最少的编码

Knowing how to code HTML email can bring you many opportunities, such as working as a digital designer, collaborating with front end developers, finding freelancing projects.知道如何对HTML电子邮件进行编码可以为您带来许多机会&#xff0c;例如担任数字设计师&a…

Hulu CEO预计网站本年营收将达5亿美元

网易科技讯 3月2日动静&#xff0c;据国外媒体报道&#xff0c;美国在线视频网站Hulu CEO杰森吉拉尔&#xff08;Jason Kilar&#xff09;明天不日发挥分析&#xff0c;Hulu本年告白及订阅营收将达5亿美元&#xff0c;是去年的两倍。吉拉尔周一在由互联网告白局举办的“2011年年…

面对 this 指向丢失,尤雨溪在 Vuex 源码中是怎么处理的

1. 前言大家好&#xff0c;我是若川。好久以前我有写过《面试官问系列》&#xff0c;旨在帮助读者提升JS基础知识&#xff0c;包含new、call、apply、this、继承相关知识。其中写了 面试官问&#xff1a;this 指向 文章。在掘金等平台收获了还算不错的反馈。最近有小伙伴看我的…

单选按钮步骤流程向导 js_创建令人愉快的按钮的6个步骤

单选按钮步骤流程向导 jsThere is no modern interactive UI without buttons. They are an fundamental part of every digital solution. Learn how to improve the style of your buttons and delight users with perfect style.没有按钮&#xff0c;就没有现代的交互式UI。…

axios怎么封装,才能提升效率?

大家好&#xff0c;我是若川。今天分享一篇axios封装的文章。学习源码系列、面试、年度总结、JS基础系列。作为前端开发者&#xff0c;每个项目基本都需要和后台交互&#xff0c;目前比较流行的ajax库就是axios了&#xff0c;当然也有同学选择request插件&#xff0c;这个萝卜白…

护肤产生共鸣_通过以人为本的设计编织共鸣的20个指针

护肤产生共鸣Deep into a project right now, I can’t help but reflect on how I practice empathy in design. Human centered design means empathising with and designing for people, keeping our focus on people throughout. It is not just one stage, it is a minds…