序文:
この記事を読むことで、これらの5つの主要な問題点を回避して解決する方法を知ることができます。
- ノードのバージョンを適切かつ迅速に切り替える方法は?
- プロジェクトでパッケージマネージャーの使用を統合するにはどうすればよいですか?
- 標準的なGitCommitの書き方の習慣を身につけるには?
- コピーせずに同様のページ/コンポーネントをすばやく開発するにはどうすればよいですか?
- 同僚がもっと読みたくなるようにCSSを書く方法は?
ノードバージョンマネージャー:
なぜノードのバージョンを管理するのですか?
- より多くのプロジェクトを開発すると、各プロジェクトが依存するNodeJs環境のバージョンが大きく異なることがわかります。これは、新しいプロジェクトを構築するときに、より安定した最新バージョンを確実に選択するためです。プロジェクトでは、NodeJの現在のバージョンに切り替えることは避けられません。
- NodeJのBateバージョンによってもたらされるいくつかの新機能を試してみたい場合は、NodeJ環境のBateバージョンが必要です。
ノードバージョンの切り替えを実装するにはどうすればよいですか?
- 繰り返しダウンロードしてインストールすることを拒否します。
- 推奨ツール:nvm-windows、nvm。
実用的なケース共有:
JavaScriptスクリプトの問題修復で、通常使用されている関数がfs.writeFile
型例外をスローし、データがファイルに正常に出力されないことが判明しました。APIをクエリした後、fs.writeFile(file, data[, options], callback)
関数のcallback
パラメーターv7.0.0
がマークされていることがわかりました。で必要とされるようにv10.0.0
、そしてで必須である必要がありました。この失敗の理由は、NodeJのバージョンをアップグレードするときに履歴プロジェクトへの影響が考慮されておらずv10
、NodeJのバージョンを次のバージョンに切り替えた後に問題が確認されたためです。
インストールノート:
- ほとんどのチームがwinシステムを使用しているため、ここではwin環境のインストールの主な概要を説明します。
- インストール前の競合を回避するために、インストールされたNodeJをアンインストールし、次のディレクトリを確認してください。
- クリアする必要があります:
%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
复制代码
// 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)
}
}
复制代码
- ExecPath方案,应用案例是vue-next;
标识获取:
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:
- 修改test命令:输出
hello world
文本到output.txt
文件。 npx husky add .husky/pre-commit "npm test"
;- 注意:如果执行后仅看到的是帮助提示,可以使用已安装到本地的husky来运行(
.\node_modules\.bin\husky
),这个问题已在npm8中得到了修复。
- 修改test命令:输出
验证hook:
- 添加暂存:
git add .husky/pre-commit
; - 执行提交:
git commit -m "Keep calm and commit"
。
卸载hook:
- 卸载依赖:
npm uninstall husky
; - 解除Git配置:
git config --unset core.hooksPath
。
更多请参考下图:
commitizen/cz-cli使用指南:
- 约定变更日志:conventional-changelog,同时会涉及standard-version、semantic-release、workflow等,非本次介绍;
- 前提约定:确保npm版本在5.2及以上。
初始化并使用生成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是一个轻量的语义化模板,我们通过掌握一些简单的模板语法就可以正常使用,除非你要构建更加复杂的组件模板,那么你可以深入学习一下。
文本渲染:
使用{{ xxx }}
的形式直接渲染。
条件判断:
条件判断助手代码块开始为{{#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}}
<template>
<div>
</div>
</template>
{{/if}}
{{#if script}}
<script>
export default {
setup () {
return {}
}
}
</script>
{{/if}}
{{#if style}}
<style{{#if scoped}} scoped{{/if}}>
</style>
{{/if}}
复制代码
CSS属性排序:
在大多数时候我们都特别在乎JavaScript代码的规范,安装了各式各样的校验工具,同样在CSS里面也应该有一份类似的规范来对编写做一定的限制,这样可以避免重复定义的样式被覆盖的情况,也体现了在编写样式时的思路,同样也提高的CSS的阅读性和维护性。
CSScomb for VSCode:
CSScomb是一款专注于CSS、Less、SCSS或Sass的编码样式格式化程序。
自定义配置:
- CSS排序顺序:布局 → 尺寸 → 界面 → 文字 → 交互;
- カスタム構成ファイル:VSCode→設定→ワークスペース→右上隅にある設定(json)を開きます。
// .vscode/settings.json
{
"csscomb.formatOnSave": true, // 保存代码时自动格式化
"csscomb.preset": {
"always-semicolon": true, // 分号结尾
"block-indent": "\t", // 换行格式
"color-case": "lower", // 颜色格式
"color-shorthand": true, // 颜色缩写
"element-case": "lower", // 元素格式
// "eof-newline": false, // 结尾空行
"leading-zero": false, // 保留前导零位
// "lines-between-rulesets": 0, // 规则间隔行数
"quotes": "double", // 引号格式
"remove-empty-rulesets": true, // 剔除空规则
"space-between-declarations": "\n", // 属性换行
"space-before-closing-brace": "\n", // 后花括号前插入
"space-after-colon": " ", // 冒号后插入
"space-before-colon": "", // 冒号前插入
"space-after-combinator": " ", // 大于号后插入
"space-before-combinator": " ", // 大于号前插入
"space-after-opening-brace": "\n", // 前花括号后插入
"space-before-opening-brace": " ", // 前花括号前插入
"space-after-selector-delimiter": "\n", // 逗号后插入
"space-before-selector-delimiter": "", // 逗号前插入
"strip-spaces": true, // 剔除空格
"tab-size": true, // 缩进大小
"unitless-zero": true, // 剔除零单位
"vendor-prefix-align": false, // 前缀缩进
"sort-order": [
// 布局属性
"display", "visibility", "overflow", "overflow-x", "overflow-y",
// 布局属性:浮动
"float", "clear",
// 布局属性:定位
"position", "left", "right", "top", "bottom", "z-index",
// 布局属性:列表
"list-style", "list-style-type", "list-style-position", "list-style-image",
// 布局属性:表格
"table-layout", "border-collapse", "border-spacing", "caption-side", "empty-cells",
// 布局属性:弹性
"flex-flow", "flex-direction", "flex-wrap", "justify-content", "align-content", "align-items", "align-self", "flex", "flex-grow", "flex-shrink", "flex-basis", "order",
// 布局属性:多列
"columns", "column-width", "column-count", "column-gap", "column-rule", "column-rule-width", "column-rule-style", "column-rule-color", "column-span", "column-fill", "column-break-before", "column-break-after", "column-break-inside",
// 布局属性:格栅
"grid-columns", "grid-rows",
// 尺寸属性
"box-sizing","margin","margin-left","margin-right","margin-top","margin-bottom","padding","padding-left","padding-right","padding-top","padding-bottom","border","border-width","border-style","border-color","border-colors","border-left","border-left-width","border-left-style","border-left-color","border-left-colors","border-right","border-right-width","border-right-style","border-right-color","border-right-colors","border-top","border-top-width","border-top-style","border-top-color","border-top-colors","border-bottom","border-bottom-width","border-bottom-style","border-bottom-color","border-bottom-colors","border-radius","border-top-left-radius","border-top-right-radius","border-bottom-left-radius","border-bottom-right-radius","border-image","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat","width","min-width","max-width","height","min-height","max-height",
// 界面属性
"appearance","outline","outline-width","outline-style","outline-color","outline-offset","outline-radius","outline-radius-topleft","outline-radius-topright","outline-radius-bottomleft","outline-radius-bottomright","background","background-color","background-image","background-repeat","background-repeat-x","background-repeat-y","background-position","background-position-x","background-position-y","background-size","background-origin","background-clip","background-attachment","bakground-composite","background-blend-mode","mask","mask-mode","mask-image","mask-repeat","mask-repeat-x","mask-repeat-y","mask-position","mask-position-x","mask-position-y","mask-size","mask-origin","mask-clip","mask-attachment","mask-composite","mask-box-image","mask-box-image-source","mask-box-image-width","mask-box-image-outset","mask-box-image-repeat","mask-box-image-slice","box-shadow","box-reflect","filter","mix-blend-mode","opacity","object-fit","clip","clip-path","resize","zoom","cursor","pointer-events","touch-callout","user-modify","user-focus","user-input","user-select","user-drag",
// 文字属性
"line-height","line-clamp","vertical-align","direction","unicode-bidi","writing-mode","ime-mode","text-overflow","text-decoration","text-decoration-line","text-decoration-style","text-decoration-color","text-decoration-skip","text-underline-position","text-align","text-align-last","text-justify","text-indent","text-stroke","text-stroke-width","text-stroke-color","text-shadow","text-transform","text-size-adjust","src","font","font-family","font-style","font-stretch","font-weight","font-variant", "font-size", "font-size-adjust", "color",
// 内容属性
"overflow-wrap", "word-wrap", "word-break", "word-spacing", "letter-spacing", "white-space", "caret-color", "tab-size", "content", "counter-increment", "counter-reset", "quotes", "page", "page-break-before", "page-break-after", "page-break-inside",
// 交互属性
"will-change", "perspective", "perspective-origin", "backface-visibility", "transform", "transform-origin", "transform-style", "transition", "transition-property", "transition-duration", "transition-timing-function", "transition-delay", "animation", "animation-name", "animation-duration", "animation-timing-function", "animation-delay", "animation-iteration-count", "animation-direction", "animation-play-state", "animation-fill-mode"
] // 属性排序
}
}
复制代码
- ショートカットキーの最適化を追加します。
// .vscode/keybindings.json
[{
"key": "ctrl+alt+c", // "cmd+alt+c"
"command": "csscomb.execute"
}]
复制代码
- その他の構成オプションについては、ドキュメントcsscomboptionsを参照してください。
最後に書く
この記事の調査を通じて、環境をスムーズに切り替えることができないため、新しい機能の早期採用をあきらめないでください。統合パッケージマネージャーでギザギザの問題が発生しなくなります。標準のGitCommitは、ステージの要約のログを生成でき、通常のクエリの方が便利です。コンポーネントレベルのテンプレート作成により、時間を節約し、長い反復プロジェクトでコーディングを標準化できます。CSSもフロントエンドの一部であり、優れた構造は読みやすく、保守しやすいという役割も果たしていることは無視できません。もちろん、開発プロセスで見落とされる可能性のあるいくつかの問題点があります。それらを整理した後、次回投稿します。また、コメント領域に、他にどのようなフロントエンド開発の問題点を見つけたかを入力してください。✔
チーム紹介
Gao Deng Technology(Beijing)Transaction Compliance Business LineのR&D部門に属するGao Deng Technology Transaction Compliance Front-End Team(GFE)は、技術主導の包括的な成長への情熱、創造性、および順守に満ちたチームです。チームの平均年齢は27歳で、それぞれの分野で長年栽培されている大きな雄牛と卒業したばかりの子牛がいます。私たちはエンジニアリング、コーディング品質、パフォーマンスの分野で積極的に調査しています。監視、マイクロサービス、インタラクティブエクスペリエンスなど、テクノロジー主導の製品実装の目的を追求し、完璧なフロントエンドテクノロジーシステムを作成します。
- ビジョン:最も信頼され、影響力のあるフロントエンドチームになる
- 使命:最初に顧客体験を守り、ビジネスの可能性を広げましょう
- 文化:引き受ける勇気、綿密なビジネス、チームワーク、シンプルでオープン
Github:github.com/gfe-team
チームのメールアドレス:[email protected]
著者:GFE(Gao Deng Technology Transaction Complianceフロントエンドチーム)
著作権は作者に帰属します。商用の再版については、著者に連絡して許可を求め、非商用の再版については、出典を示してください。