git workflow 深入
只会
git clone``git pull``git commit``git push感觉有点 low 了,这里深入写 git workflow
[用💻emoji key代表贡献者贡献方面情况](https://allcontributors.org/docs/en/emoji-key)``[常用实践工作流](https://juejin.cn/post/6844903455933333517)
基本概念
工作区是你的文件系统的实际目录
暂存区是git暂存的相对于上个提交的修改,
- 在
.git/index目录下 git add可以把改动后的文件添加到暂存区- 提交是把暂存区的内容更改到版本库,所有工作区更改都应放到暂存区
常用命令
一般在实际的企业级项目开发时,你需要去更新到一个特定的分支。git reset <commit_id> --soft:撤销到对应的提交(用HEAD无效),
soft工作区、暂存区都不变,应当用这个选项mixed工作区不变,但暂存区清空默认值hard工作区和暂存区都清空与远端交互
git pull origin branchname:从origin远端拉取branchname分支的代码,一般本地分支和远端分支是一样的,或者直线的(?。git fetch origin branchname:从origin远端将branchname的代码拉下来。但是不会合并多分支开发
git branchgit branch branchname:新建一个分支名的分支git branch --set-upstream-to=origin/remoteBranchName localBranchName:可以将本地分支与远程分支关联,远程分支可以不存在,然后推上去
git branch -d branchname:删除该分支,不过要求该分支已经被合并git checkout branchname:将当前分支切换到branchname分支git checkout -b branchname:新建并切换到对应分支。
注意切换分支时,工作区文件会被另一分支的状态覆盖,需要提前保存git merge source:将source分支合并到当前分支
比如,你在日常开发的时候,维护一个日常dev分支,你自己起了一个大的功能分支feat,你需要定期同步dev分支的代码,解决方案:
- 就是fetch+merge。
但是请注意之前先stash一下,不然目前没有提交上的代码将会丢失
不太行 [git rebase](https://blog.csdn.net/weixin_42310154/article/details/119004977)
你在你的分支mindmap下,使用git rebase master可以同步master分支的代码,且你的分支的提交都是在原有变更之后的,不会出现merge的提交顺序错乱的问题提交操作
git cherry-pick:可以将一个分支的某些提交移到当前分支前面,可以用来把之前的提交挪到最上面
撤销
可以通过git reflog,pick要撤销到的commitid,然后做撤销
对git reset等有效。
但是对于git rebase等操作无效,这种情况使用git cherry-pick
修改暂存
git stash可以把当前代码相对git state的变动缓存,届时可以恢复
(什么时候可以恢复?什么时候又会冲突
会用到的工具
[一个总体的小说明文章](https://juejin.cn/post/6878592895499108365)
npx husky-initnpm install --save-dev @commitlint/config-conventional @commitlint/cli lint-staged
"commitlint": {"extends": ["@commitlint/config-conventional"]},"lint-staged": {"*.{less,md}": ["prettier --write"],"*.js?(x)": ["prettier --write","eslint --fix"],"*.ts?(x)": ["prettier --parser=typescript --write","eslint --fix"]},
🐶husky
[源码分析](https://juejin.cn/post/7055294717335961608)
可以容易的在提交时执行命令
安装这个需要初始化一下.husky文件夹。用npx husky-init做一下就没问题
发现一个相关工具:yorkie yorkie https://juejin.cn/post/6844903816400207880
commitlint
规范提交信息,默认提交信息格式如下所示:
type[scope][!]:description(空行)body(空行)footer
默认提交信息标准参照了[约定式提交规范](https://www.conventionalcommits.org/zh-hans/v1.0.0/#%e7%ba%a6%e5%ae%9a%e5%bc%8f%e6%8f%90%e4%ba%a4%e8%a7%84%e8%8c%83)``[Angular 提交约定](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)。下面是具体说明:
type:build: 更改构建流程或者外部依赖 (example scopes: gulp, broccoli, npm)chore: 对构建过程或辅助工具和库(如文档生成)的更改ci: 对 CI 脚本和配置的改变 (example scopes: Travis, Circle, BrowserStack, SauceLabs)docs: 仅文档变化feat: 加入新特性fix: A bug fixperf: 性能提升refactor: 代码重构,不修复 bug,不加入新特性revert: 回退之前的提交。这时body应该是This reverts commit <hash>.,其中hash是被回退提交的 SHA style: 对代码风格的改变,不影响test: 加入新的测试或更正现有的测试
!:表示是一个breaking change需要大型提交
scope:可以用/``\``,隔开
如果相应npm包做了更变,用这个
此外还可以写自己项目的模块定义等别的。这个可以自定义
footer:
写#31, #34等自动关联到对应的issue
安装时,需要安装好包,然后在以下文件中写入配置:
"commitlint": {"extends": ["@commitlint/config-conventional"]},
#!/bin/sh. "$(dirname "$0")/_/husky.sh"npx --no-install commitlint --edit ""
按照这样的设定,写提交会稍微麻烦一点。这改变了你在vscode上点一下按钮就🆗的习惯。所以应该这么做:

提交时点击上图的编辑按钮填好表单,在save,然后提交
lint-staged
提交的时候用
eslint等修一下代码
这个貌似只要安装好配置好就行了,不用管太多。
目前没在上面遇到坑。遇到了再说。
changelog
https://www.npmjs.com/package/standard-version
使用 np 来完成提交发布工作流,这里推荐使用conventional-changelog-cli自动生成changelog
首先安装包到 dev,然后填写npm version命令为
zsh
zsh默认有git插件,有很多git命令的简写:去上面链接里面查
vim
首先你要知道vim的状态机:
npm
https://juejin.cn/post/6987179395714646024
package.json dependencies 的排列一定要按字母顺序排列(别问我怎么知道的)
node_modules
https://juejin.cn/post/6844903870578032647
通过 unpkg 后面输入包名和版本,可以查看这个 npm 包的文件信息,如 package.json
package.json
dependencies 的排列一定要按字母顺序排列(别问我怎么知道的)
如要重新安装 node_modules,请将node_modules和package-lock.json一起删除后,再npm installpeerDependencies不知道是必须是直接安装依赖还是可以传递依赖。
目前找到的文章:
(可能比较老了)
npm scripts(shell)
https://juejin.cn/post/6883665888348733453
https://juejin.cn/post/6844903816987410439
生命周期脚本
prepublish:在打包和发布包之前运行,在npm install没有任何参数的本地运行。prepare:在打包和发布包之前运行,在本地npm install:没有任何参数,以及安装git依赖项时运行。这是在之后运行prepublish,但是之前prepublishOnlyprepublishOnly:仅在准备和打包之前运行npm publish。prepack:前运行压缩包(npm pack,npm publish并安装git的依赖时)postpack:在生成压缩包并移动到其最终目的地之后运行。publish postpublish:发布包后运行preinstall:包安装之前运行install``postinstall:包安装后运行。默认:node-gyp rebuild,如果binding.gyp包的根目录中有一个文件而您尚未定义自己的脚本install或preinstall脚本,npm将默认install使用node-gyp进行编译。preuninstall``uninstall:在包卸载之前运行。postuninstall:在包卸载之后运行。preversion:在碰撞包版本之前运行。version:碰撞包版本之后,但提交之前运行。postversion:碰撞包版本之后,提交之后运行。
部署
纯前端原生html、css、js可以直接打开html运行。
如果是搞一个纯前端的项目,可以直接通过静态部署的方式,以index.html为入口部署单页应用。
但是一旦涉及到前后端联合,你就需要好好注意一下了。
与 node_modules
在项目中执行npm i安装时,会安装项目下dependencies``devDependencies的依赖包。
安装依赖包时,只会安装依赖包下dependencies。
对于三种dependencies的定位不再赘述。只是分情况讨论:
- 纯前端应用
纯前端应用可以说完全不需要关心三种dependencies的区别。因为部署不涉及npm安装包,部署的是打包产物(index.html等) - 前端组件/组件库
这种情况下,尤其需要注意三种dependencies的配置问题,看后面的发布 npm 包部分 - 前后端联合
这时后端就需要注意dependencies和devDpendencies的区别了。具体部署在服务器上不需要安装发布 npm 包
https://zhuanlan.zhihu.com/p/344951970
https://juejin.cn/post/6844903870678695943
发布时,一定记得使用官方源。尤其是你一般使用镜像的时候组件/组件库
就现在来说(2022/4/12),做 react 组件库最优的解决方案是 dumi 可以看我的 react 笔记,上面有 umi/dumi 的详细踩坑记录
https://juejin.cn/post/6844903928316821517[基于 antd 封装组件并发布](https://zhuanlan.zhihu.com/p/80754775)
一些需要注意的:
- 开发组件库不能使用
cra。这个东西是做react单页应用的,不能应用于做组件库依赖原则
最终构建产物一般是lib,里面是js和.d.ts文件
如果只有一个组件,可以使用module指定直接引用所拿到的js,不指定默认是项目文件夹下index.js
如果是react``antd这种非常知名且影响项目全局的库,写入peerDependencies和devDependencies,千万不要写入dependencies。这一点使用dumi额外注意,由于一些原因,不要在
node_modules显式安装react``react-dom,否则可能会出现两个react实例的情况。 另外antd也不要装,装@umijs/preset-react就有默认引入依赖了
如果是不影响全局的不太知名的,而且不以以上库作为dependencies依赖的(组件库不应该把这些库作为dependencies依赖),可以写入dependencies,这种重复其实没事。
如果在生产模式下(组件库打包不打入依赖),用不着的,全放入devDependencies
webpack配置
首先,发布组件/组件库到npm不使用create-react-app!
不但项目目录不行,docs也不行,cra没法容易的改entry,除非你在docs下面新建package.json来配然后遇到别的问题
package.json
nodejs应用
配置注意事项
如果包在peerDependencies中,请把该包移到devDependencies
np
使用 np 来做 npm 包发布与更新。
具体执行命令时,直接在命令行输入np即可,会通过交互的方式完成所有需要的步骤。
注意事项:
- 默认会清空
node_modules重装,加入--no-cleanup选项。
毕竟umi的依赖和node_modules构成都是非常高危的存在。。。写一个 npm cli
https://juejin.cn/post/6844903702453551111
- 设置
package.json中的bin,加入字段cli-name: entry.js npm link之后,你就可以直接在你本机调用了process.argv以数组的形式展示命令行参数,前两个分别是node程序的路径和脚本存放的位置。- 第三个参数开始就是你命令行输入的参数,但是只会以空格分隔,没有约定的参数规则
webpack
https://juejin.cn/post/6844904094281236487
loader
对于一个使用多个loader的规则,是从后往前执行
对于 css loader,style-loader,前者将css转为js,后者将js化的css转到html的style标签上去raw-loader加载原始内容file-loader把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)url-loader:与 file-loader 类似,区别是用户可以设置一个阈值,大于阈值会交给 file-loader 处理,小于阈值时返回文件 base64 形式编码 (处理图片和字体)Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。
在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。
plugin
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
打包结果
默认打包结果是一个bundle.js和index.html文件。如果有一些别的loader和plugin,也会导出别的文件。
如果是多入口打包,出来的js文件会是多个。
webpack.config.js
外部依赖
防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
配置形式:
module.exports = {//...externals: {// 字符串形式jquery: 'jQuery',},};
多配置合并
const merge = require('webpack-merge');const baseConfig = require('./webpack.base.js')const prodConfig = {}module.exports = merge(baseConfig, prodConfig)
rollup
模块系统
https://juejin.cn/post/6935973925004247077
https://juejin.cn/post/7002031102390976525
ejs(ES 6 Module)
ES module 通过 import结构赋值其它js文件 export得到的对象。
其中 export default直接导出,其它的需要对象属性解构赋值的方式引入。
此外,如果 import引入的是一个文件夹,会默认引入文件夹下的 index.js文件。只能在文件开头引用。
可通过 import 引入 json 文件。
如果想要不通过 babel 等方式(create react app等是使用的这种方式)使用 ES module 的引入方式(一般是 nodejs 后端应用),需要在 package.json后加入type: "module"
import 非js文件
这一部分是 webpack 等打包工具的支持。
webpack 通过 loader 来读取这些文件。这些文件读取之后没有输出(不返回变量),虽然不知道之后会怎样。
详见 https://www.webpackjs.com/concepts/#loader
cjs(commonJS)
https://juejin.cn/post/6844903576309858318
这个是在 nodejs 项目中来引用。虽然这两种方式的底层实现不同,但是不交融的情况可以一起使用。
commonjs 通过 require('js-script')来引用js文件输出的 module.exports对象。可以在任意位置引用。
AMD
UMD
eslint/prettier
https://eslint.bootcss.com/
https://eslint.org/[umi 4 解决方案](https://mp.weixin.qq.com/s/9dU9pC7SbTfuZOGhEaRT7w)
npm install babel-eslint eslint eslint-config-prettier eslint-loader eslint-plugin-vue eslint-plugin-prettier prettier —save-dev
eslint和prettier在一些地方还是有冲突的。比如switch case语句,他俩的格式风格。(这使得我取消了eslint indent 规则,暂时没找更好的解决方案)
最佳实践
- 对于代码风格:全部交给 prettier,eslint 不定义任何规则。
eslint 只对代码质量进行约束。 - 不继承任何规则 Config
uml
https://zhuanlan.zhihu.com/p/76948461时序流程图
