Common Base Project

    11. Refactor into worker

    Members only · Non-members can read 30% of the article.

    Published
    May 17, 2025
    Reading Time
    7 min read
    Author
    Felix
    Access
    Members only
    Preview only

    Non-members can read 30% of the article.

    Chapter Tag

    Basic configuration process

    Refactoring the Next.js application into Cloudflare Worker requires some of the following configurations and operations, but in fact the code has been written in Tag, I just talk about the process.

    Download dependencies, modify configuration files, and add scripts

    First execute pnpm add @opennextjs/cloudflare, and then complete the configuration of wrangler.jsonc. This part of the configuration will be automatically bound when uploaded to Cloudflare.

    The refactored configurations are these:

    {
      "$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: points to the JSON Schema of the configuration file, providing editor auto-completion function.

    • name: The name of the Worker. This will be the name your Worker displays in the Cloudflare console and is part of the subdomain name used when accessing the Worker.

    • main: Worker's entry file. For OpenNext projects, this is usually the .open-next/worker.js file generated after building.

    • compatibility_date: Specifies the date of the Worker runtime version. Cloudflare will use this date to determine which version of the Workers runtime to use.

    • compatibility_flags: Enable Node.js compatibility layer and public URL request function

    • observability: Enable logging to view running logs in the Cloudflare console

    • assets: configure static resources

      • directory: static resource directory
      • binding: The variable name used to access resources in Worker is also the variable name we write in the environment.
    • ai: Binds Cloudflare AI service, which can be used for text generation, image processing and other AI functions

    • r2_buckets: Configure R2 buckets

      • bucket_name: bucket name
      • binding: Create a binding named NEXT_INC_CACHE_R2_BUCKET for incremental caching of Next.js
    • durable_objects: configure stateful storage service

      • NEXT_CACHE_DO_QUEUE: handle Next.js cache queue
      • NEXT_TAG_CACHE_DO_SHARDED: Handle Next.js tag cache
    • migrations: Create SQLite database for Durable Objects

    • services: This configuration allows the Worker to reference itself, which is useful in certain scenarios that require the Worker to call itself, such as implementing some recursive operations or distributed processing.

    Add the following scripts to package.json to simplify the development and deployment process:

    "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"
    }
    

    These commands are used for:

    • preview: Build the application and preview it when running on local Workers, allowing you to quickly preview the application with a single command
    • deploy: Build and immediately deploy to Cloudflare
    • upload: Build and upload new versions to Cloudflare
    • cf-typegen: Generate cloudflare-env.d.ts file containing env type in the project root directory

    Then run pnpm cf-typegen to automatically generate the project type. This command can be called every time a new bound service is added to generate the type and facilitate syntax prompts.

    Configuration file settings

    Although @opennextjs/cloudflare will automatically create the configuration file during the build process if it does not exist, you can also create it yourself. In addition to the wrangler.jsonc configuration above, you also need to create an open-next.config.ts file:

    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
    })
    

    This configuration enables Cloudflare's cache to support Nextjs's caching function.

    Static resource cache optimization

    Create public/_headers file and add cache control:

    /_next/static/*
      Cache-Control: public,max-age=31536000,immutable
    

    This ensures that static resources are properly cached and improves loading speed. For more information, please refer to the static resource caching documentation.

    Modify Next.js configuration

    Update the next.config.ts file to add Cloudflare development integration:

    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)
    

    After adding the initOpenNextCloudflareForDev() call, you can access the local version of the Cloudflare binding during local development, as described in the binding documentation.

    We also added the npm run preview command in step 3, which allows you to quickly preview your app while the Workers are running instead of in Node.js. This enables you to test changes in the same runtime as when deployed to Cloudflare.

    Replace removal code

    • Remove any export const runtime = "edge"; declarations because @opennextjs/cloudflare does not support edge runtime.
    • Remove the @cloudflare/next-on-pages package.
    • Replace getRequestContext in @cloudflare/next-on-pages with getCloudflareContext in @opennextjs/cloudflare

    Deployment

    • Through Push, CL will complete the deployment by itself.
    • pnpm deploy:c will read the local .env file for deployment.

    How Cloudflare implements Nextjs caching

    Next, let’s talk about the principle source code. This part of the content can be read or not. This is to satisfy my curiosity about technology and my sense of security in using a new technology.

    Official simple document

    Next.js provides several ways to improve application performance by caching routes and network requests. The application attempts to pre-render and cache as much data as possible at build time to reduce the amount of work required to provide a response to the user.

    Cache data is updated via revalidation, either periodically or on demand:

    • Time-based revalidation: Updates cached data after the application-specified revalidation delay has expired
    • Revalidate on Demand: Allows invalidating cache entries by a specific tag (via revalidateTag) or at a given path (via revalidatePath).

    The caching support of @opennextjs/cloudflare relies on 3 components:

    1. Incremental Cache: Store cached data
    2. Queue: Synchronization and deduplication time-based re-validation
    3. Tag Cache: used for on-demand revalidation through revalidateTag and revalidatePath

    Cache implementation

    For the implementation of these three, I use:

    R2 incremental cache implementation principle

    R2 delta cache is Next.js' primary mechanism for storing cached data in a Cloudflare environment. It leverages Cloudflare's R2 object storage service to provide high-performance, low-cost data storage solutions.

    Members only

    Subscribe to unlock the full article

    Support the writing, unlock every paragraph, and receive future updates instantly.

    Comments

    Join the conversation

    0 comments
    Sign in to comment

    No comments yet. Be the first to add one.