Skip to content

Static prerender (getStaticPaths + getEmDashCollection) fails at build: live-collections pipeline bundles the native DB driver #1385

@sam-fakhreddine

Description

@sam-fakhreddine

Summary

The docs (Querying Content → "Static vs. Server Rendering", and coming-from/astro) advertise static prerendering via getStaticPaths() + getEmDashCollection()/getEmDashEntry(). In practice this fails at build time. getEmDashCollection() returns { entries: [], error } where the error message is Failed to load collection: __filename is not defined (and a cascade of follow-on errors once that's addressed). Calling the underlying loader directly (emdashLoader().loadCollection(...) from emdash/runtime) works fine in the same build — so the failure is specific to the path through Astro's Live Content Collections (getLiveCollection from astro:content), which is what getEmDashCollection is built on.

Environment

  • emdash 0.17.x (emdash, @emdash-cms/cloudflare, @emdash-cms/auth-atproto)
  • astro 6.4.x, @astrojs/node adapter (standalone), output: "server" with public pages marked export const prerender = true (hybrid prerender)
  • database: sqlite({ url: "file:..." }) pointing at a populated local DB
  • pnpm (strict, non-hoisted node_modules)

Root cause (what we traced)

getEmDashCollectiongetLiveCollection("_emdash", …) → the live loader registered in src/live.config.ts. Astro's live-content-collections build pipeline bundles emdash's loader (emdash is in the integration's ssr.noExternal), but that bundling does NOT honor the integration's ssr.external (NODE_NATIVE_EXTERNALS = ["better-sqlite3","bindings","file-uri-to-path","@libsql/kysely-libsql","pg"]). So the native better-sqlite3/bindings chain gets inlined into the prerender bundle and breaks. The error cascade when you peel it back:

  1. __filename is not defined (CJS global absent in the ESM prerender bundle — bindings uses it)
  2. with a __filename/__dirnameimport.meta shim: Could not dynamically require ".../better_sqlite3.node" (Rollup/@rollup/plugin-commonjs cannot inline a native .node addon)
  3. externalizing better-sqlite3 in build.rollupOptions.external: Cannot find package 'better-sqlite3' imported from dist/server/.prerender/chunks/… (it's a transitive dep of emdash, so it isn't resolvable from the project root under pnpm's strict layout)

Notably the SSR server bundle DOES externalize better-sqlite3 correctly (import BetterSqlite3 from 'better-sqlite3'); only the .prerender chunk path mishandles it.

Workaround that makes static prerender succeed

In the consuming app's astro.config.mjs (node-adapter static target only):

  • build.rollupOptions.external: ["better-sqlite3","bindings","file-uri-to-path"]
  • define: { __filename: "import.meta.filename", __dirname: "import.meta.dirname" }
  • add better-sqlite3 as a DIRECT dependency (so it resolves when externalized under pnpm)

With those three, getEmDashCollection returns populated entries at build time and all locales prerender to static HTML correctly.

Ask

Either (a) have the live-collections build path honor the integration's ssr.external (so the native driver stays external in the .prerender bundle), or (b) document the required rollupOptions.external + direct-dependency steps in the "Static vs. Server Rendering" guide. Today the documented static path doesn't work out of the box with the sqlite driver.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions