- 前言:
- Node版本管理器:
- 规范包管理器使用:
- GitCommit规范:
- 组件级模板开发:
- 准备环境:
- 第一个组件模板:
- prompt.js脚本,负责收集用户的操作并汇总答案:
- index.hbs模板,负责构建组件的每一块:
- 文本渲染:
- 条件判断:
- Case Modifiers,快速转换变量命名风格:">可以使用Plopjs内置的Case Modifiers,快速转换变量命名风格:
- 示例模板:
- 写在最后
- 团队介绍
前言:
通过阅读本文你了解到这5大痛点如何避免和解决:
- 如何优雅且快速的切换Node版本?
- 如何统一项目中包管理器的使用?
- 如何养成规范GitCommit编写习惯?
- 如何不Copy快速开发相似的页面/组件?
-
Node版本管理器:
为什么要管理Node版本?
当我们开发的项目变得多起来的时候你就会发现每个项目所依赖的NodeJs环境的版本会相差很大,因为新项目的搭建我们肯定是会选择更加稳定的最新版本,那么当我们需要对历史项目进行维护的时候就免不了要切换到当时的NodeJs版本。
当我们想要尝鲜一些Bate版本的NodeJs所带来的新特性的时候就需要一个Bate版的NodeJs环境。
如何实现Node版本切换?
拒绝重复下载,重复安装;
推荐使用工具:nvm-windows,nvm。
实际案例分享:
在一次JavaScript脚本问题修复中发现原本正常使用的
fs.writeFile
函数抛出了类型异常导致数据无法正常输出到文件,在查询API后发现fs.writeFile(file, data[, options], callback)
函数的callback
参数在v7.0.0
中被标记为需要必选,在v10.0.0
中被要求强制必选。导致这次故障的原因就是在升级NodeJs版本的时候没有考虑到对历史项目影响,并在切换NodeJs版本到v10
以下后验证了这一问题。安装说明:
因为团队中使用win系统为大多数,这里还是主要来介绍win环境的安装;
- 安装前为了避免冲突,请先卸载已安装的NodeJs,并检查下面这几个目录;
- 需要清空:
%ProgramFiles%\nodejs
; - 需要清空:
%UserProfile%\.npmrc
; - 建议备份:
%AppData%\npm\etc\npmrc
至%UserProfile%\.npmrc
。
- 需要清空:
- 下载nvm-windows并按默认推荐安装,安装后重启终端通过
nvm version
查看版本验证安装结果; -
常用命令介绍:
查看已安装的NodeJs:
nvm list [available]
;- 安装指定版本的NodeJs:
nvm install <version> [arch]
; - 卸载已安装的NodeJs:
nvm uninstall <version>
; 切换NodeJs版本:
nvm use [version] [arch]
。更多请参考下图:
规范包管理器使用:
同样是在协作开发中发现的问题,因为使用了不同的包管理器,导致在本地开发环境一切正常的代码推送远程后在服务器构建中却意外的失败了,但在其他同事的电脑中再次尝试本地构建是可以复现问题的,这是为什么呢?我们在最后查看
node_module
中的内容时发现,由于使用的不同的包管理器导致文件拉取出现了差别最终导致的这个问题。这里我们通过一份预安装脚本来限制使用相同的包管理。预安装脚本工作原理介绍:
通过在install正式执行前通过在进程中获取可以区别当前使用的包管理器的特殊标识来决定是允许还是中断执行。
包管理器标识获取:
UserAgent方案,应用案例是which-pm-runs;
标识获取:
process.env.npm_config_user_agent
输出结果:
npm/6.14.5 node/v14.17.1 win32 x64
yarn/1.22.10 npm/? node/v14.17.1 win32 x64
```javascript // UserAgent方案的完整脚本
// 定义统一包管理器
const allowPM = ‘yarn’
const userAgent = process.env.npm_config_user_agent || ‘’
if (userAgent !== ‘’) {
const pmName = userAgent.substring(0, userAgent.indexOf(‘/‘))
if (pmName !== allowPM) {
console.warn(
\u001b[33m This repository requires using ${allowPM} as the package manager for scripts to work properly.\u001b[39m\n
)
process.exit(1)
}
}
2. ExecPath方案,应用案例是vue-next;
```json
标识获取:
process.env.npm_execpath
输出结果:
C:\...\nvm\v14.17.1\node_modules\npm\bin\npm-cli.js
C:\...\npm\node_modules\yarn\bin\yarn.js
const allowPM = 'yarn'
const execpath = process.env.npm_execpath || ''
if (!new RegExp(`${allowPM}`).test(execpath)) {
console.warn(
`\u001b[33m This repository requires using ${allowPM} as the package manager for scripts to work properly.\u001b[39m\n`
)
process.exit(1)
}
推荐方案only-allow:
only-allow为pnpm包管理器组织开源限制方案,only-allow内部使用which-pm-runs来获取当前执行的包管理器后再进行判断拦截,仅需在安装依赖后调整scripts中的内容即可,在vite项目中有使用。
- 添加命令:
npm set-script preinstall "npx only-allow yarn"
。- 命令执行需要npm版本在v7+;
- 安装仅此一步。
- 当使用了其他的包管理执行
install
命令将会被中断。
GitCommit规范:
遵守GitCommit的通用规范是每个优秀项目比不可少的环节,不同的项目需求中会衍生更多的依赖项需要配置,这里我们通过介绍husky7、commitizen/cz-cli、commitlint三大套件的基础使用来让你快速上手拦截住不规范的Commit信息。
三大件套介绍(husky7+commitizen+commitlint):
- husky7:在git执行的生命周期进行hook,替代git自带的hooks;
- commitizen/cz-cli:通过交互的方式生成规范的GitCommit信息;
- commitlint:检查GitCommit信息是否规范。
husky7使用指南:
准备工作:
- 安装依赖:
npm install husky --save-dev
; - 增加prepare命令:
npm set-script prepare "husky install"
;- 注意:
npm set-script xxx
在npm7+生效。
初始化husky:
npm run prepare
,生成.husky
默认文件夹。创建Hook:
创建Hook命令格式:
husky add <file> [cmd]
;创建Hook命令,在git commit前执行npm test:
添加暂存:
git add .husky/pre-commit
;- 执行提交:
git commit -m "Keep calm and commit"
。
卸载hook:
- 约定变更日志:conventional-changelog,同时会涉及standard-version、semantic-release、workflow等,非本次介绍;
-
初始化并使用生成Commit信息:
为项目初始化cz-conventional-changelog:
// 如需强制执行要增加参数--force npx commitizen init cz-conventional-changelog --save-dev --save-exact
添加执行脚本:
npm set-script cm "cz"
;- 不推荐使用commit做为key,可能存在冲突导致重复执行,详见文档;
npm set-script
执行需要npm7+。
- 执行
npm run cm
后将启动交互来生成提交信息,提交前请将待提交文件添加到暂存区。
使用husky7打通git commint和cz-cli :
- 创建./husky/prepare-commit-msg :
npx husky set .husky/prepare-commit-msg 'exec < /dev/tty && git cz --hook || true'
。
- 触发
git commit
后将进入交互命令。
更多请参考下图:
commitlint使用指南:
当我们习惯使用统一的规范后就会觉得CLI的方式很慢,这时候我们就可以取消到原有的pre-commit
中的拦截,改用只进行校验的方式来避免偶尔出现的不规范情况。
安装步骤:
安装必要依赖:
npm install --save-dev @commitlint/config-conventional @commitlint/cli
生成配置文件:
// 注意:如果文件内容编码非UTF-8请修改,在windows中可使用记事本重新另存为UTF-8格式。 echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
创建一个提交信息校验的hook:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
验证是否可以触发:
验证HEAD~1到HEAD提交是否规范(源文档命令执行会发生错误):
npx commitlint -- --from HEAD~1 --to HEAD --verbose
实际操作GitCommit:
组件级模板开发:
一些开源项目为了在被使用时可以轻松的上手或减少重复配置都会提供一份最基础的项目模板并配置相应的CLI工具进行拉取创建,在实际项目开发中我们也可以用类似的思想来帮助我们快速创建页面,组件,路由,控制器等。
准备环境:
- 安装开发依赖:
npm i plop --save-dev
; - 增加Scripts:
npm set-script new "plop"
; 推荐目录结构:
|-- project name |-- plopfile.js |-- plop-templates | |-- sfc3 | |-- index.hbs | |-- prompt.js
说明:我们在plop-templates定义的各个模板在导出后均要在plopfile.js集中注册生效。
第一个组件模板:
Vue的单文件组件将代码分割成template、script、style三块,其中template、style的编写风格相差不大。但是在script部分的编写Vue3就会有一些区别:
使用默认导出创建组件;
- 使用setup方言创建组件;
- 组件编写使用了defineComponent;
- 组件编写使用了reactive;
- 组件编写使用了Ts;
- 。。。
prompt.js脚本,负责收集用户的操作并汇总答案:
待收集的信息:
- Please enter a component name:
- Please check the required block:
- Please select a type:
- Set scoped ?
收集后处理:
const actions = { // 本次需要增加一个模板 type: "add", // 输出组件的目录 path: `src/components/${name}/index.vue`, // 生成组件的模板定义 templateFile: "plop-templates/sfc3/index.hbs", // 收集到得数据 data: { name, // 是否包含template template: blocks.includes("template"), // 是否包含style style: blocks.includes("template"), // 是否包含script script: blocks.includes("script"), default: type === "default", setup: type === "setup", reactive: type === "reactive", scoped: scoped, }, }
index.hbs模板,负责构建组件的每一块:
Handlebars是一个轻量的语义化模板,我们通过掌握一些简单的模板语法就可以正常使用,除非你要构建更加复杂的组件模板,那么你可以深入学习一下。
文本渲染:
条件判断:
条件判断助手代码块开始为{{#if xxx}}
,结束为{{/if}}
,当template为true时渲染中间的内容。
{{#if template}}
<template>
<div>
</div>
</template>
{{/if}}
可以使用Plopjs内置的Case Modifiers,快速转换变量命名风格:
- camelCase: changeFormatToThis
- snakeCase: change_format_to_this
- dashCase/kebabCase: change-format-to-this
- dotCase: change.format.to.this
- pathCase: change/format/to/this
- properCase/pascalCase: ChangeFormatToThis
- lowerCase: change format to this
- sentenceCase: Change format to this,
- constantCase: CHANGE_FORMAT_TO_THIS
titleCase: Change Format To This
示例模板:
``` {{#if template}}
{{#if script}}
{{/if}}
{{#if style}}