From 03b48c78c1c66d1d04fed2501bb8cddb64db1dc9 Mon Sep 17 00:00:00 2001 From: 100gle Date: Wed, 27 Sep 2023 09:40:09 +0800 Subject: [PATCH 01/10] i18n(zh-cn): update integration docs --- .../guides/integrations-guide/cloudflare.mdx | 130 ++++++++++++++++++ .../zh-cn/guides/integrations-guide/node.mdx | 2 - .../guides/integrations-guide/tailwind.mdx | 20 +++ 3 files changed, 150 insertions(+), 2 deletions(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index 7dcb744e17c19..36d3572ac04dc 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -86,6 +86,92 @@ export default defineConfig({ 请注意,此适配器不支持使用 [Cloudflare 页面中间件](https://developers.cloudflare.com/pages/platform/functions/middleware/)。Astro 将会把 [Astro 中间件](/zh-cn/guides/middleware/) 打包到每个页面中。 +### routes.strategy + +`routes.strategy: "auto" | "include" | "exclude"` + +默认值:`"auto"` + +在没有提供自定义 `_routes.json` 的情况下决定 `routes.json` 该如何被生成。 + +这有三个选项可供选择: + +* **`"auto"`(默认):**自动选择生成最少条目的策略。这通常应该够用了,除非你有某些理由要选择其他选项。 +* **`include`:** 不会被预渲染的页面和端点将会被列为 `include` 条目,并告诉 Cloudflare 将这些路由作为函数调用。而 `exclude` 条目仅用于解决冲突。通常情况下,如果你的网站大多数是静态页面,只有少数动态页面或端点时,这将是最好的策略。 + + + 示例:对于 `src/pages/index.astro`(静态),`src/pages/company.astro`(静态),`src/pages/users/faq.astro`(静态),以及 `/src/pages/users/[id].astro` (SSR),将产生以下 `_routes.json`: + + ```json + { + "version": 1, + "include": [ + "/_image", // Astro 的图片端点 + "/users/*" // 动态路由 + ], + "exclude": [ + // 排除上述动态通配符路由中后的静态路由 + "/users/faq/", + "/users/faq/index.html" + ] + } + ``` + +* **`exclude`:** 预渲染的页面将被列为 `exclude` 条目(即告诉 Cloudflare 将这些路由作为静态资源处理)。通常情况下,如果你的网站大多数是动态页面或端点,只有少数静态页面时,这将是最好的策略。 + + 示例:对于前面示例中相同的页面,这将产生以下 `_routes.json`: + + ```json + { + "version": 1, + "include": [ + "/*" // 除了后面的路由外,所有路由都会被作为函数处理 + ], + "exclude": [ + // 所有静态资源 + "/", + "/company/", + "/index.html", + "/users/faq/", + "/favicon.png", + "/company/index.html", + "/users/faq/index.html" + ] + } + ``` + +### routes.include + +`routes.include: string[]` + +默认值:`[]` + +如果你想使用自动生成的 `_routes.json`,但又想要包含额外的路由(例如,当你有自定义函数在 `functions` 文件夹中时),那么你可以使用 `routes.include` 选项将额外的路由添加到 `include` 数组中。 + +### routes.exclude + +`routes.exclude: string[]` + +默认值:`[]` + +如果你想要使用自动生成的 `_routes.json`,但又想要排除其他的路由,那么你可以使用 `routes.exclude` 选项将额外的路由到添加 `exclude` 数组中。 + +以下示例自动生成了 `_routes.json`,同时包含和排除额外的路由。请注意,如果你在 `functions` 文件夹中有自定义函数,那么这些函数将不会被 Astro 处理。 + +```diff +// astro.config.mjs +export default defineConfig({ + adapter: cloudflare({ + mode: 'directory', ++ routes: { ++ strategy: 'include', ++ include: ['/users/*'], // 由自定义函数处理:functions/users/[id].js ++ exclude: ['/users/faq'], // 由静态页面处理:pages/users/faq.astro ++ }, + }), +}); +``` + ## 启用预览 为了使预览功能正常工作,你需要安装 `wrangler` @@ -204,6 +290,50 @@ export default defineConfig({ }); ``` +## Wasm 模块导入 + +`wasmModuleImports: boolean` + +默认值:`false` + +不论是否直接导入 `.wasm` 文件,都会将其视作 ES 模块。 + +将 `wasmModuleImports: true` 添加到 `astro.config.mjs` 以在 Cloudflare 构建和 Astro 开发服务器中启用该功能。 + +```diff +// astro.config.mjs +import {defineConfig} from "astro/config"; +import cloudflare from '@astrojs/cloudflare'; + +export default defineConfig({ + adapter: cloudflare({ ++ wasmModuleImports: true + }), + output: 'server' +}) +``` + +启用之后,你可以在 Astro 中通过 `.wasm?module` 语法来导入一个 WebAssembly。 + +以下是导入一个 Wasm 模块的示例,该模块通过将请求的数字参数相加来返回响应: + +```javascript +// pages/add/[a]/[b].js +import mod from '../util/add.wasm?module'; + +// instantiate ahead of time to share module +const addModule: any = new WebAssembly.Instance(mod); + +export async function GET(context) { + const a = Number.parseInt(context.params.a); + const b = Number.parseInt(context.params.b); + return new Response(`${addModule.exports.add(a, b)}`); +} +``` + +虽然这个例子很简单,但是 Wasm 用来加速在不涉及大量 I/O 的情况下的计算密集型操作,比如嵌入图像处理库。 + + ## 标头、重定向和函数调用路由 Cloudflare 支持添加自定义 [标头](https://developers.cloudflare.com/pages/platform/headers/)、配置静态 [重定向](https://developers.cloudflare.com/pages/platform/redirects/) 和定义哪些路由应该 [调用函数](https://developers.cloudflare.com/pages/platform/functions/routing/#function-invocation-routes)。Cloudflare 在构建输出目录中查找 `_headers`、`_redirects` 和 `_routes.json` 文件来配置这些功能。这意味着它们应该放在 Astro 项目的 `public/` 目录中。 diff --git a/src/content/docs/zh-cn/guides/integrations-guide/node.mdx b/src/content/docs/zh-cn/guides/integrations-guide/node.mdx index ddd462a98a4aa..0954120ff678e 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/node.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/node.mdx @@ -8,8 +8,6 @@ category: adapter i18nReady: true --- -import Video from '~/components/Video.astro'; - 此适配器允许 Astro 将你的 SSR 站点部署到 Node 目标。 ## 为什么是 Astro Node.js diff --git a/src/content/docs/zh-cn/guides/integrations-guide/tailwind.mdx b/src/content/docs/zh-cn/guides/integrations-guide/tailwind.mdx index 745672441de77..e77d9d8257100 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/tailwind.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/tailwind.mdx @@ -62,6 +62,26 @@ export default defineConfig({ }); ``` +然后,在你的项目根目录下创建一个 `tailwind.config.cjs` 文件。你可以使用以下命令来生成一个基本的配置文件: + +```sh +npx tailwindcss init +``` + +最后,可将如下基本配置添加到你的 `tailwind.config.cjs` 文件中: + +```js ins={4} "content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}']" +// tailwind.config.cjs +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], + theme: { + extend: {}, + }, + plugins: [], +}; +``` + ## 使用 当你安装集成后,Tailwind 的实用类应该马上就可以使用了。前往 [Tailwind 文档](https://tailwindcss.com/docs/utility-first)学习如何使用 Tailwind,如果你看到一个你想尝试的实用类,就把它添加到你项目的任何 HTML 元素中去吧! From c7bff9f9601d39fa9e5d7e4ce31caef9e2af20a4 Mon Sep 17 00:00:00 2001 From: 100gle Date: Wed, 27 Sep 2023 09:50:40 +0800 Subject: [PATCH 02/10] feat: make docs be more readable --- .../guides/integrations-guide/cloudflare.mdx | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index 36d3572ac04dc..6693536086a5e 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -72,21 +72,22 @@ export default defineConfig({ 要为每个页面编译一个单独的 bundle,请在 Cloudflare 适配器配置中设置 `functionPerPath` 选项。该选项需要手动维护 `functions` 文件夹。Astro 发出的文件将覆盖具有相同名称的现有 `functions` 文件,因此你必须为手动添加的每个文件选择唯一的文件名。此外,适配器永远不会清空 `functions` 文件夹中的过时文件,因此当你删除页面时,必须手动清理该文件夹。 -```diff +```js ins={8} +// astro.config.mjs import {defineConfig} from "astro/config"; import cloudflare from '@astrojs/cloudflare'; export default defineConfig({ adapter: cloudflare({ mode: 'directory', -+ functionPerRoute: true + functionPerRoute: true }) }) ``` 请注意,此适配器不支持使用 [Cloudflare 页面中间件](https://developers.cloudflare.com/pages/platform/functions/middleware/)。Astro 将会把 [Astro 中间件](/zh-cn/guides/middleware/) 打包到每个页面中。 -### routes.strategy +### `routes.strategy` `routes.strategy: "auto" | "include" | "exclude"` @@ -96,8 +97,8 @@ export default defineConfig({ 这有三个选项可供选择: -* **`"auto"`(默认):**自动选择生成最少条目的策略。这通常应该够用了,除非你有某些理由要选择其他选项。 -* **`include`:** 不会被预渲染的页面和端点将会被列为 `include` 条目,并告诉 Cloudflare 将这些路由作为函数调用。而 `exclude` 条目仅用于解决冲突。通常情况下,如果你的网站大多数是静态页面,只有少数动态页面或端点时,这将是最好的策略。 +* **`"auto"`(默认)**:自动选择生成最少条目的策略。这通常应该够用了,除非你有某些理由要选择其他选项。 +* **`include`**:不会被预渲染的页面和端点将会被列为 `include` 条目,并告诉 Cloudflare 将这些路由作为函数调用。而 `exclude` 条目仅用于解决冲突。通常情况下,如果你的网站大多数是静态页面,只有少数动态页面或端点时,这将是最好的策略。 示例:对于 `src/pages/index.astro`(静态),`src/pages/company.astro`(静态),`src/pages/users/faq.astro`(静态),以及 `/src/pages/users/[id].astro` (SSR),将产生以下 `_routes.json`: @@ -140,7 +141,7 @@ export default defineConfig({ } ``` -### routes.include +### `routes.include` `routes.include: string[]` @@ -148,7 +149,7 @@ export default defineConfig({ 如果你想使用自动生成的 `_routes.json`,但又想要包含额外的路由(例如,当你有自定义函数在 `functions` 文件夹中时),那么你可以使用 `routes.include` 选项将额外的路由添加到 `include` 数组中。 -### routes.exclude +### `routes.exclude` `routes.exclude: string[]` @@ -158,16 +159,16 @@ export default defineConfig({ 以下示例自动生成了 `_routes.json`,同时包含和排除额外的路由。请注意,如果你在 `functions` 文件夹中有自定义函数,那么这些函数将不会被 Astro 处理。 -```diff +```js ins={5-9} // astro.config.mjs export default defineConfig({ adapter: cloudflare({ mode: 'directory', -+ routes: { -+ strategy: 'include', -+ include: ['/users/*'], // 由自定义函数处理:functions/users/[id].js -+ exclude: ['/users/faq'], // 由静态页面处理:pages/users/faq.astro -+ }, + routes: { + strategy: 'include', + include: ['/users/*'], // 由自定义函数处理:functions/users/[id].js + exclude: ['/users/faq'], // 由静态页面处理:pages/users/faq.astro + }, }), }); ``` From 116fe7555f18867d7b17e622d7cb85f170fb8f6b Mon Sep 17 00:00:00 2001 From: Xiaoyue Lin <36526527+100gle@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:42:44 +0800 Subject: [PATCH 03/10] Update src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 李瑞丰 --- src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index 6693536086a5e..d2006f6a98433 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -332,7 +332,7 @@ export async function GET(context) { } ``` -虽然这个例子很简单,但是 Wasm 用来加速在不涉及大量 I/O 的情况下的计算密集型操作,比如嵌入图像处理库。 +虽然这个例子很简单,但是 Wasm 可以用来加速在不涉及大量 I/O 的情况下的计算密集型操作,比如嵌入图像处理库。 ## 标头、重定向和函数调用路由 From 1f11672481c8d32bb2769ac97e93cf25864e9388 Mon Sep 17 00:00:00 2001 From: 100gle Date: Wed, 27 Sep 2023 10:47:19 +0800 Subject: [PATCH 04/10] chore: update content --- .../docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index d2006f6a98433..cedbe5c349dbf 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -301,14 +301,14 @@ export default defineConfig({ 将 `wasmModuleImports: true` 添加到 `astro.config.mjs` 以在 Cloudflare 构建和 Astro 开发服务器中启用该功能。 -```diff +```js ins={7} // astro.config.mjs import {defineConfig} from "astro/config"; import cloudflare from '@astrojs/cloudflare'; export default defineConfig({ adapter: cloudflare({ -+ wasmModuleImports: true + wasmModuleImports: true }), output: 'server' }) @@ -322,7 +322,7 @@ export default defineConfig({ // pages/add/[a]/[b].js import mod from '../util/add.wasm?module'; -// instantiate ahead of time to share module +// 在使用之前实例化 const addModule: any = new WebAssembly.Instance(mod); export async function GET(context) { From b1e16d91fdca431629e93825806a141641db7292 Mon Sep 17 00:00:00 2001 From: 100gle Date: Wed, 27 Sep 2023 10:49:05 +0800 Subject: [PATCH 05/10] chore: update content --- src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index cedbe5c349dbf..de3e6293d7209 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -308,7 +308,7 @@ import cloudflare from '@astrojs/cloudflare'; export default defineConfig({ adapter: cloudflare({ - wasmModuleImports: true + wasmModuleImports: true }), output: 'server' }) From f0e68d9336f76f33de587487488ce6e392c020cf Mon Sep 17 00:00:00 2001 From: Xiaoyue Lin <36526527+100gle@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:06:58 +0800 Subject: [PATCH 06/10] Update src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx Co-authored-by: Genteure --- src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index de3e6293d7209..cd7c2831679e9 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -147,7 +147,7 @@ export default defineConfig({ 默认值:`[]` -如果你想使用自动生成的 `_routes.json`,但又想要包含额外的路由(例如,当你有自定义函数在 `functions` 文件夹中时),那么你可以使用 `routes.include` 选项将额外的路由添加到 `include` 数组中。 +如果你想使用自动生成的 `_routes.json`,但又想要包含额外的路由(例如,当你在 `functions` 文件夹中有自定义函数时),那么你可以使用 `routes.include` 选项将额外的路由添加到 `include` 数组中。 ### `routes.exclude` From a0e1c2da81c097b96d6d20d182bd464a22146174 Mon Sep 17 00:00:00 2001 From: Xiaoyue Lin <36526527+100gle@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:10:07 +0800 Subject: [PATCH 07/10] Update src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx Co-authored-by: Genteure --- src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index cd7c2831679e9..3cda8bd99e8fd 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -316,7 +316,7 @@ export default defineConfig({ 启用之后,你可以在 Astro 中通过 `.wasm?module` 语法来导入一个 WebAssembly。 -以下是导入一个 Wasm 模块的示例,该模块通过将请求的数字参数相加来返回响应: +以下是导入一个 Wasm 模块的示例,该模块返回了请求的数字参数的和: ```javascript // pages/add/[a]/[b].js From 8304152a7b4174e9746f480440c574f619f2af7b Mon Sep 17 00:00:00 2001 From: Xiaoyue Lin <36526527+100gle@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:10:23 +0800 Subject: [PATCH 08/10] Update src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx Co-authored-by: Genteure --- src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index 3cda8bd99e8fd..4338f3ec6637b 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -322,7 +322,7 @@ export default defineConfig({ // pages/add/[a]/[b].js import mod from '../util/add.wasm?module'; -// 在使用之前实例化 +// 预先初始化以共享同一个模块 const addModule: any = new WebAssembly.Instance(mod); export async function GET(context) { From cc922ef8dbf021060e7f0e6b5511f72606cf6fc4 Mon Sep 17 00:00:00 2001 From: Xiaoyue Lin <36526527+100gle@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:00:44 +0800 Subject: [PATCH 09/10] Update src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx Co-authored-by: Genteure --- src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index 4338f3ec6637b..ec930d1189cfd 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -297,7 +297,7 @@ export default defineConfig({ 默认值:`false` -不论是否直接导入 `.wasm` 文件,都会将其视作 ES 模块。 +是否将 `.wasm` 文件[直接作为 ES 模块](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration)导入。 将 `wasmModuleImports: true` 添加到 `astro.config.mjs` 以在 Cloudflare 构建和 Astro 开发服务器中启用该功能。 From 72d8ff9d3a3ebb43042e0fffc302b0ef631a290d Mon Sep 17 00:00:00 2001 From: 100gle Date: Wed, 27 Sep 2023 19:14:23 +0800 Subject: [PATCH 10/10] Revert "feat: make docs be more readable" This reverts commit c7bff9f9601d39fa9e5d7e4ce31caef9e2af20a4. --- .../guides/integrations-guide/cloudflare.mdx | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx index ec930d1189cfd..d575340dbbc0e 100644 --- a/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx +++ b/src/content/docs/zh-cn/guides/integrations-guide/cloudflare.mdx @@ -72,15 +72,14 @@ export default defineConfig({ 要为每个页面编译一个单独的 bundle,请在 Cloudflare 适配器配置中设置 `functionPerPath` 选项。该选项需要手动维护 `functions` 文件夹。Astro 发出的文件将覆盖具有相同名称的现有 `functions` 文件,因此你必须为手动添加的每个文件选择唯一的文件名。此外,适配器永远不会清空 `functions` 文件夹中的过时文件,因此当你删除页面时,必须手动清理该文件夹。 -```js ins={8} -// astro.config.mjs +```diff import {defineConfig} from "astro/config"; import cloudflare from '@astrojs/cloudflare'; export default defineConfig({ adapter: cloudflare({ mode: 'directory', - functionPerRoute: true ++ functionPerRoute: true }) }) ``` @@ -159,16 +158,16 @@ export default defineConfig({ 以下示例自动生成了 `_routes.json`,同时包含和排除额外的路由。请注意,如果你在 `functions` 文件夹中有自定义函数,那么这些函数将不会被 Astro 处理。 -```js ins={5-9} +```diff // astro.config.mjs export default defineConfig({ adapter: cloudflare({ mode: 'directory', - routes: { - strategy: 'include', - include: ['/users/*'], // 由自定义函数处理:functions/users/[id].js - exclude: ['/users/faq'], // 由静态页面处理:pages/users/faq.astro - }, ++ routes: { ++ strategy: 'include', ++ include: ['/users/*'], // 由自定义函数处理:functions/users/[id].js ++ exclude: ['/users/faq'], // 由静态页面处理:pages/users/faq.astro ++ }, }), }); ```