1. Введение
Привет всем, яВакагава. Добро пожаловать, чтобы следовать за мнойПубличный аккаунт Wakagawa Vision, недавно организованныйЧитайте исходный код вместеДействия, если вам интересно, вы можете добавить меня в WeChatruochuan12, долгосрочный обмен и обучение.
написано раньше"Изучение серии "Общая архитектура исходного кода""ВключаютjQuery
,underscore
,lodash
,vuex
,sentry
,axios
,redux
,koa
,vue-devtools
,vuex4
Десять статей с исходным кодом.
Написание относительно сложного исходного кода стоило мне времени и энергии, и я не получил много лайков от чтения.На самом деле, это был настоящий удар. С точки зрения объема чтения и выгоды для читателей это не может способствовать непрерывному выпуску статей авторами.
Так что измените свое мнение и напишите несколько относительно простых для понимания статей.На самом деле исходный код не так сложен, как можно себе представить, по крайней мере многие смогут понять.
You Yuxi недавно выпустила версию 3.2. Младшая версия уже3.2.4
. Эта статья предназначена для того, чтобы узнать, как выпускается Youda.vuejs
Да, изучите исходный код для собственного использования.
эта статья посвященаvue-next/scripts/release.js
файл, количество строк кода во всем файле составляет всего200
Это больше, чем линия, но этому стоит научиться.
Гёте однажды сказал: «Читать хорошую книгу — значит разговаривать с благородными людьми». То же самое можно получить: чтение исходного кода — это тоже способ обучения и общения с автором.
Прочитав эту статью, вы узнаете:
1. 熟悉 vuejs 发布流程
2. 学会调试 nodejs 代码
3. 动手优化公司项目发布流程
Прежде чем подготавливать окружение, давайте предварительно его просмотрим.vuejs
процесс выпуска.
2. Подготовка окружающей среды
Открытымvue-next,
Проекты с открытым исходным кодом обычно можно найти вREADME.md
или.github/contributing.mdНайдите рекомендации по содействию.
И Contribution Guide много пишет об участии в разработке проекта. Например, как запустить, какова структура каталогов проекта. Как инвестировать в развитие, какие нужны резервы знаний и т.д.
вам нужно убедитьсяNode.jsверсия10+
, иyarn
Версия1.x
Yarn 1.x.
вы установилиNode.js
версия скорее всего ниже10
. Самый простой способ — зайти на официальный сайт для переустановки. Также можно использоватьnvm
и т.д. управлениеNode.js
Версия.
node -v
# v14.16.0
# 全局安装 yarn
# 建议克隆我的项目
git clone https://github.com/lxchuan12/vue-next-analysis.git
cd vue-next-analysis/vue-next
# 或者克隆官方项目
git clone https://github.com/vuejs/vue-next.git
cd vue-next
# 安装 yarn
npm install --global yarn
# 安装依赖
yarn # install the dependencies of the project
# yarn release
2.1 Строго проверяйте использование пряжи для установки зависимостей
Тогда давайте посмотримvue-next/package.json
документ.
// vue-next/package.json
{
"private": true,
"version": "3.2.4",
"workspaces": [
"packages/*"
],
"scripts": {
// --dry 参数是我加的,如果你是调试 代码也建议加
// 不执行测试和编译 、不执行 推送git等操作
// 也就是说空跑,只是打印,后文再详细讲述
"release": "node scripts/release.js --dry",
"preinstall": "node ./scripts/checkYarn.js",
}
}
если вы попытаетесь использоватьnpm
Если вы устанавливаете зависимости, вы должны получить сообщение об ошибке. Почему он сообщает об ошибке.
так какpackage.json
имеет префиксpreinstall
node ./scripts/checkYarn.js
Определить, является ли обязательным требованием использованиеyarn
Установить.
scripts/checkYarn.js
Файл выглядит следующим образом, то есть вprocess.env
Найдите путь выполнения в переменной окруженияnpm_execpath
,если неyarn
Предупреждение выводится, а процесс заканчивается.
// scripts/checkYarn.js
if (!/yarn\.js$/.test(process.env.npm_execpath || '')) {
console.warn(
'\u001b[33mThis repository requires Yarn 1.x for scripts to work properly.\u001b[39m\n'
)
process.exit(1)
}
Если вы хотите игнорировать это решение предварительного крючка, вы можете использоватьyarn --ignore-scripts
Заказ. Есть также задние крючкиpost
.Для получения более подробной информации ознакомьтесь с документацией по npm.
2.2 Отладка файла vue-next/scripts/release.js
Тогда давайте научимся отлаживатьvue-next/scripts/release.js
документ.
объявить мое здесьVSCode
версия1.59.0
должен1.50.0
Его можно отладить в соответствии со следующими шагами.
code -v
# 1.59.0
оказатьсяvue-next/package.json
открыть файл, затем вscripts
выше будетdebug
(отладка), после нажатия выберитеrelease
. для входа в режим отладки.
В это время терминал будет таким, как показано на рисунке ниже, сDebugger attached.
вывод. Выложите фото в это время.
После того, как вы научитесь отлаживать, сначала примерно пройдитесь по процессу, поставьте несколько точек останова в ключевых местах и пройдитесь еще несколько раз, и тогда вы сможете угадать цель исходного кода.
3 Некоторые описания зависимостей и объявления функций в начале файла
Мы можем следить за точками останова и смотреть на введение некоторых зависимостей и объявлений функций в начале файла.
3.1 Часть 1
// vue-next/scripts/release.js
const args = require('minimist')(process.argv.slice(2))
// 文件模块
const fs = require('fs')
// 路径
const path = require('path')
// 控制台
const chalk = require('chalk')
const semver = require('semver')
const currentVersion = require('../package.json').version
const { prompt } = require('enquirer')
// 执行子进程命令 简单说 就是在终端命令行执行 命令
const execa = require('execa')
Через зависимости мы можемnode_modules
Найдите зависимости соответствующей установки. также найти егоREADME
иgithub
склад.
3.1.1 Минимальный анализ параметров командной строки
Проще говоря, эта библиотека анализирует параметры командной строки. Глядя на пример, нам легче понять передачу параметров и результаты парсинга.
$ node example/parse.js -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }
$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
n: 5,
a: true,
b: true,
c: true,
beep: 'boop' }
const args = require('minimist')(process.argv.slice(2))
вprocess.argv
Первый и второй элементыNode
Полные пути файловой системы к исполняемым файлам и исполняемым файлам JavaScript, независимо от того, вводите ли вы их как таковые.
3.1.2 меловой терминал: многоцветный вывод.
Проще говоря, это используется для многоцветного вывода терминала.
3.1.3 Семантическое управление версиями semver
Семантическая версия реализации NodeJS, используемая для сравнения проверки версий и т. д. Вы можете увидеть это в симатической версии.Семантическое управление версиями 2.0.0 Документация
Формат версии: основной номер версии. дополнительный номер версии. номер редакции. Правила увеличения номера версии следующие:
Основной номер версии: когда вы вносите несовместимые изменения API,
Второстепенный номер версии: когда вы добавляете функции, совместимые с предыдущими версиями,
Номер редакции: когда вы вносите исправления для проблем обратной совместимости.
Предыдущий номер версии и информация о компиляции версии могут быть добавлены в конце «основной номер версии. дополнительный номер версии. номер редакции» в качестве расширения.
3.1.4 Опрашивающий в интерактивном режиме запрашивает CLI
Проще говоря, он интерактивно запрашивает у пользователя ввод.
3.1.5 команда выполнения execa
Проще говоря, он выполняет команды, аналогичные вводу команд в терминал самим, например,echo 若川
.
// 例子
const execa = require('execa');
(async () => {
const {stdout} = await execa('echo', ['unicorns']);
console.log(stdout);
//=> 'unicorns'
})();
Прочитав первую часть, переходим ко второй части.
3.2 Часть II
// vue-next/scripts/release.js
// 对应 yarn run release --preid=beta
// beta
const preId =
args.preid ||
(semver.prerelease(currentVersion) && semver.prerelease(currentVersion)[0])
// 对应 yarn run release --dry
// true
const isDryRun = args.dry
// 对应 yarn run release --skipTests
// true 跳过测试
const skipTests = args.skipTests
// 对应 yarn run release --skipBuild
// true
const skipBuild = args.skipBuild
// 读取 packages 文件夹,过滤掉 不是 .ts文件 结尾 并且不是 . 开头的文件夹
const packages = fs
.readdirSync(path.resolve(__dirname, '../packages'))
.filter(p => !p.endsWith('.ts') && !p.startsWith('.'))
Вторую часть относительно легко продолжить, чтобы увидеть третью часть.
3.3 Часть III
// vue-next/scripts/release.js
// 跳过的包
const skippedPackages = []
// 版本递增
const versionIncrements = [
'patch',
'minor',
'major',
...(preId ? ['prepatch', 'preminor', 'premajor', 'prerelease'] : [])
]
const inc = i => semver.inc(currentVersion, i, preId)
Эта часть может быть не совсем понята.inc
заключается в создании версии. Больше можно посмотретьдокументация
semver.inc('3.2.4', 'prerelease', 'beta')
// 3.2.5-beta.0
3.4 Часть 4
Четвертая часть объявляет некоторые функции сценария выполнения и т.д.
// vue-next/scripts/release.js
// 获取 bin 命令
const bin = name => path.resolve(__dirname, '../node_modules/.bin/' + name)
const run = (bin, args, opts = {}) =>
execa(bin, args, { stdio: 'inherit', ...opts })
const dryRun = (bin, args, opts = {}) =>
console.log(chalk.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts)
const runIfNotDry = isDryRun ? dryRun : run
// 获取包的路径
const getPkgRoot = pkg => path.resolve(__dirname, '../packages/' + pkg)
// 控制台输出
const step = msg => console.log(chalk.cyan(msg))
3.4.1 функция корзины
Получатьnode_modules/.bin/
Команда в каталоге, весь файл используется один раз.
bin('jest')
Эквивалентно запуску в командном терминале, корневой каталог проекта./node_modules/.bin/jest
Заказ.
3.4.2 запустить, высушитьВыполнить, запустить, если не высохнуть
const run = (bin, args, opts = {}) =>
execa(bin, args, { stdio: 'inherit', ...opts })
const dryRun = (bin, args, opts = {}) =>
console.log(chalk.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts)
const runIfNotDry = isDryRun ? dryRun : run
run
На самом деле запускайте команды в терминале, напримерyarn build --release
dryRun
не работает, простоconsole.log();
напечатать 'сборка пряжи --release'
runIfNotDry
Если это не пустой запуск, выполните команду. Параметр isDryRun вводится через консоль.yarn run release --dry
Вот и всеtrue
.runIfNotDry
Он просто печатает и не выполняет команды. Преимущество этого дизайна в том, что иногда вы не хотите отправлять напрямую, вы должны сначала посмотреть на результат выполнения команды. Должен сказать, Ю Да просто умеет играть.
существуетmain
Подобные советы также можно увидеть в конце функции. Можно использоватьgit diff
Сначала посмотрите на модификацию файла.
if (isDryRun) {
console.log(`\nDry run finished - run git diff to see package changes.`)
}
Прочитав некоторые введения в зависимости и объявления функций в начале файла, давайте посмотримmain
Основная функция входа.
4 основной основной процесс
Раздел 4, в основномmain
Функциональный анализ разборки.
4.1 Основная функция сортировки процессов
const chalk = require('chalk')
const step = msg => console.log(chalk.cyan(msg))
// 前面一堆依赖引入和函数定义等
async function main(){
// 版本校验
// run tests before release
step('\nRunning tests...')
// update all package versions and inter-dependencies
step('\nUpdating cross dependencies...')
// build all packages with types
step('\nBuilding all packages...')
// generate changelog
step('\nCommitting changes...')
// publish packages
step('\nPublishing packages...')
// push to GitHub
step('\nPushing to GitHub...')
}
main().catch(err => {
console.error(err)
})
вышеmain
В функции отсутствуют многие конкретные реализации функций. Далее разбираемmain
функция.
4.2 Подтвердите выпуск версии
Хотя первый код относительно длинный, его легко понять. Главное, подтвердить версию, которая будет выпущена.
При отладке давайте взглянем на два скриншота этого абзаца, там легко разобраться.
// 根据上文 mini 这句代码意思是 yarn run release 3.2.4
// 取到参数 3.2.4
let targetVersion = args._[0]
if (!targetVersion) {
// no explicit version, offer suggestions
const { release } = await prompt({
type: 'select',
name: 'release',
message: 'Select release type',
choices: versionIncrements.map(i => `${i} (${inc(i)})`).concat(['custom'])
})
// 选自定义
if (release === 'custom') {
targetVersion = (
await prompt({
type: 'input',
name: 'version',
message: 'Input custom version',
initial: currentVersion
})
).version
} else {
// 取到括号里的版本号
targetVersion = release.match(/\((.*)\)/)[1]
}
}
// 校验 版本是否符合 规范
if (!semver.valid(targetVersion)) {
throw new Error(`invalid target version: ${targetVersion}`)
}
// 确认要 release
const { yes } = await prompt({
type: 'confirm',
name: 'yes',
message: `Releasing v${targetVersion}. Confirm?`
})
// false 直接返回
if (!yes) {
return
}
4.3 Выполнение тестовых случаев
// run tests before release
step('\nRunning tests...')
if (!skipTests && !isDryRun) {
await run(bin('jest'), ['--clearCache'])
await run('yarn', ['test', '--bail'])
} else {
console.log(`(skipped)`)
}
4.4 Обновите номера версий всех пакетов и номера версий внутренних зависимостей, связанных с vue.
Эта часть предназначена для обновления корневого каталогаpackage.json
номер версии и всеpackages
номер версии.
// update all package versions and inter-dependencies
step('\nUpdating cross dependencies...')
updateVersions(targetVersion)
function updateVersions(version) {
// 1. update root package.json
updatePackage(path.resolve(__dirname, '..'), version)
// 2. update all packages
packages.forEach(p => updatePackage(getPkgRoot(p), version))
}
4.4.1 updatePackage Номер версии пакета обновления
function updatePackage(pkgRoot, version) {
const pkgPath = path.resolve(pkgRoot, 'package.json')
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
pkg.version = version
updateDeps(pkg, 'dependencies', version)
updateDeps(pkg, 'peerDependencies', version)
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
}
В основном это три модификации.
1. 自己本身 package.json 的版本号
2. packages.json 中 dependencies 中 vue 相关的依赖修改
3. packages.json 中 peerDependencies 中 vue 相关的依赖修改
Одна картинка стоит тысячи слов. мы выступаемyarn release --dry
Заднийgit diff
Просмотреноgit
Изменено, некоторые скриншоты выглядят следующим образом.
4.4.2 updateDeps обновляет номер версии внутренних зависимостей, связанных с vue.
function updateDeps(pkg, depType, version) {
const deps = pkg[depType]
if (!deps) return
Object.keys(deps).forEach(dep => {
if (
dep === 'vue' ||
(dep.startsWith('@vue') && packages.includes(dep.replace(/^@vue\//, '')))
) {
console.log(
chalk.yellow(`${pkg.name} -> ${depType} -> ${dep}@${version}`)
)
deps[dep] = version
}
})
}
Одна картинка стоит тысячи слов. Выполняем в терминалеyarn release --dry
. Вы увидите, что это выход.
Это вывод этого кода.
console.log(
chalk.yellow(`${pkg.name} -> ${depType} -> ${dep}@${version}`)
)
4.5 Упаковать и скомпилировать все пакеты
// build all packages with types
step('\nBuilding all packages...')
if (!skipBuild && !isDryRun) {
await run('yarn', ['build', '--release'])
// test generated dts files
step('\nVerifying type declarations...')
await run('yarn', ['test-dts-only'])
} else {
console.log(`(skipped)`)
}
4.6 Создать журнал изменений
// generate changelog
await run(`yarn`, ['changelog'])
yarn changelog
Соответствующий скрипт естьconventional-changelog -p angular -i CHANGELOG.md -s
.
4.7 Отправить код
После обновления номера версии есть изменения в файлах, поэтомуgit diff
.
Есть ли изменения в файлах и есть ли коммиты.
git add -A
git commit -m 'release: v${targetVersion}'
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.')
}
4.8 Релизный пакет
// publish packages
step('\nPublishing packages...')
for (const pkg of packages) {
await publishPackage(pkg, targetVersion, runIfNotDry)
}
Эта функция относительно длинная, поэтому внимательно ее рассматривать не нужно, проще говоря, этоyarn publish
пакет выпуска.
мыyarn release --dry
После этого вывод этой функции в терминал выглядит следующим образом:
Стоит упомянуть, что еслиvue
По умолчанию естьtag
заnext
. когдаVue 3.x
удаляется по умолчанию.
} else if (pkgName === 'vue') {
// TODO remove when 3.x becomes default
releaseTag = 'next'
}
Вот почему мы сейчас устанавливаемvue3
все ещеnpm i vue@next
Заказ.
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.
let releaseTag = null
if (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 default
releaseTag = 'next'
}
// TODO use inferred release channel after official 3.0 release
// const releaseTag = semver.prerelease(version)[0] || null
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
}
}
}
4.9 Отправить на гитхаб
// push to GitHub
step('\nPushing to GitHub...')
// 打 tag
await runIfNotDry('git', ['tag', `v${targetVersion}`])
// 推送 tag
await runIfNotDry('git', ['push', 'origin', `refs/tags/v${targetVersion}`])
// git push 所有改动到 远程 - github
await runIfNotDry('git', ['push'])
// yarn run release --dry
// 如果传了这个参数则输出 可以用 git diff 看看更改
// const isDryRun = args.dry
if (isDryRun) {
console.log(`\nDry run finished - run git diff to see package changes.`)
}
// 如果 跳过的包,则输出以下这些包没有发布。不过代码 `skippedPackages` 里是没有包。
// 所以这段代码也不会执行。
// 我们习惯写 arr.length !== 0 其实 0 就是 false 。可以不写。
if (skippedPackages.length) {
console.log(
chalk.yellow(
`The following packages are skipped and NOT published:\n- ${skippedPackages.join(
'\n- '
)}`
)
)
}
console.log()
мыyarn release --dry
После этого вывод этой функции в терминал выглядит следующим образом:
Здесь будем разбирать и анализироватьmain
функция.
Весь процесс понятен.
1. 确认要发布的版本
2. 执行测试用例
3. 更新所有包的版本号和内部 vue 相关依赖版本号
3.1 updatePackage 更新包的版本号
3.2 updateDeps 更新内部 vue 相关依赖的版本号
4. 打包编译所有包
5. 生成 changelog
6. 提交代码
7. 发布包
8. 推送到 github
Резюме с картинкой:
прочитай этоvue-next/scripts/release.js
, вы также можете посмотреть, если вы заинтересованыvue-next/scripts
Другие коды в папке имеют относительно мало строк, но преимущества относительно велики.
5. Резюме
Изучив эту статью, мы узнали об этом.
1. 熟悉 vuejs 发布流程
2. 学会调试 nodejs 代码
3. 动手优化公司项目发布流程
В то же время рекомендуется использовать его самостоятельноVSCode
Больше отладки, больше исполнения в терминале, больше понимания и переваривания.
vuejs
Мы можем напрямую копировать и вставлять множество кодов в опубликованные файлы, чтобы оптимизировать собственный процесс публикации. Например, при написании небольшой программы относительно вероятно, что она будет часто выпускаться, и вы можете использовать этот набор кода для взаимодействия сminiprogram-ci, а также некоторые настройки для оптимизации.
О мини-программахci
Загрузите и поделитесь еще двумя статьями.
Непрерывное построение апплета WeChat на основе CI
Инженерная практика автоматического построения и выпуска апплета малой перфокартыХотя статья не последняяminiprogram-ci
, но эта сцена написана более развернуто.
Конечно, выпуск версии также может использовать открытый исходный код.release-it.
При этом мы можем:
вводитьgit flow,управлятьgit
филиал. Я думаю, что многие люди не знаютwindows
git bash
уже поддерживается по умолчаниюgit flow
Заказ.
вводитьhuskyиlint-stagedОтправитьcommit
время использоватьESLint
Дождитесь отправки кода подтверждения для прохождения теста.
Внедрение модульных тестовjest, тестировать ключевые служебные функции и т. д.
вводитьconventional-changelog
вводитьgit-czинтерактивныйgit commit
.
И так далее, чтобы стандартизировать процесс вашего собственного проекта. Если кандидат, глядя наvuejs
Выпускают исходный код, активно оптимизируют собственные проекты. Думаю, интервьюер увидит в этом кандидате бонус.
Преимущество просмотра исходного кода проекта с открытым исходным кодом в том, что, с одной стороны, он может расширить кругозор, а с другой стороны, его можно использовать самому, и доход относительно высок.
Наконец, добро пожаловать, чтобы добавить меня на WeChatruochuan12общаться, участвоватьЧитайте исходный код вместеДействия, все вместе изучают исходный код и вместе добиваются прогресса.
о
Автор: Чанг ИВакагаваНазвание смешано в реках и озерах. По дороге на фронт | Энтузиасты РРТ | Знаю очень мало, только хорошо учусь.
Публичный аккаунт Wakagawa Vision, стремящийся помочь развитию фронтенда в течение 5 лет
Блог Вакагавы
segmentfault
Колонна Вакагава Видение, открылВидение ВакагаваКолонка, добро пожаловать на внимание~
Колонка самородков, добро пожаловать, обратите внимание~
Колонна видений Чжиху Руочуань, открылВидение ВакагаваКолонка, добро пожаловать на внимание~
github blog, спроситьstar
^_^~