通用基础项目

    11. 重构为worker

    会员专享 · 非会员仅可阅读 30% 的正文。

    发布时间
    May 17, 2025
    阅读时间
    7 min read
    作者
    Felix
    访问
    会员专享
    这是预览内容

    非会员仅可阅读 30% 的正文。

    章节Tag

    基础配置流程

    将Next.js应用重构为Cloudflare Worker需要一些下面的配置和操作,但其实代码已经写好了在Tag里,只是讲一下过程。

    下载依赖、修改配置文件、添加脚本

    首先执行pnpm add @opennextjs/cloudflare,紧接着完成wrangler.jsonc的配置,这部分配置会在上传到Cloudflare的时候自动完成绑定。

    重构的配置是这些:

    {
      "$schema": "node_modules/wrangler/config-schema.json",
      "name": "cloudflare-template",
      "main": ".open-next/worker.js",
      "compatibility_date": "2025-04-22",
      "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
      "observability": {
        "logs": {
          "enabled": true
        }
      },
      "assets": {
        "directory": ".open-next/assets",
        "binding": "ASSETS"
      },
      "ai": {
        "binding": "AI"
      },
      "r2_buckets": [
        {
          "bucket_name": "demo",
          "binding": "NEXT_INC_CACHE_R2_BUCKET"
        }
      ],
      "durable_objects": {
        "bindings": [
          {
            "name": "NEXT_CACHE_DO_QUEUE",
            "class_name": "DOQueueHandler"
          },
          {
            "name": "NEXT_TAG_CACHE_DO_SHARDED",
            "class_name": "DOShardedTagCache"
          }
        ]
      },
      "migrations": [
        {
          "tag": "v1",
          "new_sqlite_classes": ["DOQueueHandler", "DOShardedTagCache"]
        }
      ],
      "services": [
        {
          "binding": "WORKER_SELF_REFERENCE",
          "service": "cloudflare-template"
        }
      ]
    }
    ```
    
    - `$schema`: 指向配置文件的JSON Schema,提供编辑器自动完成功能。
    - `name`: Worker的名称,这将是你的 Worker 在 Cloudflare 控制台中显示的名称,也是访问 Worker 时使用的子域名的一部分。
    - `main`: Worker的入口文件,对于 OpenNext 项目,这通常是构建后生成的 .open-next/worker.js 文件。
    - `compatibility_date`: 指定Worker运行时版本的日期,Cloudflare 会根据这个日期确定使用哪个版本的 Workers 运行时。
    - `compatibility_flags`: 启用Node.js兼容层和公共URL请求功能
    
    - `observability`: 启用日志记录,方便在Cloudflare控制台查看运行日志
    
    - `assets`: 配置静态资源
    
      - `directory`: 静态资源目录
      - `binding`: 在Worker中访问资源的变量名,也是我们在环境中写的变量名。
    
    - `ai`: 绑定Cloudflare AI服务,可用于文本生成、图像处理等AI功能
    
    - `r2_buckets`: 配置R2存储桶
    
      - `bucket_name`: 存储桶名称
      - `binding`: 创建一个名为 `NEXT_INC_CACHE_R2_BUCKET` 的绑定,用于 Next.js 的增量缓存
    
    - `durable_objects`: 配置有状态存储服务
    
      - `NEXT_CACHE_DO_QUEUE`: 处理Next.js缓存队列
      - `NEXT_TAG_CACHE_DO_SHARDED`: 处理Next.js标签缓存
    
    - `migrations`: 为Durable Objects创建SQLite数据库
    
    - `services`: 这个配置允许 Worker 引用自己,这在某些需要 Worker 调用自身的场景中很有用,比如实现某些递归操作或分布式处理。
    
    在package.json中添加以下脚本,简化开发和部署流程:
    
    ```json
    "scripts": {
      "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
      "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
      "upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload",
      "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
    }
    ```
    
    这些命令分别用于:
    
    - preview: 构建应用并在本地Workers运行时预览,让你通过单个命令快速预览应用
    - deploy: 构建并立即部署到Cloudflare
    - upload: 构建并上传新版本到Cloudflare
    - cf-typegen: 在项目根目录生成包含env类型的cloudflare-env.d.ts文件
    
    紧接着跑一下`pnpm cf-typegen`自动生成项目的类型,这个命令在每次新增绑定的服务的时候都可以调用一下,用于生成类型,便于语法提示。
    
    ### 配置文件设置
    
    虽然在构建过程中`@opennextjs/cloudflare`会自动创建配置文件(如果不存在),但你也可以自己创建。除了上面的`wrangler.jsonc`配置外,还需要创建一个`open-next.config.ts`文件:
    
    ```typescript
    import { defineCloudflareConfig } from '@opennextjs/cloudflare'
    import r2IncrementalCache from '@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache'
    import doQueue from '@opennextjs/cloudflare/overrides/queue/do-queue'
    import doShardedTagCache from '@opennextjs/cloudflare/overrides/tag-cache/do-sharded-tag-cache'
    
    export default defineCloudflareConfig({
      incrementalCache: r2IncrementalCache,
      tagCache: doShardedTagCache({ baseShardSize: 12, regionalCache: true }),
      queue: doQueue
    })
    ```
    
    这个配置是启用了Cloudflare的缓存以支持Nextjs的缓存功能。
    
    ### 静态资源缓存优化
    
    创建`public/_headers`文件,添加缓存控制:
    
    ```
    /_next/static/*
      Cache-Control: public,max-age=31536000,immutable
    ```
    
    这能确保静态资源得到适当缓存,提高加载速度。更多信息可以参考静态资源缓存文档。
    
    ### 修改Next.js配置
    
    更新`next.config.ts`文件,添加Cloudflare开发集成:
    
    ```typescript
    import { initOpenNextCloudflareForDev } from '@opennextjs/cloudflare'
    import { NextConfig } from 'next'
    import createNextIntlPlugin from 'next-intl/plugin'
    
    initOpenNextCloudflareForDev()
    
    const nextConfig: NextConfig = {
      devIndicators: false,
      experimental: {
        staleTimes: {
          dynamic: 3600,
          static: 3600
        }
      }
    }
    
    const withNextIntl = createNextIntlPlugin({
      experimental: {
        createMessagesDeclaration: './messages/en.json'
      }
    })
    export default withNextIntl(nextConfig)
    ```
    
    添加`initOpenNextCloudflareForDev()`调用后,你可以在本地开发过程中访问Cloudflare绑定的本地版本,如绑定文档中所述。
    
    我们在第3步中还添加了`npm run preview`命令,它允许你在Workers运行时而不是Node.js中快速预览应用。这使你能够在与部署到Cloudflare时相同的运行时中测试更改。
    
    ### 替换移除代码
    
    - 移除任何`export const runtime = "edge";`声明,因为@opennextjs/cloudflare不支持edge运行时。
    - 移除`@cloudflare/next-on-pages`这个包。
    - 用`@opennextjs/cloudflare`中的`getCloudflareContext`替换`@cloudflare/next-on-pages`中的`getRequestContext`
    
    ### 部署
    
    - 通过Push,CL会自己完成部署。
    - `pnpm deploy:c`会读取本地的`.env`文件进行部署。
    
    ## Cloudflare如何实现Nextjs的缓存
    
    > 接下来讲一下原理源码,这部分的内容是属于可看可不看的,这是满足我对技术的好奇心以及对使用一门新技术的安全感。
    
    [官方的简单文档](https://opennext.js.org/cloudflare/caching)
    
    Next.js提供了多种通过缓存路由和网络请求来提高应用性能的方法。应用程序会尝试在构建时预渲染并缓存尽可能多的数据,以减少向用户提供响应时所需的工作量。
    
    缓存数据通过重新验证进行更新,可以是定期的或按需的:
    
    - **基于时间的重新验证**:在应用程序指定的重新验证延迟过期后更新缓存数据
    - **按需重新验证**:允许通过特定标签(通过`revalidateTag`)或在给定路径(通过`revalidatePath`)使缓存条目无效。
    
    `@opennextjs/cloudflare`的缓存支持依赖于3个组件:
    
    1. **增量缓存(Incremental Cache)**:存储缓存数据
    2. **队列(Queue)**:同步和去重基于时间的重新验证
    3. **标签缓存(Tag Cache)**:用于通过`revalidateTag`和`revalidatePath`进行按需重新验证
    
    ### 缓存实现
    
    而对于这三者的实现我采用的是:
    
    - **增量缓存**:使用R2存储数据,[源码地址](https://github1s.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src/api/overrides/incremental-cache/r2-incremental-cache.ts)
    - **队列**:使用由Durable Objects实现的时间验证队列,[源码地址](https://github1s.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src/api/durable-objects/queue.ts)
    - **标签缓存**:使用由Durable Objects实现的缓存验证系统,[源码地址](https://github1s.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src/api/durable-objects/sharded-tag-cache.ts)
    
    ### R2增量缓存实现原理
    
    R2增量缓存是Next.js在Cloudflare环境中存储缓存数据的主要机制。它利用Cloudflare的R2对象存储服务,提供高性能、低成本的数据存储解决方案。
    
    R2增量缓存实现了标准的Next.js增量缓存接口,包括`get`、`set`和`delete`方法,使其能够无缝集成到Next.js的缓存系统中。
    
    核心实现代码如下:
    
    ```typescript
    class R2IncrementalCache implements IncrementalCache {
    会员专享

    订阅后解锁完整文章

    支持创作、解锁全文,未来更新也会第一时间送达。

    评论

    加入讨论

    0 条评论
    登录后评论

    还没有评论,来占个沙发吧。