超全面的前端工程化配置指南

网站建设4年前发布
50 0 0

本文讲解如何构建一个工程化的前端库,并结合 Github Actions ,自动发布到  Github 和  NPM 的整个详细流程。,我们经常看到像 Vue 、 React 这些流行的开源项目有很多配置文件,他们是干什么用的?他们的 Commit、Release 记录都那么规范,是否基于某种约定?,废话少说,先上图!,2023030520335096c8795998cabdf381107724f6651bc5173bae160,上图标红就是相关的工程化配置,有 Linter、Tests,Github Actions 等,覆盖开发、测试、发布的整个流程。,下面我们从创建一个 TypeScript 项目开始,一步一步完成所有的工程化配置,并说明每个配置含义以及容易踩的坑。,为了避免兼容性问题,建议先将 node 升级到最新的长期支持版本。,首先在 Github 上创建一个 repo,拉下来之后通过 npm init -y​ 初始化。然后创建 src​ 文件夹,写入 index.ts 。,package.json 生成之后,我需要添加如下配置项:,我们将项目定义为 ESM 规范,前端社区正逐渐向 ESM 标准迁移,从 Node v12.0.0 开始,只要设置了  "type": "module"​ , Node 会将整个项目视为 ESM 规范,我们就可以直接写裸写 import/export 。,publishConfig.access​ 表示当前项目发布到 NPM 的访问级别,它有  restricted​ 和 public​ 两个选项, restricted​ 表示我们发布到 NPM 上的是私有包(收费),访问级别默认为 restricted​ ,因为我们是开源项目所以标记为 public 。,创建项目之后,我们开始安装工程化相关的依赖,因为我们是 TypeScript 项目,所以也需要安装 TypeScript 的依赖。,先安装 TypeScript,然后使用 tsc​ 命名生成  tsconfig.json 。,然后我们需要添加修改 tsconfig.json 的配置项,如下:,更多详细配置参考: www.typescriptlang.org/tsconfig,注意的点,如果你的项目涉及到 WebWorker API​ ,需要添加到  lib 字段中,然后我们将编译后的文件路径添加到 package.json​ ,并在  scripts 中添加编译命令。,types​ 配置项是指定编译生成的类型文件,如果  compilerOptions.declarationDir​ 指定的是 dist​ ,也就是源码和  .d.ts​ 同级,那么 types 可以省略。,验证配置是否生效,在 index.ts 写入,在控制台中执行,会在 dist​ 目录中生成  types/index.d.ts​ 、 index.js​ 、 index.js.map​ ,并打印  996 。,代码规范离不开各种 Linter​ , 之所以把这两个放在一起讲,借用  Prettier​ 官网的一句话: “使用 Prettier 解决代码格式问题,使用 linters 解决代码质量问题” 。虽然 eslint​ 也有格式化功能,但是 prettier 的格式化功能更强大。,大部分同学编辑器都装了 prettier-vscode 和 eslint-vscode 这两个插件,如果你项目只有其中一个的配置,因为这两者部分格式化的功能有差异,那么就会造成一个的问题,代码分别被两个插件分别格式化一次,网上解决 prettier​ + eslint​ 冲突的方案五花八门,甚至还有把整个 rules 列表贴出来的。,那这里我们按照官方推荐,用最少的配置去解决 prettier​ 和 eslint 的集成问题。,首先安装 eslint​ ,然后利用  eslint 的命令行工具生成基本配置。,执行上面命令后会提示一些选项,我们依次选择符合我们项目的配置。,注意,这里 eslint 推荐了三种社区主流的规范, Airbnb 、 Standard 、 Google ,因个人爱好我选择了不写分号的  Standard 规范。,生成的 .eslintrc.cjs 文件应该长这样,有些同学可能就要问了,这里为什么生成的配置文件名称是 .eslintrc.cjs​ 而不是 .eslintrc.js ?,因为我们将项目定义为 ESM​ , eslit --init​ 会自动识别 type​ ,并生成兼容的配置文件名称,如果我们改回 .js​ 结尾,再运行 eslint​ 将会报错。出现这个问题是 eslint​ 内部使用了 require() 语法读取配置。,同样,这个问题也适用于其他功能的配置,比如后面会讲到的 Prettier​ 、 Commitlint​ 等,配置文件都不能以 xx.js​ 结尾,而要改为当前库支持的其他配置文件格式,如: .xxrc​ 、 .xxrc.json​ 、 .xxrc.yml 。,验证配置是否生效,修改 index.ts,在 package.json​ 中添加 lint 命令,然后在控制台执行 lint​ , eslint 将会提示 1 条错误信息,说明校验生效。,因为是 Typescript 项目所以我们还要添加 Standard 规范提供的 TypeScrip 扩展配置(其他规范同理),安装 eslint-config-standard-with-typescript,添加修改 .eslintrc.cjs,验证配置是否生效,在控制台执行 lint​ , eslint 将会提示 2 条错误信息,说明校验生效。,现在我们按照官网的推荐方式,把 prettier​ 集成到  eslint 的校验中。,安装 prettier 并初始化配置文件,然后在 .prettierrc.json 添加配置,这里只需要添加和你所选规范冲突的部分。,更多配置详见: prettier.io/docs/en/opt…,安装解决冲突需要用到的两个依赖,再添加修改 .eslintrc.cjs ,如下:,然后验证配置是否生效,修改 index.ts,然后在控制台执行 lint​ ,这里 prettier​ 和 eslint 的行为已保持一致,如果没有报错,那就成功了。,我们现在已经完成了 eslint​ 和 prettier 的集成配置。和编辑器无关,也就是说无论你使用什么编辑器,有没有安装相关插件,都不会影响代码校验的效果。,因为一个项目通常是团队合作,我们不能保证每个人在提交代码之前执行一遍 lint​ 校验,所以需要 git hooks 来自动化校验的过程,否则禁止提交。,安装 Husky​ 并生成 .husky 文件夹,然后我们需要在每次执行 npm install​ 时自动启用 husky,如果你的 npm​ 版本大于等于 7.1.0,否则手动在 package.json 中添加,然后添加一个 lint 钩子,相当于手动在 .husky/pre-commit 文件写入以下内容:,测试钩子是否生效,修改 index.ts,然后提交一条 commit​ ,如果配置正确将会自动执行 lint​ 并提示 1 条错误信息, commit 提交将会失败。,为什么需要 Commitlint​ ,除了在后续的生成 changelog​ 文件和语义发版中需要提取 commit​ 中的信息,也利于其他同学分析你提交的代码,所以我们要约定 commit 的规范。,安装 Commitlint,最后将 Commitlint 添加到钩子,创建 .commitlintrc ,并写入配置,注意,这里配置文件名使用的是 .commitlintrc​ 而不是默认的 .commitlintrc.js ,详见  Eslint 章节,测试钩子是否生效,修改 index.ts ,让代码正确,提交一条不符合规范的 commit ,提交将会失败,修改为正确的 commit ,提交成功!,Angular 规范说明:,美好生活从测试覆盖率 100% 开始。,安装 jest​ ,和类型声明 @types/jest​ ,它执行需要 ts-node​ 和 ts-jest,这里暂时固定了 ts-node​ 的版本为  v9.1.1​ ,新版的 ts-node@v10.0.0​ 会导致 jest 报错,等待官方修复,详见: issues,初始化配置文件,然后修改 jest.config.ts 文件,将测试命令添加到 package.json 中。,创建测试文件夹 __tests__​ 和测试文件 __tests__/calc.spec.ts,修改 index.ts,然后在 calc.spec.ts 中写入测试代码,验证配置是否生效,在控制台执行 test ,将会看到测试覆盖率 100% 的结果。,最后我们给 __tests__​ 目录也加上 lint 校验,修改 package.json,这里如果我们直接执行 npm run lint​ 将会报错,提示 __tests__​ 文件夹没有包含在 tsconfig.json​ 的 include​ 中,当我们添加到 include​ 之后,输出的 dist 中就会包含测试相关的文件,这并不是我们想要的效果。,我们使用 typescript-eslint 官方给出的解决方案,如下操作:,新建一个 tsconfig.eslint.json 文件,写入以下内容:,在 .eslintrc.cjs 中修改,然后验证配置是否生效,直接提交我们添加的测试文件,能正确提交说明配置成功。,我们通过 Github Actions​ 实现代码合并或推送到主分支, dependabot 机器人升级依赖等动作,会自动触发测试和发布版本等一系列流程。,在项目根目录创建 .github/workflows​ 文件夹,然后在里面新建 ci.yml​ 文件和 cd.yml 文件,在 ci.yml 文件中写入:,上面配置大概意思就是,监听所有分支的 push​ 和 pull_request​ 动作,自动执行 linter​ 和 tests 任务。,GithubActions 更多用法参考: github.com/features/ac…,然后推送代码,验证配置是否生效,此时打开当前项目的 Github 页面,然后点击顶部  Actions 菜单就会看到正在进行的两个任务,一个将会成功(测试),一个将会失败(发布)。,上面只是实现了代码自动测试流程,下面实现自动发布的流程。,在此之前需要到 NPM 网站上注册一个账号(已有可忽略),并创建一个 package 。,然后创建 GH_TOKEN​ 和 NPM_TOKEN (注意,不要在代码中包含任何的 TOKEN 信息):,将创建好的两个 TOKEN 添加到项目的  Actions secrets 中:,Github 项目首页 ->  顶部 Settings 菜单 ->  侧边栏 Secrets,然后修改 package.json​ 中的 “name”​ , “name”​ 就是你在 NPM 上创建的 package 的名称。,在 cd.yml 文件中写入:,由于“黑命贵”,Github 已将新项目的默认分支名称更改为 “main” ,详见: issues , 为了方便,后面统一称为  主分支,所以如果你的主分支名称是 “main”​ ,上面的 branches 需要修改为:,然后安装语义发版依赖,需要用到 semantic-release 和它的插件:,在项目根目录新建配置文件 .releaserc 并写入:,这里同样,如果你的主分支名称是 “main”​ ,上面的 branches 需要修改为:,最后新建分支 develop 分支并提交工作内容。,然后将 develop 分支合并到  主分支 ,并提交,注意:这个提交会触发测试并  发布版本 (自动创建 tag​ 和 changelog ),完成上面操作之后,打开 Github 项目主页 和  NPM 项目主页 可以看到一个  Release 的更新记录。,最后切回到 develop 分支,创建一个自动更新依赖的 workflow 。,在 .github​ 文件夹中创建 dependabot.yml 文件,并写入内容:,提交并查看 workflows 是否全部通过,再合并到  主分支 并提交,这个提交不会触发版本发布。,触发版本发布需要两个条件:,更多发布规则,详见: github.com/semantic-re…,SemanticRelease 使用方式,详见: semantic-release.gitbook.io,如果你能正确配置上面所有步骤,并成功发布,那么恭喜你!你拥有了一个完全自动化的项目,它拥有:自动依赖更新、测试、发布,和自动生成版本信息等功能。,完整的项目示例: @resreq/event-hub,本文未涉及到:组件库、Monorepo、Jenkins CI 等配置,但能覆盖绝大部前端项目 CI/CD 流程。,有些地方讲得比较细,甚至有些啰嗦,但还是希望能帮助到大家!

© 版权声明

相关文章