从 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"}
}

同理可得:强制使用 npmpnpm也是类似设置。

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

3765aa9c5feb908512584d4d60661af4.png

调试截图

最终调试完会在终端报错提示使用 pnpm install

如下图所示:

92c761744ed79af76c0f4dd9f88e0c1a.png

终端报错截图

更多调试细节可以看我的这篇文章:新手向:前端程序员必学基本技能——调试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?

我在阿里招前端,该怎么帮你(可进面试群)

aacbcea36749e00447e5a51007bcc265.gif

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

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

99c451672624f46aacf7a0247525fbf8.png

识别方二维码加我微信、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

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

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

相关文章

什么事接口

假设你设计一个和人交流的程序。 先建立一个接口 interface 人 //定义接口&#xff0c;它代表一个人&#xff0c; {void Hello(); }//接口虚函数&#xff0c;用来跟这个人说话 但不同的人有不用的交流方式&#xff0c;具体方式用类来实现&#xff0c;比如。 class 美国人&#…

6个高效办公的Excel小技巧,学会让你高效办公

很多人在做Excel表格的时候&#xff0c;会出现下面这种情况&#xff1a;好不容易把内容都输入好了&#xff0c;才发现文字或是数字的排列组合需要重新调整&#xff0c;这个时候头就大了&#xff0c;到底是要一个个复制黏贴&#xff0c;还是要删除后再添加&#xff1f;不管哪种方…

unity 完美像素_像素完美

unity 完美像素从Kidpix到设计系统 (From Kidpix to design systems) Did you ever create stamps in KidPix? Kidpix is bitmap drawing software that’s been around since the nineties, and I remember many happy — more like maddening — hours creating tiny pixela…

整整4个月了,尽全力组织了源码共读活动~

大家好&#xff0c;我是若川。从8月份到现在11月结束了。每周一期&#xff0c;一起读200行左右的源码&#xff0c;撰写辅助文章&#xff0c;截止到现在整整4个月了。由写有《学习源码整体架构系列》20余篇的若川【若川视野公众号号主】倾力组织&#xff0c;召集了各大厂对于源码…

kvm 学习(二)

Linux下 如何通过命令行使用现有的镜像创建、启动kvm虚拟机 这里假定已经创建好了相应的镜像&#xff1a; eg&#xff1a;我这里制作的镜像名称为zu1-centos7.img # lszu1-centos7.img 1、拷贝这个镜像到某一个目录 cp zu1-centos7.img /data2/ 2、编写镜像的配置文件&#x…

字节内部前端开发手册(完整版)开放下载!

备战2022&#xff0c;准备好了吗&#xff1f;据字节HR部门发布的最新信息&#xff0c;2019年以来字节连续3年扩招&#xff0c;而即将到来的2022年春招前端岗位数不低于3000&#xff0c;虽连年扩招&#xff0c;但是报录比却从2019年的3%下降到今年的1%。BAT等一线大厂同样有类似…

EBS中Java并发程序笔记(1)

在Oracle EBS中的Java并发程序&#xff08;Java Concurrent Program&#xff09;是系统功能中的一个亮点&#xff0c;它的出现使得用户可以在ERP系统中运行自己定义的Java程序。本文为学习笔记&#xff0c;所以不会介绍太多背景知识。 使用Java并发程序的好处&#xff1a; 当遇…

figma设计_5位来自杂乱无章的设计师的Figma技巧

figma设计When starting a design project, a fast pace and multiple design iterations can easily lead to a cluttered mess. Taking the time in the beginning to build good organizational habits will save you time later. You’ll thank your past self when you do…

hello,你知道获取元素有哪几种方式吗?

收下我的小心心&#xff01;&#xff08;害羞脸&#xff09; 根据id属性的值获取元素&#xff0c;返回来的是一个元素对象 document.getElementById("id属性的值") 根据标签名获取元素&#xff0c;返回来的是一个伪数组&#xff0c;里面保存了多个的DOM对象 documen…

设计和实现一个 Chrome 插件提升登录效率

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。前言在我们的工作过程中&#xff0c;每当…

[待总结]redmine

先列出来&#xff0c;有空再总结转载于:https://www.cnblogs.com/gracexiao/archive/2011/11/18/2253834.html

qq空间网页设计_网页设计中的负空间

qq空间网页设计重点 (Top highlight)Because screens are limited, web design is also limited. It can be said that in the small box of the screen, each pixel is a piece of real estate.由于屏幕有限&#xff0c;因此网页设计也受到限制。 可以说&#xff0c;在屏幕的小…

前端组件化-抽象公共组件类

优化上次的组件化小demo 上次的组件化demo只是为了简单的实现前端组件化的思想&#xff0c;这次我们稍微优化一下抽离公共类 下面代码 html <div id"wrapper"></div> 复制代码js /* DOM字符串转DOM节点 */ const createStringToDom str > {const ele…

时隔一年半,我,一个卑微的前端菜鸡,又来写面经了

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。作者&#xff1a;刮涂层_赢大奖原文地址…

javascript模版引擎-tmpl的bug修复与性能优化

http://www.planeart.cn/?p1594 http://ejohn.org/blog/javascript-micro-templating http://bbs.phpchina.com/thread-224712-1-1.html [ Noevil: 下面直接贴出改进好的MicroTemp&#xff0c;但是还是建议看一下原文&#xff0c;里面有详细的改进细节&#xff0c;和改进前后的…

2019.5.8_此书真乃宝书也_从定位参数到仅限关键字参数

《摘自流畅的Python》 此书真乃宝书也,虽说还是有点儿没懂 从定位参数到仅限关键字参数 Python最好的特性之一是提供了极为灵活的参数处理机制&#xff0c;而且Python3进一步提供了仅限关键字参数(keyword-only argument)。与之密切相关的是&#xff0c;调用函数时使用*和**“展…

用户体验与可用性测试_可用性作为用户体验的原则

用户体验与可用性测试Every UX Designer has his views and best practices. We all have a guide book created through time and experience. I want to share mine with you.每个UX设计器都有他的观点和最佳实践。 我们都有一本通过时间和经验编写的指南。 我想和你分享我的…

Jenkins插件之Deploy

deploy插件&#xff1a; Deploy Plugindeploy插件支持将War/Jar部署到远程的应用服务器上&#xff0c;例如Tomcat,JBoss,Glassfish。正在寻找或开发.NET web 应用的自动发布插件。如何回滚或重新部署先前的build&#xff1a;0&#xff09; 需要被deploy的job的结果要存档&#…

受美国法律保护美国妞_为什么美国法律有效地要求所有软件设计都要响应

受美国法律保护美国妞Smashing Magazine defines “responsive design” as an approach where design responds to the user’s behavior and environment based on screen size, platform, and orientation. In responsive design, a breakpoint is the “point” at which a…

源码群友问:你这么多项目是怎么进行技术选型的?

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信ruochuan12 进群参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。已进行4个月了&#xff0c;很多小伙伴表示收获颇丰。源码群有群友提问我是怎么找到那么多npm…