网站建设综合案例,做ui什么图库网站好呀,免费制作网站的步骤 怎样做网站,传奇网站架设方法Monorepo pnpm 模式管理多个 web 项目 Monorepo pnpm 模式管理多个 web 项目项目地址git flow 工作流程pnpm workspace.npmrc初始化项目架构引入Husky规范git提交配置eslint和prettiereslint 配置prettier 配置 配置lint-staged创建项目创建shared项目全局安装 vue在 packages … Monorepo pnpm 模式管理多个 web 项目 Monorepo pnpm 模式管理多个 web 项目项目地址git flow 工作流程pnpm workspace.npmrc初始化项目架构引入Husky规范git提交配置eslint和prettiereslint 配置prettier 配置 配置lint-staged创建项目创建shared项目全局安装 vue在 packages 项目下创建 vue 项目 配置全局指令引用 shared 内容建立关联打包插件 配置单命令启动多项目 Monorepo pnpm 模式管理多个 web 项目
项目地址
Vue: Monorepo pnpm 模式管理多个 web 项目Vue3)Nuxt:Monorepo pnpm 模式管理多个 web 项目Nuxt)
git flow 工作流程 参考链接[https://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html] 新建功能 新建feature分支 git checkout -b feature/MYFEATURE
git flow feature start MYFEATURE完成新功能开发将feature分支合并到develop分支现在已写成文件直接执行命令 yarn feature即可 git flow feature finish MYFEATURE基于最新的develop分支切出release分支此版本为预发布版本分支为版本号 git checkout -b release/1.0.0
git flow release start release/1.0.0测试无问题 执行git flow release finish 1.0.0 输出提交日志合并到develop分支和mian/master分支输入版本信息 # -m tag提交信息
# 参数参考https://github.com/nvie/gitflow/wiki/Command-Line-Arguments#hotfix
git flow release finish 1.0.0 -m 在develop分支并推送develop分支到远程 git push origin develop切换到main/master 分支, 推送到远程推送最新的tag到远程 git push origin main
git push origin v1.0.0bug修改 新增一个hotfix分支 git checkout -b hotfix/1.0.1
git flow hotfix start 1.0.1修改完成后的操作与release一样
pnpm workspace
创建 pnpm-workspace.yaml 文件 touch pnpm-workspace.yamlpnpm-workspace.yaml
packages:- packages/* # 代表所有项目都放在packages文件夹之下.npmrc
# 注释三方依赖也有依赖要是项目中使用了第三方的依赖
# 要是哪天第三方卸载不在该包了那就找不到了称之为“幽灵依赖”
# 所以需要“羞耻提升”暴露到外层中即在根目录下的node_modules内而非在.pnpm文件夹中。shamefully-hoist true# 根目录下的node_modules里vue安装到了与.pnpm同层级位置当中了
# 这就是shamefully-hoist true的效果把vue从.pnpm内提到node_modules中
# 并且vue的相关依赖也拍平到了该层级文件夹中。初始化项目架构
Conventional Changelog 生态探索: https://zhuanlan.zhihu.com/p/392303778
# 初始化package.json
pnpm init
# 初始化项目
pnpm run init
# git flow init 前需要 执行 git init
# 每修改一次filter-flow-hotfix-finish-tag-message.sh,filter-flow-release-finish-tag-message.sh 需要重新initpackage.json
{script: {init: sh ./scripts/shell/init.sh --all}
}init.sh
# 项目初始化# 初始化项目配置
SCRIPTPATH$(pwd -P)# 初始化git设置
git config core.filemode false
git config tag.sort version:refname
git config pull.rebase trueif [ $1 ]; then# 安装 editorconfig 扩展command -v code code --install-extension editorconfig.editorconfig || echo Make sure your IDEs support for \EditorConfig\. You can check by https://editorconfig.org/# 设置git filter-flow-hotfix-finish-tag-message hook 软连接rm -f ./.git/hooks/filter-flow-hotfix-finish-tag-messagechmod x $SCRIPTPATH/scripts/shell/filter-flow-hotfix-finish-tag-message.shln -s $SCRIPTPATH/scripts/shell/filter-flow-hotfix-finish-tag-message.sh ./.git/hooks/filter-flow-hotfix-finish-tag-message# 设置git filter-flow-release-finish-tag-message hook 软连接rm -f ./.git/hooks/filter-flow-release-finish-tag-messagechmod x $SCRIPTPATH/scripts/shell/filter-flow-release-finish-tag-message.shln -s $SCRIPTPATH/scripts/shell/filter-flow-release-finish-tag-message.sh ./.git/hooks/filter-flow-release-finish-tag-message# 初始化git-flow设置git config gitflow.branch.master mastergit config gitflow.branch.develop developgit config gitflow.prefix.versiontag vgit config gitflow.path.hooks $SCRIPTPATH/.git/hooksgit flow init
fiif [ $? -eq 0 ]; thenecho init finish
elseecho init failed
fi filter-flow-hotfix-finish-tag-message.sh,filter-flow-release-finish-tag-message.sh git flow 工作流钩子用于releasehotfix 打版自定义两个命令增加中途写入CHANGELOG的功能执行git flow release finish 和 git flow hotfix finish 工作流时会执行hooks中的filter-flow-hotfix-finish-tag-message.sh,filter-flow-release-finish-tag-message.sh具体参考https://github.com/jaspernbrouwer/git-flow-hooks/blob/master/filter-flow-hotfix-finish-tag-message filter-flow-hotfix-finish-tag-message.sh, filter-flow-release-finish-tag-message.sh 为保证CHANGELOG正常写入release的命名格式为xxx-tagnametagname和提交时的scope保持一致
#!/usr/bin/env bash# Runs during git flow release finish and a tag message is given
#
# Positional arguments:
# $1 Message
# $2 Full version
#
# Return MESSAGE
#
# The following variables are available as they are exported by git-flow:
#
# MASTER_BRANCH - The branch defined as Master
# DEVELOP_BRANCH - The branch defined as DevelopMESSAGE$1
VERSION$2
# 同步远程tag防止本地打版写入多个版本changelog-needed
git fetch --tagsBEHIND_COMMIT$(git rev-list --count ..origin/develop)
ROOT_DIR$PWD
# 根据tag来截取需要写入日志的package
PACKAGE${VERSION#*-}
# 获取需要写入日志的package最近的一个tag
PREVIOUSTAG$(git tag -l | grep $PACKAGE | tail -n 1)
# 获取semver格式的版本号
PACKAGE_VERSION${VERSION%%-*}# 获取两个tag之间的changelog信息
CHANGELOG_MESSAGEpnpm cross-env PACKAGE$PACKAGE PREVIOUS_TAG$PREVIOUSTAG CURRENT_TAG$VERSION conventional-changelog -p custom-config -i -n ./scripts/changelog/changelog-option.cjs | tail -n 4 | sed $d | sed s/(changelog-needed)/ /g# 判断是否需要rebase落后于target branch合并会失败
[ $BEHIND_COMMIT -ne 0 ] { echo Please rebase develop before finishing this branch; exit 1; }isMono$(echo $VERSION | grep mono)# 判断是否为mono的更新是的话changelog会更新到changelogs目录的mono.md内
if [[ $isMono ! ]]; then# 更新版本号pnpm version --new-version ${PACKAGE_VERSION/v/} --no-git-tag-version /dev/nullTEMP_CHANGELOG_MESSAGE$(echo ### $PACKAGE_VERSION;git log -1 --pretty#### %ci;printf \n;echo ${CHANGELOG_MESSAGE};printf \n---\n\n;cat ./changelogs/mono.md)echo $TEMP_CHANGELOG_MESSAGE ./changelogs/mono.md
# 否则更新到changelogs目录对应package的package.md内
elseTEMP_CHANGELOG_MESSAGE$(echo ### $PACKAGE_VERSION;git log -1 --pretty#### %ci;printf \n;echo ${CHANGELOG_MESSAGE};printf \n---\n\n;cat ./changelogs/$PACKAGE.md)echo $TEMP_CHANGELOG_MESSAGE ./changelogs/$PACKAGE.md
fi
git add . /dev/null
git commit --amend --no-edit --no-verify /dev/nullecho $MESSAGEexit 0配置commit规范以及自动生成CHNAGELOG并自定义需要的依赖包
# conventional-changelog-cli 要配合conventional-changelog-custom-config使用指定版本为^2
# conventional-changelog-custom-config参考https://itxiaohao.github.io/passages/git-commit/#%E6%B7%B1%E5%85%A5-conventional-changelog-%E6%BA%90%E7%A0%81
# lerna 要配合 cz-lerna-changelog 使用指定版本为^3.22.1
# cz-lerna-changelog参考https://www.npmjs.com/package/cz-lerna-changelog# -w 有工作区的时候使用
pnpm add commitlint/cli commitlint/config-conventional commitizen conventional-changelog-cli^2.2.2 conventional-changelog-custom-config cz-lerna-changelog lerna^3.22.1 -D -wpnpm add cross-env -w添加comitizen相应配置创建commitlint.config.js
touch commitlint.config.jsconst fs require(fs)
const path require(path)module.exports {extends: [monorepo],rules: {header-max-length: [0, always],// scope 不允许为空保证CHANGELOG正常写入release的命名格式为xxx-tagnametagname和scope保持一致scope-empty: [2, never],scope-enum: [2, always, [...fs.readdirSync(path.join(__dirname, packages)), mono]],type-enum: [2, always, [build, ci, chore, feat, fix, refactor, style, test, config, docs]],close-issue-needed: [2, always],},plugins: [{rules: {close-issue-needed: (msg) {const ISSUES_CLOSED ISSUES CLOSED:return [msg.raw.includes(ISSUES_CLOSED), Your commit message must contain ISSUES message]},},},],
}自定定义CHANGELOG配置 changelog-option.cjs
const path require(path)
const compareFunc require(compare-func)// 自定义配置
let pkgJson {}
try {pkgJson require(path.join(__dirname, ../../package.json))
} catch (err) {console.error(no root package.json found)
}const { changelog } pkgJson
let bugsUrl changelog ? changelog.bugsUrl || false : false
if (typeof bugsUrl ! string) bugsUrl false
const authorName changelog ? changelog.authorName || false : false
const authorEmail changelog ? changelog.authorEmail || false : falselet gitUserInfo
if (authorName authorEmail) {gitUserInfo by: **{{authorName}}** ({{authorEmail}})
}
if (authorName authorEmail false) {gitUserInfo by: **{{authorName}}**
}
if (authorName false authorEmail) {gitUserInfo by: ({{authorEmail}})
}const getWriterOpts () {return {transform: (commit, context) {let discard trueconst issues []commit.notes.forEach((note) {note.title BREAKING CHANGESdiscard false})if (commit.type feat) {commit.type Features} else if (commit.type fix) {commit.type Bug Fixes} else if (commit.type perf) {commit.type Performance Improvements} else if (commit.type revert) {commit.type Reverts} else if (commit.type docs) {commit.type Documentation} else if (commit.type style) {commit.type Styles} else if (commit.type refactor) {commit.type Code Refactoring} else if (commit.type test) {commit.type Tests} else if (commit.type build) {commit.type Build System} else if (commit.type ci) {commit.type Continuous Integration} else if (commit.type chore) {commit.type Chores} else if (discard) {return}if (commit.scope *) {commit.scope }if (typeof commit.hash string) {commit.hash commit.hash.substring(0, 7)}if (typeof commit.subject string) {let url context.repository ? ${context.host}/${context.owner}/${context.repository} : context.repoUrlif (url) {url ${url}/issues/// Issue URLs.commit.subject commit.subject.replace(/#([0-9])/g, (_, issue) {issues.push(issue)return [#${issue}](${url}${issue})})}if (context.host) {// User URLs.commit.subject commit.subject.replace(/\B([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) {if (username.includes(/)) {return ${username}}return [${username}](${context.host}/${username})})}}// remove references that already appear in the subjectcommit.references commit.references.filter((reference) {if (!issues.includes(reference.issue)) {return true}return false})if (bugsUrl) {commit.references commit.references.map((ref) {return {...ref,bugsUrl,}})}const needChangelog commit.header.includes((changelog-needed)) commit.header.includes((${process.env.PACKAGE}):)// 可在此过滤所需要的commit信息if (needChangelog) {commit.header commit.header.replace(/\(changelog-needed\)/g, )}return needChangelog ? commit : null},groupBy: type,commitGroupsSort: title,commitsSort: [scope, subject],noteGroupsSort: title,notesSort: compareFunc,finalizeContext: (context) {return Object.assign(context, {version: process.env.CURRENT_TAG,linkCompare: false,})},}
}module.exports {gitRawCommitsOpts: {from: process.env.PREVIOUS_TAG,to: process.env.CURRENT_TAG,},writerOpts: getWriterOpts(),
}{repository: {type: git,url: https://github.com/example.git},changelog: {bugsUrl: https://github.com/,authorName: true,authorEmail: false}
}配置 cz-lerna-changlog,支持选择packages
const czLernaChangelog require(cz-lerna-changelog)function makePrompter() {return function (cz, commit) {cz.prompt([{type: confirm,name: addChangeLog,message: Auto add (changelog-needed) to subject line?\n,},]).then((answer) {let customQuestion [{type: input,name: subject,message: Write a short, imperative tense description of the change:\n,filter: function (value) {const mark (answer.addChangeLog (changelog-needed)) || return value.charAt(0).toLowerCase() value.slice(1) mark},validate: function (value) {return !!value},},]return czLernaChangelog.makePrompter(() customQuestion)(cz, commit)})}
}module.exports {prompter: makePrompter(),makePrompter: makePrompter,
}{config: {commitizen: {path: ./scripts/changelog/cz-lerna-changelog.cjs}},workspaces: [packages/*]
}引入Husky规范git提交
安装 husky
pnpm add husky -D -w在 package.json 中 scripts 中设置 prepare 钩子:husky install,在使用pnpm install的时候就会自动执行husky,以便于别人拉取完我们代码进行pnpm insall的时候直接进行husky install版本8操作版本9直接执行 init
pnpm pkg set scripts.preparehusky install或者
{scripts: {prepare: husky install}
}执行install 生成.husky文件夹
# 版本 8
npx husky install#版本9
npx husky init添加一个 commit 钩子文件
# 版本8
npx husky add .husky/pre-commit
# 版本8 .husky/commit-msg 中添加npx --no -- commitlint --edit $1
npx --no -- commitlint --edit $1
# 版本9
echo npx --no -- commitlint --edit $1 .husky/commit-msg
# .husky/pre-commit中写入以下命令配合eslint使用
pnpm run lint-staged配置eslint和prettier
eslint 配置
安装依赖包
# eslint eslint依赖包
# eslint-config-standard JavaScript标准样式的ESLint可配置基础配置,比较流行的有 airbnb、standard、prettier等
# eslint-plugin-import 支持ES6以上的导入/导出语法并防止文件路径和导入名称拼写错误的问题
# eslint-plugin-node 为node准备的eslint规则配置
# eslint-plugin-promise es语法promise的eslint最佳配置
# eslint-plugin-vue vue项目的的配置vue项目必须
# typescript-eslint/parser 解析器
# typescript-eslint/eslint-plugin ts语法的配置
# eslint-define-config eslint-define-config可以帮助我们做语法提示
pnpm add eslint eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-vue typescript-eslint/parser typescript-eslint/eslint-plugin eslint-define-config -D -w根目录下创建.eslintrc.cjs、.eslintignore文件
// .eslinttrc.cjs
// eslint-define-config可以帮助我们做语法提示
const { defineConfig } require(eslint-define-config)module.exports defineConfig({// ESLint 一旦发现配置文件中有 root: true它就会停止在父级目录中寻找。root: true,// 解析器parser: vue-eslint-parser,parserOptions: {// 解析器parser: typescript-eslint/parser,// js的版本ecmaVersion: 2020,// 模块化方案sourceType: module,ecmaFeatures: {jsx: true,},},// 启用的规则extends: [plugin:vue/vue3-recommended, plugin:typescript-eslint/recommended, standard],rules: {quotes: [error, single],typescript-eslint/ban-ts-ignore: off,typescript-eslint/explicit-function-return-type: off,typescript-eslint/no-explicit-any: off,typescript-eslint/no-var-requires: off,typescript-eslint/no-empty-function: off,typescript-eslint/no-use-before-define: off,typescript-eslint/ban-ts-comment: off,typescript-eslint/ban-types: off,typescript-eslint/no-non-null-assertion: off,typescript-eslint/explicit-module-boundary-types: off,typescript-eslint/no-unused-vars: [error,{argsIgnorePattern: ^h$,varsIgnorePattern: ^h$,},],no-use-before-define: off,no-unused-vars: [error,{argsIgnorePattern: ^h$,varsIgnorePattern: ^h$,},],no-tabs: off,indent: off,vue/custom-event-name-casing: off,vue/html-indent: off,vue/max-attributes-per-line: off,vue/html-self-closing: off,vue/singleline-html-element-content-newline: off,vue/multi-word-component-names: off,space-before-function-paren: off,comma-dangle: off,},
}).eslintignore
node_modules
.vscode
.idea
dist
.eslintrc.cjsprettier 配置
安装依赖
# eslint-config-prettiereslint-plugin-prettier 用于解决eslint和prettier的冲突问题
pnpm add prettier eslint-config-prettier eslint-plugin-prettier -D -w根目录创建.prettierrc文件
{printWidth: 150,tabWidth: 2,useTabs: true,semi: false,singleQuote: true,quoteProps: as-needed,jsxSingleQuote: false,trailingComma: es5,bracketSpacing: true,jsxBracketSameLine: false,arrowParens: always,rangeStart: 0,requirePragma: false,insertPragma: false,proseWrap: preserve,htmlWhitespaceSensitivity: css,vueIndentScriptAndStyle: false,endOfLine: auto
}根目录创建.prettierignore文件用于忽略prewitter格式化 安装 VSCode 插件 Prettier - Code formatter 安装该插件以实现在保存的时候自动完成格式化 在 .vscode/settings.json 中添加一下规则
{// 保存的时候自动格式化editor.formatOnSave: true,// 默认格式化工具选择prettiereditor.defaultFormatter: esbenp.prettier-vscode
}配置lint-staged
提交前在pre-commit中应该做一次lint 校验在package.json添加
{scripts: {lint:script: eslint --ext .js,.jsx,.vue,.ts,.tsx --fix --quiet ./}
}在pre-commit 中添加命令 npm lint:script 根据上面的配置是可以实现我们想要的效果的,但是我们会发现每次提交代码的时候 ESlint 或 Stylelint 都会检查所有文件,而我们需要的是只让它们检测新增的文件,因此我们可以使用lint-staged来解决这个问题 安装lint-staged
pnpm add lint-staged -D -w在package.json中添加配置,更改pre-commit的命令 pnpm run lint-staged
{lint-staged: {src/**/*.{js,jsx,ts,tsx,vue}: [eslint --ext .js,.jsx,.vue,.ts,.tsx --fix --quiet ./]},scripts: {lint-staged: lint-staged}
}创建项目
创建shared
shared项目用来服务其他多个web项目提供公共方法、组件、样式等等
项目全局安装 vue # -w的意思是workspace-root把依赖包安装到工作目录的根路径下# 则根目录下会生成node_modules文件夹。可以共用后续每个项目需要用到vue的# 都直接从根目录node_modules里取。pnpm add vue -w在 packages 项目下创建 vue 项目
执行创建命令根据提示选择 pnpm create vite删除 vue vitejs/plugin-vue vite vue-tsc typescript 等依赖安装到全局中 # 子项目下执行pnpm remove vuepnpm remove vitejs/plugin-vue vite vue-tsc typescript -D# 根目录下执行pnpm add vitejs/plugin-vue vite vue-tsc typescript -D -w运行项目 # 子项目下运行pnpm dev配置全局指令
{script: {dev:project: cd packages/vite-project pnpm dev// pnpm -C packages/vue-config-1 pnpm dev 亦可}
}引用 shared 内容
加入 tsconfig.json 来配置路径
# 根目录下
pnpm add typescript -D -w
pnpm tsc --init配置
{compilerOptions: {outDir: dist, // 输出的目录sourceMap: true, //采用sourcemaptarget: es2016, // 目标语法module: esnext, // 模块格式moduleResolution: node, // 模块解析strict: false, // 严格模式resolveJsonModule: true, // 解析json模块esModuleInterop: true, // 允许通过es6语法引入commonjs模块jsx: preserve, // jsx不转义lib: [esnext, dom], // 支持的类库esnext及dombaseUrl: ., // 当前是以该路径进行查找paths: {monorepo/shared/components: [packages/shared/components],monorepo/shared/utils: [packages/shared/utils],monorepo/shared/fetch: [packages/shared/fetch],monorepo/shared/styles: [packages/shared/styles],// 或者用*号处理匹配monorepo/shared/*: [packages/shared/*]}}
}建立关联
# 指定版本号
pnpm add monorepo/sharedworkspace --filter monorepo/vite-project
打包插件
安装 minimist esbuild
pnpm add minimist esbuild -D -w新增 打包脚本
// minimist 可以解析命令行参数非常好用功能简单
import minimist from minimist
// 打包模块
import { build } from esbuild
// node 中的内置模块
import path from path
import fs from fs
const __dirname path.resolve()
const args minimist(process.argv.slice(2))
const target args._[0]
const format args.f || global
const entry path.resolve(__dirname, ./packages/plugins/${target}/src/index.ts)
/* iife 立即执行函数(function(){})()cjs node中的模块 module.exportsesm 浏览器中的esModule模块 import */
const outputFormat format.startsWith(global) ? iife : format cjs ? cjs : esm
const outfile path.resolve(__dirname, ./packages/plugins/${target}/dist/${target}.${format}.js)
const pkaPath path.resolve(__dirname, ./packages/plugins/${target}/package.json)
const pkaOps JSON.parse(fs.readFileSync(pkaPath, utf8))
const packageName pkaOps.buildOptions?.name
build({entryPoints: [entry],outfile,bundle: true,sourcemap: true,format: outputFormat,globalName: packageName,platform: format cjs ? node : browser,
}).then(() {console.log(watching~~~)
})配置 plugins package.json
{name: monorepo/common,version: 1.0.0,description: ,main: index.js,scripts: {test: echo \Error: no test specified\ exit 1},// 打包会用到, 用于定义全局变量buildOptions: {name: common},keywords: [],author: ,license: ISC,dependencies: {monorepo/shared: workspace:^}
}配置并执行打包命令
{scripts: {dev:common: node scripts/dev-plugins.js common -f global}
}pnpm dev:common测试使用
!doctype html
html langenheadmeta charsetUTF-8 /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/title/headbodyscript src./common.global.js/scriptscriptconst { testFunc } commonconsole.log(testFunc())/script/body
/html配置单命令启动多项目
{scripts: {serve: node ./scripts/build/build.cjs,build: node ./scripts/build/build.cjs --production}
}build.cjs
const { spawn } require(child_process)
const core require(./core.cjs)
const path require(path)class BuildCore extends core {constructor(optionArray []) {super()this.initOption(optionArray)this.start()}/*** description 执行构建流程*/start() {this.getPackages().then(async () {this._argument this._program.parse(process.argv).argstry {const answer await this.selectPackage()answer this._argument.unshift(answer)this.initBuildSpawn()} catch (error) {console.error(the application must be selected!)}})}/*** description 初始化本地开发或者构建build过程*/initBuildSpawn() {if (!this.validatePackage()) return falseconst isProduction this._program.parse(process.argv).productionprocess.env.PACKAGE this._argument[0]process.env.NODE_ENV isProduction ? production : developmentconst args isProduction ? [build] : [dev]const clinetPath path.resolve(__dirname, ../../packages/${process.env.PACKAGE}/)try {const clientSpawnInstance spawn(pnpm, [-C, clinetPath, args], {stdio: inherit,shell: true, // 兼容部分win10系统Error: spawn yarn ENOENT报错})this.registErrorHandle(clientSpawnInstance)} catch (error) {console.log(error)}}
}new BuildCore([{short: -p,long: --production,description: build package in production mode,},
])core.js
/*** 操作终端面板选择项目启动* 思路读取packages下的文件获取每个项目的名称存到项目数组中this._packageArray getPackages* 根据项目数组构建命令行选择器选择对应的项目 selectPackage*/const process require(process)
const fs require(fs)
const path require(path)
const { Command } require(commander)
const { Select } require(enquirer)class Core {constructor() {// 项目数组this._packageArray []// 命令实例this._program new Command()}/*** description 选择应用* return Promise*/selectPackage() {// 深拷贝应用数组const packages JSON.parse(JSON.stringify(this._packageArray))// 判断选择的包是否包含在应用数组中包含则返回Promise成功状态if (this._argument packages.includes(this._argument[0])) return Promise.resolve()// 终端命令行选择const prompt new Select({name: apps,message: Please select the application to run,choices: packages,})return prompt.run()}/*** description 初始化自定义command参数* param {Object[]} optionArray 自定义参数数组* param {String} optionArray[].short 自定义参数缩写如 -p* param {String} optionArray[].long 自定义参数全称 如 --production* param {String} optionArray[].description 自定义参数作用的描述*/initOption(optionArray) {optionArray.forEach((obj) {this._program.option(${obj.short}, ${obj.long}, obj.description)})}/*** description 检测自定义的package参数是否匹配packages目录下的项目*/validatePackage() {let pass trueif (!this._packageArray.includes(this._argument[0])) {console.error(package param should be one of [${this._packageArray.join(,)}])console.log(eg: yarn script auth-overseas)pass false}return pass}/*** description 获取packages目录下的项目*/getPackages() {return new Promise((resolve, reject) {// 读取packages下的文件fs.readdir(path.join(__dirname, ../../packages), { withFileTypes: true }, (err, dir) {if (err) reject(err)// 将目录的文件名筛选读取添加到应用数组中this._packageArray dir.filter((i) {const typeKey Object.getOwnPropertySymbols(i)[0]return i.name ! plugins i.name ! shared i[typeKey] 2}).map((j) j.name)resolve()})})}/*** description 注册对子进程错误进行异常处理* param {Object} spawnInstance 子进程* param {Function} callback 子进程执行完成后回调* param {Function} errorCallback 子进程执行报错后回调*/registErrorHandle(spawnInstance, callback, errorCallback) {spawnInstance.on(error, (err) {console.log(err)errorCallback errorCallback(err)process.exit(1)})spawnInstance.on(exit, (code) {callback callback()// code 0表示流程正常if (code ! 0) {process.exit(1)}})}
}module.exports Core