构建系统
Backstage 构建系统是一系列构建和开发工具的集合,可帮助您对 Backstage 项目进行检查、测试、开发和最终发布。 构建系统的目的是提供与 Backstage 完美配合的开箱即用解决方案,让您专注于应用程序的构建,而不必花时间设置自己的工具。
构建系统设置是@backstage/cli并已包含在您使用@backstage/create-app例如React 脚本这是您使用创建 React 应用程序Backstage 构建系统在很大程度上依赖于 JavaScript 和 TypeScript 生态系统中现有的开源工具,例如Webpack,卷轴,玩笑和ESLint.
设计考虑因素
在设计 Backstage 构建系统时,我们遵循了几个核心理念和约束条件。 首先,也是最重要的一点是,我们将开发体验放在第一位。 如果我们需要偷工减料或增加复杂性,我们会在其他领域这样做,但启动编辑器和迭代代码的体验应始终尽可能顺畅。
此外,还有一些硬性和软性要求:
- 发布--应能构建和发布单个软件包 * 扩展--应能扩展到数百个大型软件包,而无需过长的等待时间 * 重载--开发流程应支持快速的保存热重载 * 简单--使用应简单,配置应保持在最低水平 * 通用--面向网络应用程序、同构软件包和 Node.js 的开发 * 现代--构建系统以现代环境为目标 * 编辑器--大多数编辑器都应提供类型检查和衬垫功能
在设计构建系统的过程中,现有工具无法支持这种需求收集,例如react-scripts
由于需要结合 monorepo、出版和编辑支持进行扩展,我们采用了自己的专门设置。
结构
我们可以将 Backstage 内部的开发流程分为几个不同的步骤:
- 格式化** - 对源代码应用一致的格式化 * 着色 - 分析源代码以查找潜在问题 * 类型检查 - 验证 TypeScript 类型是否有效 * 测试 - 对项目运行不同级别的测试套件 * 构建 - 在单个软件包中编译源代码 * 捆绑 - 将软件包及其所有依赖项合并为一个可用于生产的捆绑包
这些步骤通常是相互隔离的,每个步骤都专注于其特定的任务。 例如,我们不会在构建或捆绑的同时进行着色或类型检查。 这样做是为了提供更大的灵活性,避免重复工作,提高性能。 强烈建议您在开发 Backstage 时使用支持格式化、着色和类型检查的代码编辑器或集成开发环境。
下面我们就来详细了解一下这些步骤中的每一步,以及它们在典型的 Backstage 应用程序中是如何实现的。
包裹角色
要迁移现有项目,请参阅迁移指南。
Backstage 构建系统使用软件包角色的概念,以帮助精简配置、提供实用程序和工具,并实现优化。 软件包角色是一个单独的字符串,用于标识软件包的用途,它定义在package.json
每个软件包的
{
"name": "my-package",
"backstage": {
"role": "<role>"
},
..
}
这些是Backstage构建系统目前支持的可用角色:
| 角色 | 说明 | 示例 | | ---------------------- | -------------------------------------------- | -------------------------------------------- | 前端 | 绑定的前端应用程序 | 前端应用程序packages/app
| | 后端 | | 捆绑后端应用程序 | | 后端应用程序packages/backend
| 作为命令行界面使用的软件包@backstage/cli
,@backstage/codemods
| | web-library | 供其他软件包使用的网络库 | | | web-library@backstage/plugin-catalog-react
| | node-library | 供其他软件包使用的 Node.js 库 | | | Node.js 数据库@backstage/plugin-techdocs-node
| 其他软件包使用的同构库@backstage/plugin-permission-common
| | 前端插件 | Backstage前端插件 | | 前端插件@backstage/plugin-scaffolder
| | 前端插件模块 | Backstage前端插件模块 | | 前端插件模块@backstage/plugin-analytics-module-ga
| | 后端插件 | Backstage后端插件 | | 后端插件@backstage/plugin-auth-backend
| | 后端插件模块 | Backstage后端插件模块@backstage/plugin-search-backend-module-pg
|
下面介绍的大多数步骤都有相应的命令,可用作软件包脚本。 这些命令都可以在backstage-cli package
这些命令可以这样使用:
{
"scripts": {
"start": "backstage-cli package start",
"build": "backstage-cli package build",
"lint": "backstage-cli package lint",
..
}
}
格式化
格式设置完全在每个 Backstage 应用程序中进行,而不是 CLI 的一部分。 在使用@backstage/create-app
格式由漂亮但每个应用程序都可以选择自己的格式化规则,并根据需要切换到不同的格式化器。
林汀
Backstage CLI 包括一个lint
命令,它是对eslint
它增加了一些无法通过配置设置的选项,例如包括.ts
和.tsx
扩展名。lint
命令只是提供了一个合理的默认设置,并不打算进行自定义。 如果想提供更多高级选项,可以调用eslint
而不是直接
除了lint
命令,后端 CLI 还包括一套基本 ESLint 配置,一套用于前端软件包,另一套用于后端软件包。 这些 lint 配置反过来又建立在来自于@spotify/web-scripts.
在标准的 Backstage 设置中,每个单独的软件包都有自己的 lint 配置,以及适用于整个项目的根配置。 每个软件包中的配置一开始都是根据软件包角色确定的标准配置,但也可以根据每个软件包的需要进行定制。
最低限度.eslintrc.js
现在的配置是这样的
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
但您可以使用可选的第二个参数为每个软件包提供自定义重载:
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, {
ignorePatterns: ['templates/'],
rules: {
'jest/expect-expect': 'off',
},
});
配置工厂还为扩展配置提供了实用工具,否则使用普通 ESLint 进行扩展会非常麻烦,特别是对于像no-restricted-syntax
这些是可用的额外按键:
| 关键 | 说明 | | -------------------------- | ------------------------------------------------------------------ | | |tsRules
| 适用于 TypeScript 文件的附加规则testRules
| 适用于测试文件的附加规则restrictedImports
| 添加到no-restricted-imports
| |restrictedImportPatterns
| 添加到其他模式no-restricted-imports
| |restrictedSrcImports
| 添加到no-restricted-imports
在源文件中restrictedTestImports
| 添加到no-restricted-imports
在测试文件中restrictedSyntax
| 添加到其他模式no-restricted-syntax
| |restrictedSrcSyntax
| 添加到其他模式no-restricted-syntax
在源文件中restrictedTestSyntax
| 添加到其他模式no-restricted-syntax
在测试文件中
类型检查
与格式化一样,Backstage CLI 也没有自己的类型检查命令,但它有一个基本配置,其中既有推荐的默认值,也有构建系统工作所需的一些设置。
在 backstage 项目中,TypeScript 设置最值得注意的部分可能是整个项目是一个大的编译单元。 这是出于性能优化和易用性的考虑,因为将项目分解成更小的部分已被证明会导致更复杂的设置,而且整个项目的类型检查也会慢一个数量级。 为了使这 种设置正常工作,每个包的入口点都需要指向 TypeScript 源文件,这反过来又会在发布过程中造成一些复杂问题,我们将在以下章节中讨论该部分.
类型检查一般配置为增量式,用于本地开发,其输出存储在dist-types
这样,在运行tsc
中禁用增量类型检查。tcs:full
Yarn 脚本默认包含在任何 Backstage 应用程序中,供 CI 使用。
另一个默认使用的优化是跳过库类型的检查,这意味着 TypeScript 不会验证在node_modules
禁用该检查可大大加快类型检查的速度,但归根结底,它仍然是一个重要的检查,不应完全省略,因为它根本不可能捕捉到本地开发过程中引入的问题。 我们选择在 CI 中通过tsc:full
脚本,它将运行全面的类型检查,包括node_modules
.
基于上述两个原因,我们认为高度建议使用tsc:full
脚本在 CI 中运行类型检查。
测试
如上所述,Backstage CLI 使用玩笑Jest 是一个 JavaScript 测试框架,涵盖测试执行和断言。 Jest 在 Node.js 中执行所有测试,包括前端浏览器代码。 它使用的技巧是在 Node.js 虚拟机中使用各种预定义环境执行测试,例如基于jsdom有助于模仿浏览器 API 和行为。
Backstage CLI 有自己的命令,可以帮助执行测试、backstage-cli test
以及其自身的配置@backstage/cli/config/jest.js
该命令是运行jest
它的主要职责是确保使用所包含的配置,以及设置NODE_ENV
和TZ
环境变量,并提供了一些合理的默认标志,如--watch
在 Git 仓库中执行。
到目前为止,最大的工作量是由Backstage CLI 附带的 Jest 配置完成的。 它既负责提供默认的 Jest 配置,又允许在每个package.json
如何在实践中做到这一点,将在Jest 配置节。
架构
构建过程的主要目的是为发布软件包做准备,但它也是后端捆绑过程的一部分。 由于它只在这两种情况下使用,任何不使用项目后端部分的 Backstage 应用程序可能根本不需要与构建过程交互。 不过,了解它的工作原理还是很有用的,因为所有已发布的 Backstage 软件包都是通过该过程构建的。
目前的构建使用卷轴并对每个软件包单独执行。package build
命令,并适用于所有软件包角色(捆绑的角色除外)、frontend
和backend
.
联编过程可能有三种不同的输出:CommonJS 模块格式的 JavaScript、ECMAScript 模块格式的 JavaScript 以及类型声明。 每次调用联编命令都会将其中一个或多个输出写入dist
文件夹,并复制样式表或图像等任何资产文件。 有关构建过程支持哪些语法和文件格式的更多详情,请参阅装载机部分.
在构建 CommonJS 或 ESM 输出时,构建命令将始终使用src/index.ts
所有非相关模块的导入都被视为外部导入,这意味着 Rollup 编译只会编译软件包本身的源代码。 所有外部依赖包的导入语句,即使是在同一个 monorepo 中,也将保持不变。
类型定义的联编工作方式完 全不同。 类型定义联编的入口点是软件包在dist-types
这意味着,在构建任何包含类型定义的包之前,运行类型检查非常重要,并且必须在 TypeScript 配置中启用类型声明。 类型定义构建步骤的原因是,除从包中导出的类型外,剥离所有类型,留下一个更简洁的类型定义文件,并确保类型定义与生成的 JavaScript 同步。
捆绑
捆绑过程的目的是将多个软件包组合成一个运行时单元。 在前端和后端、本地开发和生产部署之间,捆绑的方式各不相同。 因此,我们将分别介绍这些情况的每一种组合。
前端开发
前端开发设置用于所有具有前端角色的软件包,并使用package start
不同角色之间的唯一区别是,使用'frontend'
角色使用src/index
作为入口点,而其他角色则使用dev/index
运行启动命令后,开发服务器将被设置为监听协议、主机和端口。app.baseUrl
如果需要,也可以通过app.listen
配置。
前端开发捆绑目前基于Webpack和Webpack 开发服务器Webpack 配置本身在前端开发和生产捆绑之间差别不大,因此我们将在下面的生产部分深入探讨配置。 主要区别在于process.env.NODE_ENV
设置为'development'
禁用最小化,使用廉价源映射,以及React 刷新已启用。
如果您希望在 Webpack 流程中运行类型检查和工整,可以启用使用ForkTsCheckerWebpackPlugin通过传递--check
尽管如上所述,在开发过程中处理这些检查的推荐方法是使用内置支持这些检查的编辑器。
前端生产
前端制作捆绑会创建典型的网络内容捆绑包,所有内容都包含在一个文件夹中,可随时提供静态服务。'frontend'
角色,而且与开发捆绑不同的是,没有办法为单个插件构建生产捆绑包。 捆绑过程的输出将写入dist
文件夹。
与开发捆绑一样,生产捆绑的基础是Webpack它使用HtmlWebpackPlugin以产生index.html
可通过添加public/index.html
模板可以访问两个全局常量、publicPath
是捆绑包打算提供服务的公共基本路径,以及config
的常规前端范围配置。@backstage/config
.
Webpack 配置还包括一个自定义插件,用于从链接的软件包中正确解析软件包,即ModuleScopePlugin
从React-dev-utils可以确保导入不会超出包的范围,还可以为一些 Node.js 模块提供一些回退,例如'buffer'
和'events'