从 vue3 和 vite 源码中,我学到了一行代码统一规范团队包管理器的神器
1. 前言
大家好,我是若川。最近组织了源码共读活动,感兴趣的可以加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。已进行四个月了,很多小伙伴表示收获颇丰。
想学源码,极力推荐之前我写的《学习源码整体架构系列》 20余篇源码文章。
本文仓库 only-allow-analysis,求个star^_^[1]
最近组织了源码共读活动,每周大家一起学习200行左右的源码。每周一期,已进行到14期。于是搜寻各种值得我们学习,且代码行数不多的源码。
阅读本文,你将学到:
1. 如何学习调试源码
2. 学会 npm 钩子
3. 学会 "preinstall": "npx only-allow pnpm" 一行代码统一规范包管理器
4. 学到 only-allow 原理
5. 等等
2. 场景
我们项目开发时,常需要安装依赖,虽说一般用文档可以说明。但不是比较强制的约束。是人就容易犯错或者疏忽,假如规定是用的npm
,而团队里有人某一天不小心使用了其他包管理器安装了的其他依赖,上传了代码,严重时可能导致线上问题。所以我们需要借助工具(代码)来强制约束。
在源码共读第12期[2]中,我们学习了尤雨溪推荐神器 ni ,能替代 npm/yarn/pnpm ?简单好用!源码揭秘!根据锁文件自动匹配相应的包管理器,运行相应的命令。
在源码共读第3期[3]中,我们学习了Vue 3.2 发布了,那尤雨溪是怎么发布 Vue.js 的?
其中 Vue3 源码用了 npm 的 preinstall
钩子[4] 约束,只能使用 pnpm
安装依赖。我们接着来看其实现。
3. Vue3 源码 && npm 命令钩子
// vue-next/package.json
{"private": true,"version": "3.2.22","scripts": {"preinstall": "node ./scripts/preinstall.js",}
}
依次执行
# install 之前执行这个脚本
preinstall
# 执行 install 脚本
install
# install 之后执行这个脚本
postinstall
当然也支持自定义的命令。
更多可以查看官方文档钩子[5]。
接着我们来看 preinstall[6] 源码。
// vue-next/scripts/preinstall.jsif (!/pnpm/.test(process.env.npm_execpath || '')) {console.warn(`\u001b[33mThis repository requires using pnpm as the package manager ` +` for scripts to work properly.\u001b[39m\n`)process.exit(1)
}
这段代码也相对简单,校验如果不是 pnpm
执行脚本则报错,退出进程。
关于 process
对象可以查看 阮一峰老师 process 对象[7]
process.argv
属性返回一个数组,由命令行执行脚本时的各个参数组成。它的第一个成员总是node
,第二个成员是脚本文件名,其余成员是脚本文件的参数。
这段代码能解决文章开头场景提出的问题,但是总不能每个项目都复制粘贴这段代码吧。我们是不是可以封装成 npm 包使用。当时我也没想太多,也没有封装 npm 包。直到我翻看 vite[8] 源码发现了 only-allow[9] 这个包。一行代码统一规范包管理器。
{"scripts": {"preinstall": "npx only-allow pnpm -y"}
}
当时看到这段代码时,我就在想:他们咋知道这个的。当时依旧也没想太多。直到有一天,发现 pnpm 文档 Only allow pnpm 文档[10] 上就有这个。好吧,吃了没看文档的亏。那时我打算分析下这个only-allow 包的源码[11],打开一看惊喜万分,才 36 行,写它,于是写了这篇文章。
按照惯例,看源码前先准备环境。
4. 环境准备
先克隆代码。
4.1 克隆代码
# 推荐克隆我的源码库
git clone https://github.com/lxchuan12/only-allow-analysis.git
cd only-allow-analysis/only-allow
# npm i -g pnpm
pnpm i# 或者克隆官方仓库
git clone https://github.com/pnpm/only-allow.git
cd only-allow
# npm i -g pnpm
pnpm i
开源项目一般先看README.md[12]。
Force a specific package manager to be used on a project
强制在项目上使用特定的包管理器
Usage
Add a preinstall script to your project's package.json.
If you want to force yarn[13], add:
{"scripts": {"preinstall": "npx only-allow yarn"}
}
同理可得:强制使用 npm
、pnpm
也是类似设置。
4.2 调试源码
我们通过查看 package.json
文件。
// only-allow/package.json
{"bin": "bin.js",
}
确定主入口文件为 only-allow/bin.js
。
在最新版的 VSCode
中,auto attach
功能,默认支持智能调试,如果发现不支持,可以通过快捷键 ctrl + shift + p
查看是否启用。
于是我们在 only-allow/package.json
文件中,添加如下命令。
// only-allow/package.json
{"scripts": {"preinstall": "node bin.js pnpm"},
}
可以提前在 only-allow/bin.js
文件打上断点 const usedPM = whichPMRuns()
按快捷键 ctrl + ` 快捷键打开终端。输入如下 yarn add release-it -D
命令,即可调试 only-allow/bin.js
。
最终调试完会在终端报错提示使用 pnpm install
。
如下图所示:
更多调试细节可以看我的这篇文章:新手向:前端程序员必学基本技能——调试JS代码[14]
接着我们按调试来看源码主流程。
5. only-allow 源码
// only-allow/bin.js
#!/usr/bin/env node
const whichPMRuns = require('which-pm-runs')
// 输出边框盒子
const boxen = require('boxen')const argv = process.argv.slice(2)
if (argv.length === 0) {console.log('Please specify the wanted package manager: only-allow <npm|pnpm|yarn>')process.exit(1)
}
// 第一个参数则是 用户传入的希望使用的包管理器
// 比如 npx only-allow pnpm
// 这里调试是 node bin.js pnpm
const wantedPM = argv[0]
// npm pnpm yarn 都不是,则报错
if (wantedPM !== 'npm' && wantedPM !== 'pnpm' && wantedPM !== 'yarn') {console.log(`"${wantedPM}" is not a valid package manager. Available package managers are: npm, pnpm, or yarn.`)process.exit(1)
}
// 使用的包管理器
const usedPM = whichPMRuns()
// 希望使用的包管理器 不相等,则报错。
// - npm 提示使用 npm install
// - pnpm 提示使用 pnpm install
// - yarn 提示使用 yarn install
// 最后退出进程
if (usedPM && usedPM.name !== wantedPM) {const boxenOpts = { borderColor: 'red', borderStyle: 'double', padding: 1 }switch (wantedPM) {case 'npm':console.log(boxen('Use "npm install" for installation in this project', boxenOpts))breakcase 'pnpm':console.log(boxen(`Use "pnpm install" for installation in this project.If you don't have pnpm, install it via "npm i -g pnpm".
For more details, go to https://pnpm.js.org/`, boxenOpts))breakcase 'yarn':console.log(boxen(`Use "yarn" for installation in this project.If you don't have Yarn, install it via "npm i -g yarn".
For more details, go to https://yarnpkg.com/`, boxenOpts))break}process.exit(1)
}
跟着断点,我们可以查看到 which-pm-runs[15]。
6. which-pm-runs 当前运行的是哪一个包管理器
最终返回包管理器和版本号。
根据调试可知,process.env.npm_config_user_agent
是类似这样的字符串。
"yarn/1.22.10 npm/? node/v14.16.0 linux x64"
'use strict'module.exports = function () {if (!process.env.npm_config_user_agent) {return undefined}return pmFromUserAgent(process.env.npm_config_user_agent)
}function pmFromUserAgent (userAgent) {const pmSpec = userAgent.split(' ')[0]const separatorPos = pmSpec.lastIndexOf('/')return {name: pmSpec.substr(0, separatorPos),version: pmSpec.substr(separatorPos + 1)}
}
6.1 String.prototype.substr 截取字符串
顺带提下。我之前在 vue-next 源码看到的 pull request => chore: remove deprecated String.prototype.substr[16]
String.prototype.substr is deprecated.
也就是说不推荐使用 substr
。推荐使用 slice
。
ecma 规范[17]
7. 总结
我们通过从团队需要规范统一包管理器的实际场景出发,讲了 vue3 源码中 preinstall 钩子 约束只能使用 pnpm 。同时通过查看 vite[18] 源码和 pnpm[19] 文档,了解到 only-allow[20] 这个包。可以做到一行代码统一规范包管理器"preinstall": "npx only-allow pnpm"
。
也学习了其原理。only-allow 期待的包管理器和运行的包管理器对比。匹配失败,则报错。而which-pm-runs 通过获取 process.env.npm_config_user_agent
变量获取到当前运行脚本的包管理器和版本号。
我们通过文档和沟通约束,不如用工具(代码)约束。
文章写到这里,让我想起我2018年写的文章参加有赞前端技术开放日所感所想[21]
当时演讲的大佬说过一句话。无比赞同。
技术(开源)项目本质上是:理念、套路、规范的工具化。
同时给我们的启发也是要多看官方文档和规范。
建议读者克隆我的仓库[22]动手实践调试源码学习。
最后可以持续关注我@若川。欢迎加我微信 ruochuan12[23] 交流,参与 源码共读[24] 活动,每周大家一起学习200行左右的源码,共同进步。
参考资料
[1]
本文仓库 only-allow-analysis,求个star^_^: https://github.com/lxchuan12/only-allow-analysis.git
最近组建了一个江西人的前端交流群,如果你是江西人可以加我微信 ruochuan12 私信 江西 拉你进群。
推荐阅读
1个月,200+人,一起读了4周源码
我历时3年才写了10余篇源码文章,但收获了100w+阅读
老姚浅谈:怎么学JavaScript?
我在阿里招前端,该怎么帮你(可进面试群)
················· 若川简介 ·················
你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》10余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结。
同时,最近组织了源码共读活动,帮助1000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。
识别上方二维码加我微信、拉你进源码共读群
今日话题
略。分享、收藏、点赞、在看我的文章就是对我最大的支持~
从 vue3 和 vite 源码中,我学到了一行代码统一规范团队包管理器的神器相关推荐
- OpenCV源码中Haar训练及特征提取的代码说明
//针对大小为winsize的图,计算所有HaarFeature的rect,存入features返回,即获取所有特征坐标 CvIntHaarFeatures* icvCreateIntHaarFeat ...
- 从Vue.js源码中我学到的几个实用函数
大家好,我是若川.欢迎加我微信 ruochuan12,长期交流学习.今天推荐Vuejs源码中几个实用的方法. 如果想看Vuejs源码,不知道如何下手,一般推荐配置Sourcemap,针对单个问题调试来 ...
- 4hutool源码分析:DateUtil(时间工具类)-格式化时间(万字长文源码分析,学大佬如何写代码)
技术活,该赏 点赞再看,养成习惯 看本篇文章前,建议先对java源码的日期和时间有一定的了解,如果不了解的话,可以先看这篇文章: 万字博文教你搞懂java源码的日期和时间相关用法 关联文章: huto ...
- ofo html源码,Github最火开源项目-一行代码实现ofo小黄车的引导界面
自定义控件 联网 工具 数据库 源码分析相关面试题 Activity相关面试题 Service相关面试题 与XMPP相关面试题 与性能优化相关面试题 与登录相关面试题 与开发相关面试题 与人事相关面试 ...
- 使用 Chrome 调试 Vue3 的 TypeScript 源码
相信很多同学都已经上手 Vue3 了,用起来是真香! 学习技术又怎能不学习源码,多看看源码,说不定自己哪天也成大佬了呢 ︿( ̄︶ ̄)︿ 今天,我来记录一下自己调试 Vue3 源码的过程,方便以后参考. ...
- 【Faster R-CNN论文精度系列】从Faster R-CNN源码中,我们“学习”到了什么?
[Faster R-CNN论文精度系列] (如下为建议阅读顺序) 1[Faster R-CNN论文精度系列]从Faster R-CNN源码中,我们"学习"到了什么? 2[Faste ...
- 以rpm为后端及以yum为前端工具的程序包管理器在Linux发行版系统centos中的使用...
程序包管理: 应用程序的安装,实际上是解压缩并复制程序包中的文件到指定目录的过程: 程序包管理器: 方便终端用户进行程序的安装.卸载.升级.安装信息查询及校验等工作: 不同的Linux的发行版本中,有 ...
- 学习尤雨溪写的 Vue3 源码中的简单工具函数
大家好,我是若川.最近组织了源码共读活动.每周读 200 行左右的源码.很多第一次读源码的小伙伴都感觉很有收获,感兴趣可以加我微信ruochuan12,拉你进群学习. 初学者也能看懂的 Vue3 源码 ...
- 初学者也能看懂的 Vue3 源码中那些实用的基础工具函数
1. 前言 大家好,我是若川.最近组织了源码共读活动.每周读 200 行左右的源码.很多第一次读源码的小伙伴都感觉很有收获,感兴趣可以加我微信ruochuan12,拉你进群学习. 写相对很难的源码,耗 ...
最新文章
- php使用redis的GEO地理信息类型
- microsoft edge 打不开 csdn 博客
- 枚举类的使用-使用实例域来替代序数
- java.lang.NoClassDefFoundError: org/springframework/dao/support/PersistenceE解决方法
- 【机卓14蒋海平-U201411018】机电传动控制课程-《自动化技术中的进给电气传动》第一章的1.1节和1.2节——读书笔记整理...
- VGA显示器驱动设计与验证
- 第 5-5 课:线程安全——synchronized 和 ReentrantLock + 面试题
- sublime安装AngularJS插件
- 一个自动上传ip到ftp服务器的bat脚本
- sql azure 语法_Azure Data Studio中SQL代码段
- 最新型号设备信息对照表_高利洁中央空调风管清洗设备:K11三维度清扫除尘一体机器人...
- [转]微波/毫米波雷达
- Go:表驱动单元测试
- 深入理解JavaScript内部原理(6): 闭包
- Linux中查看进程命令ps aux,ps -ef,ps -A,ps -a
- Wordle_1.0
- 网络编程(三)sqlist轻量级数据库的简单应用
- Python网络爬虫(二):小说下载器
- YII2框架AJAX请求报500错误的处理方法
- bestCoder 2015 百度之星程序设计大赛 资格赛-1003-IP聚合
热门文章
- 第3章 Python 数字图像处理(DIP) - 灰度变换与空间滤波17 - 锐化高通滤波器 - 梯度图像(罗伯特,Sobel算子)
- python引入redis_使用python向Redis批量导入数据
- 车间生产能耗管控方案_SAREN三仁净化工程:锂电池生产车间的设计规范及方案...
- 配置springboot在访问404时自定义返回结果以及统一异常处理
- Scrapy-redis实现分布式爬取的过程与原理
- 【bzoj2326】[HNOI2011]数学作业 矩阵乘法
- hadoop入门小知识点
- 《架构之美》阅读笔记四
- linux查看文件大小
- matlab标准化出现负值,为什么我求出来的约束条件是负值