Vue团队核心成员开发的39行小工具 install-pkg 安装包,值得一学!

1. 前言

大家好,我是若川。最近组织了源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。

本文仓库 https://github.com/lxchuan12/install-pkg-analysis.git,求个star^_^[1]

源码共读活动 每周一期,已进行到16期。Vue团队核心成员 Anthony Fu 开发的 install-pkg[2] 小工具,主文件源码仅39行,非常值得我们学习。

阅读本文,你将学到:

1. 如何学习调试源码
2. 如何开发构建一个 ts 的 npm 包
3. 如何配置 github action
4. 配置属于自己的 eslint 预设、提升版本号等
5. 学会使用 execa 执行命令
6. 等等

2. install-pkg 是什么

Install package programmatically. Detect package managers automatically (npm, yarn and pnpm).

以编程方式安装包。自动检测包管理器(npmyarnpnpm)。

npm i @antfu/install-pkg
import { installPackage } from '@antfu/install-pkg'
await installPackage('vite', { silent: true })

我们看看npmjs.com @antfu/install-pkg[3] 有哪些包依赖的这个包。

我们可以发现目前只有以下这两个项目使用了。

unplugin-icons[4]@chenyueban/lint[5]

我们克隆项目来看源码。

3 克隆项目

# 推荐克隆我的项目,保证与文章同步
git clone https://github.com/lxchuan12/install-pkg-analysis.git
# npm i -g pnpm
cd install-pkg-analysis/install-pkg && pnpm i
# VSCode 直接打开当前项目
# code .# 或者克隆官方项目
git clone https://github.com/antfu/install-pkg.git
# npm i -g pnpm
cd install-pkg && pnpm i
# VSCode 直接打开当前项目
# code .

看源码一般先看 package.json,再看 script

{"name": "@antfu/install-pkg","version": "0.1.0","scripts": {"start": "esno src/index.ts"},
}

关于调试可以看我的这篇文章:新手向:前端程序员必学基本技能——调试JS代码,这里就不再赘述了。

我们可以得知入口文件是 src/index.ts

src文件夹下有三个文件

src
- detect.ts
- index.ts
- install

接着我们看这些文件源码。

4. 源码

4.1 index.js

导出所有

// src/install.ts
export * from './detect'
export * from './install'

我们来看 install.ts 文件,installPackage 方法。

4.2 installPackage 安装包

// src/install.ts
import execa from 'execa'
import { detectPackageManager } from '.'export interface InstallPackageOptions {cwd?: stringdev?: booleansilent?: booleanpackageManager?: stringpreferOffline?: booleanadditionalArgs?: string[]
}export async function installPackage(names: string | string[], options: InstallPackageOptions = {}) {const agent = options.packageManager || await detectPackageManager(options.cwd) || 'npm'if (!Array.isArray(names))names = [names]const args = options.additionalArgs || []if (options.preferOffline)args.unshift('--prefer-offline')return execa(agent,[agent === 'yarn'? 'add': 'install',options.dev ? '-D' : '',...args,...names,].filter(Boolean),{stdio: options.silent ? 'ignore' : 'inherit',cwd: options.cwd,},)
}

支持安装多个,也支持指定包管理器,支持额外的参数。

其中 github execa[6] 是执行脚本

Process execution for humans

也就是说:最终执行类似以下的脚本。

pnpm install -D --prefer-offine release-it react antd

我们接着来看 detect.ts文件 探测包管理器 detectPackageManager 函数如何实现的。

4.3 detectPackageManager 探测包管理器

根据当前目录锁文件,探测包管理器。

// src/detect.ts
import path from 'path'
import findUp from 'find-up'export type PackageManager = 'pnpm' | 'yarn' | 'npm'const LOCKS: Record<string, PackageManager> = {'pnpm-lock.yaml': 'pnpm','yarn.lock': 'yarn','package-lock.json': 'npm',
}export async function detectPackageManager(cwd = process.cwd()) {const result = await findUp(Object.keys(LOCKS), { cwd })const agent = (result ? LOCKS[path.basename(result)] : null)return agent
}

其中 find-up[7] 查找路径。

/
└── Users└── install-pkg├── pnpm-lock.yaml
import {findUp} from 'find-up';console.log(await findUp('pnpm-lock.yaml'));
//=> '/Users/install-pkg/pnpm-lock.yaml'

path.basename('/Users/install-pkg/pnpm-lock.yaml') 则是 pnpm-lock.yaml

所以在有pnpm-lock.yaml文件的项目中,detectPackageManager 函数最终返回的是 pnpm

至此我们可以用一句话总结原理就是:通过锁文件自动检测使用何种包管理器(npm、yarn、pnpm),最终用 execa[8] 执行类似如下的命令。

pnpm install -D --prefer-offine release-it react antd

看完源码,我们接着来解释下 package.json 中的 scripts 命令。

5. package.json script 命令解析

{"name": "@antfu/install-pkg","version": "0.1.0","scripts": {"prepublishOnly": "nr build","dev": "nr build --watch","start": "esno src/index.ts","build": "tsup src/index.ts --format cjs,esm --dts --no-splitting","release": "bumpp --commit --push --tag && pnpm publish","lint": "eslint \"{src,test}/**/*.ts\"","lint:fix": "nr lint -- --fix"},
}

5.1 ni 神器

github ni[9]

我之前写过源码文章。

尤雨溪推荐神器 ni ,能替代 npm/yarn/pnpm ?简单好用!源码揭秘![10]

自动根据锁文件 yarn.lock / pnpm-lock.yaml / package-lock.json 检测使用 yarn / pnpm / npm 的包管理器。

nr dev --port=3000# npm run dev -- --port=3000
# yarn run dev --port=3000
# pnpm run dev -- --port=3000
nr
# 交互式选择脚本
# interactively select the script to run
# supports https://www.npmjs.com/package/npm-scripts-info convention

nci - clean install

nci
# npm ci
# 简单说就是不更新锁文件
# yarn install --frozen-lockfile
# pnpm install --frozen-lockfile

pnpm install --frozen-lockfile[11]

5.2 esno 运行 ts

esno[12]

TypeScript / ESNext node runtime powered by esbuild

源码也不是很多。

#!/usr/bin/env nodeconst spawn = require('cross-spawn')
const spawnSync = spawn.syncconst register = require.resolve('esbuild-register')const argv = process.argv.slice(2)process.exit(spawnSync('node', ['-r', register, ...argv], { stdio: 'inherit' }).status)

esbuild-register[13]简单说:使用 esbuild 即时传输 JSX、TypeScript 和 esnext 功能

5.3 tsup 打包 ts

打包 TypeScript 库的最简单、最快的方法。

tsup[14]

5.4 bumpp 交互式提升版本号

bumpp[15]

version-bump-prompt[16]

交互式 CLI 可增加您的版本号等

5.5 eslint 预设

eslint 预设[17]

pnpm add -D eslint @antfu/eslint-config

添加 .eslintrc 文件

// .eslintrc
{"extends": ["@antfu"],"rules": {}
}

之前看其他源码发现的也很好用的 eslint 工具 xo

xo[18]

JavaScript/TypeScript linter (ESLint wrapper) with great defaults JavaScript/TypeScript linter(ESLint 包装器)具有很好的默认值

看完 scripts 命令解析,我们来看看 github action 配置。

6. github action workflows

对于github action 不熟悉的读者,可以看阮一峰老师 GitHub Actions 入门教程[19]

配置文件workflows/release[20]

构建历史github action workflow[21]

name: Releaseon:push:tags:- 'v*'jobs:release:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v2with:fetch-depth: 0- uses: actions/setup-node@v2with:node-version: '14'registry-url: https://registry.npmjs.org/- run: npm i -g pnpm @antfu/ni- run: nci- run: nr test --if-present- run: npx conventional-github-releaser -p angularenv:CONVENTIONAL_GITHUB_RELEASER_TOKEN: ${{secrets.GITHUB_TOKEN}}

根据每次 tags 推送,执行。

# 全局安装 pnpm 和 ni
npm i -g pnpm @antfu/ni
# 如何存在 test 命令则执行
nr test --if-present

nci - clean install

nci
# npm ci
# 简单说就是不更新锁文件
# yarn install --frozen-lockfile
# pnpm install --frozen-lockfile

最后 npx conventional-github-releaser -p angularconventional-github-releaser[22]

生成 changelog

至此我们就学习完了 install-pkg[23] 包。

7. 总结

整体代码比较简单。原理就是通过锁文件自动检测使用何种包管理器(npm、yarn、pnpm),最终用 execa[24] 执行类似如下的命令。

pnpm install -D --prefer-offine release-it react antd

我们学到了:

1. 如何学习调试源码
2. 如何开发构建一个 ts 的 npm 包
3. 如何配置 github action
4. 配置属于自己的 eslint 预设、提升版本号等
5. 学会使用 execa 执行命令
6. 等等

还有各种依赖工具。

建议读者克隆 我的仓库[25] 动手实践调试源码学习。

最后可以持续关注我@若川。欢迎加我微信 ruochuan12 交流,参与 源码共读 活动,每周大家一起学习200行左右的源码,共同进步。

参考资料

[1]

本文仓库 https://github.com/lxchuan12/install-pkg-analysis.git,求个star^_^: https://github.com/lxchuan12/install-pkg-analysis.git
更多资料点击阅读原文查看

208ae9c58817eed53856c7888ce15771.gif

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

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

6bfc7c64144aaf513a230a2762ce36be.png

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

今日话题

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

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

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

相关文章

人脸识别及对比_没有“色彩对比可及性的神话”

人脸识别及对比重点 (Top highlight)When you need to work on interfaces, color contrast is a real thing you have to take into account to make it accessible. You have the right to be afraid of losing part of the aesthetics of your beautifully well-designed in…

Entity Framework4.0 (一)概述(EF4 的Database First方法)

Entity Framework4.0(以后简称&#xff1a;EF4)&#xff0c;是Microsoft的一款ORM&#xff08;Object-Relation-Mapping&#xff09;框架。同其它ORM&#xff08;如&#xff0c;NHibernate,Hibernate&#xff09;一样&#xff0c;一是为了使开发人员以操作对象的方式去操作关系…

mysql 相关子查询使用【主表得数据需要扩展(统计数据依赖与其他表,但是与主表有关联)】...

2019独角兽企业重金招聘Python工程师标准>>> SELECT t.building,t.unit,t.room,t.ashcan ,(SELECT COUNT(a.resident_id) from t_address_book a where a.village_id t.village_id AND a.building t.building and a.room t.unit and a.house t.room and…

竟然被尤雨溪点赞了:我给Vue生态贡献代码的这一年

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。这篇文章在知乎被尤雨溪…

java版电子商务spring cloud分布式微服务b2b2c社交电商(四)SpringBoot 整合JPA

b2b2c电子商务社交平台源码请加企鹅求求&#xff1a;一零三八七七四六二六。JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。JPA 的目标之一是制定一个可以由很多供应商实现的AP…

60款很酷的 jQuery 幻灯片演示和下载

jQuery 是一个非常优秀的 JavaScript 框架&#xff0c;使用简单灵活&#xff0c;同时还有许多成熟的插件可供选择&#xff0c;它可以帮助你在项目中加入漂亮的效果&#xff0c;其中之一就是幻灯片&#xff0c;一种在有限的网页空间内展示系列项目时非常好的方法。今天这篇文章要…

流体式布局与响应式布局_将固定像素设计转换为流体比例布局

流体式布局与响应式布局Responsive web design has been a prime necessity for every enterprise ever since Google announced that responsive, mobile-friendly websites will see a hike in their search engine rank in 2015.自Google宣布响应式&#xff0c;移动友好型网…

怎样开发一个 Node.js 命令行工具包

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。源码共读活动很多都是读…

redis完全攻略

安装篇 声明&#xff1a;以下环境均是在ubuntu下进行 wget http://redis.googlecode.com/files/redis-2.4.4.tar.gztar zxf redis-2.4.4.tar.gz 然后进入目录后直接make就可以了、如果迩的系统是32位的那么执行 make 32bit 安装完成后、执行一下make test看是否正常、如果出现“…

印刷报价系统源码_皇家印刷术-设计系统案例研究

印刷报价系统源码重点 (Top highlight)Typography. It’s complicated. With Product Design, it’s on every screen. Decisions for a type scale affect literally every aspect of a product. When you’re working with an existing product, defining typography can fee…

Python简单试题3

1&#xff0c;水仙花数 水仙花数是指一个 3 位数&#xff0c;它的每个位上的数字的 3次幂之和等于它本身 &#xff08;例如&#xff1a;1^3 5^3 3^3 153&#xff09; 代码如下&#xff1a; 方法一&#xff1a; for i in range(100,1000): # 进行for循环num ia num % 10 # …

React Hooks 完全使用指南

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。React HooksHook 是什么…

重新设计Videoland的登录页面— UX案例研究

In late October of 2019 me and our CRO lead Lucas, set up a project at Videoland to redesign our main landing page for prospect customers (if they already have a subscription, they will go to the actual streaming product).在2019年10月下旬&#xff0c;我和我…

【常见Web应用安全问题】---5、File Inclusion

Web应用程序的安全性问题依其存在的形势划分&#xff0c;种类繁多&#xff0c;这里不准备介绍所有的&#xff0c;只介绍常见的一些。 常见Web应用安全问题安全性问题的列表&#xff1a;   &#xff11;、跨站脚本攻击(CSS or XSS, Cross Site Scripting)   &#xff12;、S…

全新的 Vue3 状态管理工具:Pinia

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。Vue3 发布已经有一段时间…

JS中变量和函数的使用

一、变量的介绍 1、啥是变量&#xff1f; 变量的本质是一块有名字的内存空间。变量由变量名和变量值构成。变量名指的是内存空间的别名&#xff0c;一般位于赋值运算符的左边&#xff1b;而变量值指的是内存空间中的数据&#xff0c;一般位于赋值运算符的右边。例如:var balanc…

Win32 API消息函数:GetMessagePos

Win32 API消息函数:GetMessagePos 函数功能&#xff1a;该函数返回表示屏幕坐标下光标位置的长整数值。此位置表示当上一消息由GetMessage取得时鼠标占用的点。 函数原型&#xff1a;DWORD GetMessagePos&#xff08;VOID&#xff09; 参数&#xff1a;无。 返回值&…

都快 2022 年了,这些 Github 使用技巧你都会了吗?

大家好&#xff0c;我是若川。最近组织了源码共读活动&#xff0c;感兴趣的可以点此加我微信 ruochuan12 参与&#xff0c;每周大家一起学习200行左右的源码&#xff0c;共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。最近经常有小伙伴问我如…

单线程+异步协程

一 . 线程池和进程池 可以适当的使用,在大量的IO情况下有更好的方法 import time from multiprocessing.dummy import Pool def request(url):print(正在下载->,url)time.sleep(2)print(下载完毕->,url) start time.time() urls [www.baidu.com,www.taobao.com,www.sou…

Repeater\DataList\GridView实现分页,数据编辑与删除

一、实现效果 1、GridView 2、DataList 3、Repeater 二、代码 1、可以去Csdn资源下载&#xff0c;包含了Norwind中文示例数据库噢&#xff01;&#xff08;放心下&#xff0c;不要资源分&#xff09; 下载地址&#xff1a;数据控件示例源码Norwind中文数据库 2、我的开发环境&a…