Created
March 17, 2024 14:04
-
-
Save dac09/38a87dc1fb04b852f0008b9945cbf51f to your computer and use it in GitHub Desktop.
How I modified the streaming server to build with client conditions and "redirect" server imports.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fs from 'node:fs' | |
import path from 'node:path' | |
import { build as viteBuild } from 'vite' | |
import { cjsInterop } from 'vite-plugin-cjs-interop' | |
import { getPaths } from '@redwoodjs/project-config' | |
export async function buildForStreamingServer({ | |
verbose = false, | |
clientEntryFiles, | |
serverEntryFiles, | |
}: { | |
verbose?: boolean | |
clientEntryFiles: Record<string, string> | |
serverEntryFiles: Record<string, string> | |
}) { | |
console.log('Starting streaming server build...\n') | |
const rwPaths = getPaths() | |
const rscBuildManifest: Record<string, any> = JSON.parse( | |
fs.readFileSync( | |
path.join(rwPaths.web.distRsc, 'server-build-manifest.json'), | |
'utf-8', | |
), | |
) | |
const serverEntriesPaths = Object.values(serverEntryFiles) | |
if (!rwPaths.web.viteConfig) { | |
throw new Error('Vite config not found') | |
} | |
await viteBuild({ | |
configFile: rwPaths.web.viteConfig, | |
plugins: [ | |
cjsInterop({ | |
dependencies: ['@redwoodjs/**'], | |
}), | |
{ | |
name: 'rw-resolve-redirect', | |
enforce: 'pre', | |
async resolveId(source, importer, _options) { | |
// Not sure how this is possible but TS says so | |
if (!importer) { | |
return null | |
} | |
// @TODO: ignore node_modules, this seems like a lot of processing otherwise | |
// Step 1: create path for lookup | |
const absPath = path.join(path.parse(importer).dir, source) | |
// Only do it for files with "use server" in src, ignore node_modules | |
// @MARK @TODO Temporary!!!! | |
const absPathWithHackedExtension = absPath + '.ts' | |
if ( | |
!serverEntriesPaths.includes(absPathWithHackedExtension) || | |
absPath.includes('node_modules') | |
) { | |
return null | |
} | |
const relToSrc = path.relative( | |
rwPaths.web.src, | |
absPathWithHackedExtension, | |
) | |
// Step 2: lookup in the manifest | |
// const manifest = await getManifest() | |
const fileId = rscBuildManifest[relToSrc].file | |
// Step 3, return fileId and external: true | |
return { | |
id: path.join('../../rsc', fileId), | |
external: true, | |
} | |
}, | |
}, | |
], | |
build: { | |
rollupOptions: { | |
input: { | |
...clientEntryFiles, | |
entries: rwPaths.web.entries as string, | |
}, | |
}, | |
outDir: rwPaths.web.distServer, | |
ssr: true, | |
emptyOutDir: true, | |
}, | |
ssr: { | |
noExternal: /^(?!node:)/, | |
// Can't inline prisma client | |
external: ['@prisma/client'], | |
}, | |
envFile: false, | |
logLevel: verbose ? 'info' : 'warn', | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What this is effectively achieving:
We then need to launch the server with: