Claude-skill-registry Dynamic Imports

Why and how to use dynamic imports in LivestockAI server functions for Cloudflare Workers compatibility

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dynamic-imports" ~/.claude/skills/majiayu000-claude-skill-registry-dynamic-imports && rm -rf "$T"
manifest: skills/data/dynamic-imports/SKILL.md
source content

Dynamic Imports

LivestockAI requires dynamic imports in server functions for Cloudflare Workers compatibility. This skill explains the pattern and why it's necessary.

The Problem

Cloudflare Workers doesn't support

process.env
at module load time. Environment variables are only available through the
env
binding from
cloudflare:workers
, and that binding is only accessible during request handling.

// ❌ This fails on Cloudflare Workers
// The import runs at module load time, before env is available
import { db } from '~/lib/db'

export const fn = createServerFn().handler(async () => {
  return db.selectFrom('users').execute() // db is undefined or throws
})

The Solution

Use dynamic imports inside the handler function:

// ✅ This works on Cloudflare Workers
export const fn = createServerFn().handler(async () => {
  const { getDb } = await import('~/lib/db')
  const db = await getDb()
  return db.selectFrom('users').execute()
})

The
getDb()
Function

The

getDb()
function in
app/lib/db/index.ts
handles environment detection:

async function getDatabaseUrl(): Promise<string | undefined> {
  // Try process.env first (Node.js, Bun, Vite dev server)
  if (typeof process !== 'undefined' && process.env?.DATABASE_URL) {
    return process.env.DATABASE_URL
  }

  // Fall back to Cloudflare Workers env binding
  try {
    const { env } = await import('cloudflare:workers')
    return env.DATABASE_URL
  } catch {
    return undefined
  }
}

export async function getDb(): Promise<Kysely<Database>> {
  if (!dbInstance) {
    const databaseUrl = await getDatabaseUrl()
    if (!databaseUrl) {
      throw new Error('DATABASE_URL not set')
    }
    dbInstance = new Kysely<Database>({
      dialect: new NeonDialect({ neon: neon(databaseUrl) }),
    })
  }
  return dbInstance
}

When to Use Dynamic Imports

Server Functions (ALWAYS)

export const createBatchFn = createServerFn({ method: 'POST' })
  .inputValidator(schema)
  .handler(async ({ data }) => {
    // Dynamic import for auth
    const { requireAuth } = await import('../auth/server-middleware')
    const session = await requireAuth()

    // Dynamic import for database
    const { getDb } = await import('~/lib/db')
    const db = await getDb()

    // Dynamic import for utilities that need env
    const { checkFarmAccess } = await import('../auth/utils')
    await checkFarmAccess(session.user.id, data.farmId)

    return insertBatch(db, data)
  })

CLI Scripts (NOT NEEDED)

For seeders, migrations, and CLI scripts running in Node.js/Bun, use static imports:

// seeders/production.ts - runs in Node.js/Bun
import { db } from '~/lib/db'

await db.insertInto('users').values({...}).execute()

Common Patterns

Auth Middleware

const { requireAuth } = await import('../auth/server-middleware')
const session = await requireAuth()

Farm Access Check

const { checkFarmAccess, getUserFarms } = await import('../auth/utils')
const hasAccess = await checkFarmAccess(userId, farmId)

Database Operations

const { getDb } = await import('~/lib/db')
const db = await getDb()

Anti-Patterns

// ❌ Static import of db
import { db } from '~/lib/db'

// ❌ Old pattern - doesn't work
const { db } = await import('~/lib/db')

// ❌ Accessing process.env directly
const url = process.env.DATABASE_URL

Performance Note

Dynamic imports are cached by the JavaScript runtime. The first import loads the module, subsequent imports return the cached module. The

getDb()
function also maintains a singleton database instance.

Related Skills

  • neon-database
    - Database connection details
  • cloudflare-workers
    - Deployment environment
  • tanstack-start
    - Server function patterns