发布于 2026-01-06 1 阅读
0

使用 Bazel 1.0 构建无服务器 Azure 函数应用 🌿 创建 Azure 函数应用程序框架 设置 Bazel 工作区 构建 Azure 函数应用程序 部署到 Azure

使用 Bazel 1.0 构建您的无服务器 Azure 函数应用🌿

搭建 Azure 函数应用程序框架

设置 Bazel 工作区

构建 Azure 函数应用程序

部署到 Azure

Bazel 刚刚迎来了一个新的里程碑:Bazel 1.0 于今日正式发布。现在正是投资这款分布式构建和测试编排工具的最佳时机。

在本快速指南中,我们将使用 Bazel 构建一个用 TypeScript 编写的Azure 函数应用程序。

Bazel 是多语言的,这意味着你可以用它同时构建和测试不同的技术,即使是在同一个 monorepo 中!今天我们将重点关注 TypeScript。

如果您想了解更多关于 Bazel 在构建 Web 应用程序方面的功能,我强烈建议您阅读我的朋友 Alex Eagle(来自 Google 的 JavaScript 构建/服务团队)撰写的以下文章。

以下是我们将要遵循的步骤:

  1. 搭建 Azure 函数应用程序
  2. 设置 Bazel 工作区
  3. 使用 Bazel 构建 Azure 函数应用程序
  4. 部署到 Azure

如果需要,我附上了Azure 免费试用版的链接,您可以自行试用。

让我们开始吧……

10 月 20 日更新:Hexa现在内置了对 Bazel 的支持!

搭建 Azure 函数应用程序框架

为了方便地创建和部署我们的Azure 函数应用程序,我们将使用Hexa CLI:

$ mkdir azurefunctionbazel && cd $_
$ hexa init --just functions
$ cd functions/azurefunctionbazel-5816
Enter fullscreen mode Exit fullscreen mode

Hexa 是一个开源 CLI 工具,可以增强 Azure CLI(了解更多关于 Hexa 以及如何安装它的信息)。

我们使用Hexa./functions/azurefunctionbazel-5816一个新的 TypeScript Azure 函数应用程序中搭建了脚手架,该应用程序tsc(默认情况下)使用构建。

我们将设置 Bazel 并使用它来通过ts_library规则(即 Bazel 插件)来编排构建过程。

设置 Bazel 工作区

为了在 Azure 函数项目中设置和使用 Bazel ./functions/azurefunctionbazel-5816,我们需要:

  1. 从 NPM 安装 Bazel 及其依赖项
  2. WORKSPACE在项目根目录下添加一个文件
  3. BUILD.bazel在项目根目录下添加一个文件
  4. BUILD.bazel在每个函数内部添加一个

通常情况下,您无需手动设置 Bazel,而是可以使用诸如 Bazel 之类的工具@bazel/create来自动完成设置和配置。

安装 Bazel 及其依赖项

在文件夹内./functions/azurefunctionbazel-5816,使用以下命令从 NPM 安装所需的 Bazel 及其依赖项(它还会更新现有依赖项package.json):

$ npm install -D \
      @bazel/bazel@latest \
      @bazel/typescript@latest \
      typescript@^3.3.3
Enter fullscreen mode Exit fullscreen mode

确保typescript已将其列为依赖项并已安装。package.json

添加WORKSPACE文件

WORKSPACE在根目录下创建一个文件,./functions/azurefunctionbazel-5816内容如下(详见下方说明):

workspace(
    name = "azurefunctionbazel",
    managed_directories = {"@npm": ["node_modules"]},
)

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "build_bazel_rules_nodejs",
    sha256 = "1447312c8570e8916da0f5f415186e7098cdd4ce48e04b8e864f793c766959c3",
    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.38.2/rules_nodejs-0.38.2.tar.gz"],
)

load("@build_bazel_rules_nodejs//:index.bzl", "npm_install")
npm_install(
    name = "npm",
    package_json = "//:package.json",
    package_lock_json = "//:package-lock.json",
)

load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
install_bazel_dependencies()

load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
ts_setup_workspace()

Enter fullscreen mode Exit fullscreen mode

让我们逐一解释每个部分……

workspace(
    name = "azurefunctionbazel",
    managed_directories = {"@npm": ["node_modules"]},
)
Enter fullscreen mode Exit fullscreen mode
  1. workspace规则声明此文件夹是 Bazel工作区的根目录。
  2. name属性声明了如何从另一个工作区使用绝对标签引用此工作区,例如:@azurefunctionbazel//
  3. managed_directories属性将@npmBazel 工作区映射到node_modules目录。这使得 Bazel 可以使用与其他本地工具相同的目录node_modules

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "build_bazel_rules_nodejs",
    sha256 = "1447312c8570e8916da0f5f415186e7098cdd4ce48e04b8e864f793c766959c3",
    urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.38.2/rules_nodejs-0.38.2.tar.gz"],
)
Enter fullscreen mode Exit fullscreen mode

这将安装 Node.js“bootstrap”包,该包提供在 Bazel 中运行和打包 Node.js 应用程序的基本工具。

load("@build_bazel_rules_nodejs//:index.bzl", "npm_install")
npm_install(
    name = "npm",
    package_json = "//:package.json",
    package_lock_json = "//:package-lock.json",
)
Enter fullscreen mode Exit fullscreen mode
  1. npm_install规则会在配置文件更改时运行npmyarn根据您的配置运行)。它还会提取软件包中分发的任何 Bazel 规则。package.jsonpackage-lock.jsonnpm
  2. name属性就是 Bazel Label 引用的样子。@npm//@azure/functions
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
install_bazel_dependencies()
Enter fullscreen mode Exit fullscreen mode

此调用将安装之前由该规则提取的所有 Bazel 规则npm_install

load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
ts_setup_workspace()
Enter fullscreen mode Exit fullscreen mode

这将为您的工作区设置 TypeScript 工具链。

BUILD.bazel

BUILD.bazel在根目录下创建一个文件,./functions/azurefunctionbazel-5816内容如下:

exports_files(["tsconfig.json"], visibility = ["//:__subpackages__"])
Enter fullscreen mode Exit fullscreen mode

这段简单的代码BUILD.bazel会将文件导出tsconfig.json,以便其他包可以引用它。

包裹BUILD.bazel

Bazel 建议创建细粒度的包,以提高构建效率。在 Bazel 术语中,包是指包含BUILD.bazel文件的文件夹,例如 .bazel.js ./functions/azurefunctionbazel-5816/httpTrigger/BUILD.bazel

在我们的示例中,Azure 函数应用程序包含一个文件夹,每个函数对应一个文件夹。这些文件夹将用于存放我们的 Bazel 包。

在每个部分中,BUILD.bazel我们将描述该包(即 Azure 函数)应该如何构建,并让 Bazel 来处理编排。

为了构建我们的应用程序,我们将尽量简化流程,仅使用tsc编译器。但是,对于更复杂的场景,我们也可以使用工具对应用程序进行打包rollup和压缩terser。一个假设的构建过程可能如下所示:

# Note: this build hasn't been tested!

load("@npm_bazel_typescript//:index.bzl", "ts_library")
load("@npm_bazel_rollup//:index.bzl", "rollup_bundle")
load("@npm_bazel_terser//:index.bzl", "terser_minified")

package(default_visibility = ["//visibility:public"])

ts_library(
    name = "httpTrigger",
    srcs = ["index.ts"],
    deps = ["@npm//@azure/functions"]
)

rollup_bundle(
    name = "bundle",
    entry_point = ":index.ts",
    deps = [":httpTrigger"],
)

terser_minified(
    name = "bundle.min",
    src = ":bundle",
)
Enter fullscreen mode Exit fullscreen mode

但就我们而言,我们将化繁为简:

load("@npm_bazel_typescript//:index.bzl", "ts_library")

package(default_visibility = ["//visibility:public"])

ts_library(
    name = "httpTrigger",
    srcs = ["index.ts"],
    deps = ["@npm//@azure/functions"]
)
Enter fullscreen mode Exit fullscreen mode
  1. 该属性是目标(本次调用)name的名称。ts_library
  2. srcs属性列出了所有要转译的 TypeScript 文件。
  3. deps属性列出了此包中使用的所有外部依赖项(例如@azure/functions)。@npm//是 NPM 工作区的名称(见WORKSPACE上文)。

细粒度的包管理让我们能够从 Bazel 获得增量式、可远程并行化的构建和自动缓存,这将大大缩短构建时间,尤其对于规模庞大、更为复杂的项目而言。

构建 Azure 函数应用程序

现在,我们可以运行 Bazel 来构建这个特定的软件包:

$ bazel build @azurefunctionbazel//httpTrigger:httpTrigger
Enter fullscreen mode Exit fullscreen mode

到达目标的标准路径解释如下:

替代文字

事实上,这条路径可以缩短为:

$ bazel build //httpTrigger
Enter fullscreen mode Exit fullscreen mode

这是因为我们是在同一个工作空间中构建指定的目标。所以我们可以省略工作空间标识符,并且由于包名和目标名相同,我们也可以省略目标名称。

我们还可以指示 Bazel 构建当前工作区内所有软件包的所有目标:

$ bazel build //...
Enter fullscreen mode Exit fullscreen mode

你可能不会觉得使用 Bazel 构建一个简单的函数有什么好处,但是一旦你开始处理数百个无服务器应用程序,Bazel 就能帮助你提高构建和测试性能。

Bazel 也非常擅长理解我们应用程序的依赖关系图。我们可以让 Bazel 向我们展示这个依赖关系图:

$ bazel query --noimplicit_deps 'deps(//...)' --output graph | dot -Tpng > azurefunctionbazel.png
Enter fullscreen mode Exit fullscreen mode

输出结果:

替代文字

我们可以利用这种可视化方式更好地了解应用程序的内部结构。想象一下,一个应用程序包含数百个函数应用!

部署到 Azure

ts_library()默认情况下, (*.js和)规则的输出*.d.ts将存储在./functions/azurefunctionbazel-5816/bazel-bin/httpTrigger

在部署到 Azure 之前,我们需要更新function.json每个函数的配置,并将其scriptFile指向bazel-bin/

{
  ...
  "scriptFile": "../bazel-bin/httpTrigger/index.js"
}
Enter fullscreen mode Exit fullscreen mode

我们还需要通过更新文件来确保不要将 Bazel 工作区部署到 Azure .funcignore

## Bazel ignored files
node_modules/@bazel/*
BUILD.bazel

# ignore all bazel output folder except the bazel-bin folder 
# where the transpiled code lives
bazel-*
!bazel-bin
Enter fullscreen mode Exit fullscreen mode

现在我们准备使用Hexa CLI 将应用程序部署到 Azure:

$ # cd to the root of azurefunctionbazel where hexa.json is located
$ hexa deploy
Enter fullscreen mode Exit fullscreen mode

部署命令的输出结果为:


✔ Building Function app azurefunctionbazel-5816...
✔ Deploying Function app azurefunctionbazel-5816...
✔ Application azurefunctionbazel deployed successfully!

➜ Functions:
 - httptrigger: https://azurefunctionbazel-5816.azurewebsites.net/api/httptrigger?code=POfqT9xFCtYKOaryFW8LkzFsUtD3ioWi8Y2e4M8BpBeLhTOH8aqUIg==
✔ Done in 68 seconds.
Enter fullscreen mode Exit fullscreen mode

恭喜🎉!您的 Azure 函数应用程序现已使用 Bazel 构建,并使用Hexa部署。

在 GitHub 上找到示例项目

使用 Bazel 1.0 构建 Azure 函数应用

文章来源:https://dev.to/azure/build-azure-function-apps-with-bazel-1-0-mci