Skip to content

Commit

Permalink
RSC: Refactor to share buildRouteManifest function with SSR process (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobbe committed Dec 4, 2023
1 parent 03eaa0c commit 00462e5
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 140 deletions.
90 changes: 8 additions & 82 deletions packages/vite/src/buildFeServer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import fs from 'fs/promises'
import path from 'path'

import type { PluginBuild } from 'esbuild'
import { build as esbuildBuild } from 'esbuild'
import type { Manifest as ViteBuildManifest } from 'vite'
import { build as viteBuild } from 'vite'

import {
Expand All @@ -12,11 +8,10 @@ import {
} from '@redwoodjs/babel-config'
import { buildWeb } from '@redwoodjs/internal/dist/build/web'
import { findRouteHooksSrc } from '@redwoodjs/internal/dist/files'
import { getProjectRoutes } from '@redwoodjs/internal/dist/routes'
import { getAppRouteHook, getConfig, getPaths } from '@redwoodjs/project-config'
import { getConfig, getPaths } from '@redwoodjs/project-config'

import { buildRouteManifest } from './buildRouteManifest'
import { buildRscFeServer } from './buildRscFeServer'
import type { RWRouteManifest } from './types'
import { ensureProcessDirWeb } from './utils'

export interface BuildOptions {
Expand Down Expand Up @@ -51,16 +46,18 @@ export const buildFeServer = async ({ verbose, webDir }: BuildOptions = {}) => {
throw new Error('RSC entries file not found')
}

return await buildRscFeServer({
await buildRscFeServer({
viteConfigPath,
webSrc: rwPaths.web.src,
webHtml: rwPaths.web.html,
entries: rwPaths.web.entries,
webDist: rwPaths.web.dist,
webDistServer: rwPaths.web.distServer,
webDistServerEntries: rwPaths.web.distServerEntries,
webRouteManifest: rwPaths.web.routeManifest,
})

// Write a route manifest
return await buildRouteManifest()
}

// Step 1A: Generate the client bundle
Expand Down Expand Up @@ -118,77 +115,6 @@ export const buildFeServer = async ({ verbose, webDir }: BuildOptions = {}) => {
outdir: rwPaths.web.distRouteHooks,
})

// Step 3: Generate route-manifest.json

// TODO When https://github.com/tc39/proposal-import-attributes and
// https://github.com/microsoft/TypeScript/issues/53656 have both landed we
// should try to do this instead:
// const clientBuildManifest: ViteBuildManifest = await import(
// path.join(getPaths().web.dist, 'client-build-manifest.json'),
// { with: { type: 'json' } }
// )
// NOTES:
// * There's a related babel plugin here
// https://babeljs.io/docs/babel-plugin-syntax-import-attributes
// * Included in `preset-env` if you set `shippedProposals: true`
// * We had this before, but with `assert` instead of `with`. We really
// should be using `with`. See motivation in issues linked above.
// * With `assert` and `@babel/plugin-syntax-import-assertions` the
// code compiled and ran properly, but Jest tests failed, complaining
// about the syntax.
const manifestPath = path.join(
getPaths().web.dist,
'client-build-manifest.json'
)
const buildManifestStr = await fs.readFile(manifestPath, 'utf-8')
const clientBuildManifest: ViteBuildManifest = JSON.parse(buildManifestStr)

const routesList = getProjectRoutes()

const routeManifest = routesList.reduce<RWRouteManifest>((acc, route) => {
acc[route.pathDefinition] = {
name: route.name,
bundle: route.relativeFilePath
? clientBuildManifest[route.relativeFilePath]?.file ?? null
: null,
matchRegexString: route.matchRegexString,
// @NOTE this is the path definition, not the actual path
// E.g. /blog/post/{id:Int}
pathDefinition: route.pathDefinition,
hasParams: route.hasParams,
routeHooks: FIXME_constructRouteHookPath(route.routeHooks),
redirect: route.redirect
? {
to: route.redirect?.to,
permanent: false,
}
: null,
renderMode: route.renderMode,
}

return acc
}, {})

await fs.writeFile(
rwPaths.web.routeManifest,
JSON.stringify(routeManifest, null, 2)
)
}

// TODO (STREAMING) Hacky work around because when you don't have a App.routeHook, esbuild doesn't create
// the pages folder in the dist/server/routeHooks directory.
// @MARK need to change to .mjs here if we use esm
const FIXME_constructRouteHookPath = (rhSrcPath: string | null | undefined) => {
const rwPaths = getPaths()
if (!rhSrcPath) {
return null
}

if (getAppRouteHook()) {
return path.relative(rwPaths.web.src, rhSrcPath).replace('.ts', '.js')
} else {
return path
.relative(path.join(rwPaths.web.src, 'pages'), rhSrcPath)
.replace('.ts', '.js')
}
// Write a route manifest
await buildRouteManifest()
}
92 changes: 92 additions & 0 deletions packages/vite/src/buildRouteManifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import fs from 'fs/promises'
import path from 'path'

import type { Manifest as ViteBuildManifest } from 'vite'

import { getProjectRoutes } from '@redwoodjs/internal/dist/routes'
import { getAppRouteHook, getPaths } from '@redwoodjs/project-config'

import type { RWRouteManifest } from './types'

/**
* RSC build. Step 6.
* Generate a route manifest file for the web server side.
*/
export async function buildRouteManifest() {
const webRouteManifest = getPaths().web.routeManifest

// TODO When https://github.com/tc39/proposal-import-attributes and
// https://github.com/microsoft/TypeScript/issues/53656 have both landed we
// should try to do this instead:
// const clientBuildManifest: ViteBuildManifest = await import(
// path.join(getPaths().web.dist, 'client-build-manifest.json'),
// { with: { type: 'json' } }
// )
// NOTES:
// * There's a related babel plugin here
// https://babeljs.io/docs/babel-plugin-syntax-import-attributes
// * Included in `preset-env` if you set `shippedProposals: true`
// * We had this before, but with `assert` instead of `with`. We really
// should be using `with`. See motivation in issues linked above.
// * With `assert` and `@babel/plugin-syntax-import-assertions` the
// code compiled and ran properly, but Jest tests failed, complaining
// about the syntax.
const manifestPath = path.join(
getPaths().web.dist,
'client-build-manifest.json'
)
const buildManifestStr = await fs.readFile(manifestPath, 'utf-8')
const clientBuildManifest: ViteBuildManifest = JSON.parse(buildManifestStr)

const routesList = getProjectRoutes()

const routeManifest = routesList.reduce<RWRouteManifest>((acc, route) => {
acc[route.pathDefinition] = {
name: route.name,
bundle: route.relativeFilePath
? clientBuildManifest[route.relativeFilePath]?.file ?? null
: null,
matchRegexString: route.matchRegexString,
// NOTE this is the path definition, not the actual path
// E.g. /blog/post/{id:Int}
pathDefinition: route.pathDefinition,
hasParams: route.hasParams,
routeHooks: FIXME_constructRouteHookPath(route.routeHooks),
redirect: route.redirect
? {
to: route.redirect?.to,
permanent: false,
}
: null,
renderMode: route.renderMode,
}

return acc
}, {})

console.log('routeManifest', JSON.stringify(routeManifest, null, 2))

return fs.writeFile(webRouteManifest, JSON.stringify(routeManifest, null, 2))
}

// TODO (STREAMING) Hacky work around because when you don't have a App.routeHook, esbuild doesn't create
// the pages folder in the dist/server/routeHooks directory.
// @MARK need to change to .mjs here if we use esm
const FIXME_constructRouteHookPath = (
routeHookSrcPath: string | null | undefined
) => {
const rwPaths = getPaths()
if (!routeHookSrcPath) {
return null
}

if (getAppRouteHook()) {
return path
.relative(rwPaths.web.src, routeHookSrcPath)
.replace('.ts', '.js')
} else {
return path
.relative(path.join(rwPaths.web.src, 'pages'), routeHookSrcPath)
.replace('.ts', '.js')
}
}
6 changes: 0 additions & 6 deletions packages/vite/src/buildRscFeServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { rscBuildAnalyze } from './rsc/rscBuildAnalyze'
import { rscBuildClient } from './rsc/rscBuildClient'
import { rscBuildClientEntriesMappings } from './rsc/rscBuildClientEntriesFile'
import { rscBuildCopyCssAssets } from './rsc/rscBuildCopyCssAssets'
import { rscBuildRouteManifest } from './rsc/rscBuildRouteManifest'
import { rscBuildServer } from './rsc/rscBuildServer'

interface Args {
Expand All @@ -13,7 +12,6 @@ interface Args {
webDist: string
webDistServer: string
webDistServerEntries: string
webRouteManifest: string
}

export const buildRscFeServer = async ({
Expand All @@ -24,7 +22,6 @@ export const buildRscFeServer = async ({
webDist,
webDistServer,
webDistServerEntries,
webRouteManifest,
}: Args) => {
// Analyze all files and generate a list of RSCs and RSFs
const { clientEntryFiles, serverEntryFiles } = await rscBuildAnalyze(
Expand Down Expand Up @@ -57,7 +54,4 @@ export const buildRscFeServer = async ({
clientEntryFiles,
webDistServerEntries
)

// Write a route manifest
await rscBuildRouteManifest(webRouteManifest)
}
52 changes: 0 additions & 52 deletions packages/vite/src/rsc/rscBuildRouteManifest.ts

This file was deleted.

0 comments on commit 00462e5

Please sign in to comment.