Skip to content

Commit

Permalink
RSC: Fix server build root (#10076)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobbe authored Feb 29, 2024
1 parent fe30874 commit d83d52d
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 57 deletions.
75 changes: 19 additions & 56 deletions packages/babel-config/src/plugins/babel-plugin-redwood-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,18 @@ const EXPECTED_EXPORTS_FROM_CELL = [
]

export default function ({ types: t }: { types: typeof types }): PluginObj {
// This array will
// - collect exports from the Cell file during ExportNamedDeclaration
// This array will collect exports from the Cell file during
// ExportNamedDeclaration
// - collected exports will then be passed to `createCell`
// - be cleared after Program exit to prepare for the next file
// - The array is reset every time we `enter` a new Program
let exportNames: string[] = []
let hasDefaultExport = false

// TODO (RSC):
// This code relies on the fact that all cells first become client side
// cells. And then we do a second pass over all cells and transform them to
// server cells if applicable
// It'd be better if we could only do one pass over all cells. So the real
// todo here is to first figure out why we do two passes, and then update
// this code to directly generate `createCell` or `createServerCell` HoCs

return {
name: 'babel-plugin-redwood-cell',
visitor: {
ExportDefaultDeclaration(path) {
ExportDefaultDeclaration() {
hasDefaultExport = true

// This is for RSC cells:
// Determine if this is `export default createCell(...)`
// If it is, then we change it to `export default createServerCell(...)`
const declaration = path.node.declaration
if (
t.isCallExpression(declaration) &&
t.isIdentifier(declaration.callee) &&
declaration.callee.name === 'createCell'
) {
declaration.callee.name = 'createServerCell'
}
},
ExportNamedDeclaration(path) {
const declaration = path.node.declaration
Expand All @@ -85,34 +65,6 @@ export default function ({ types: t }: { types: typeof types }): PluginObj {
exportNames.push(name)
}
},
ImportDeclaration(path) {
// This is for RSC cells:
// Change createCell imports to createServerCell
const source = path.node.source.value
if (source === '@redwoodjs/web') {
const specifiers = path.node.specifiers
const createCellSpecifier: types.ImportSpecifier | undefined =
specifiers.find((specifier): specifier is types.ImportSpecifier => {
return (
t.isImportSpecifier(specifier) &&
t.isIdentifier(specifier.imported) &&
specifier.imported.name === 'createCell'
)
})

if (
createCellSpecifier &&
t.isIdentifier(createCellSpecifier.imported)
) {
createCellSpecifier.imported.name = 'createServerCell'
createCellSpecifier.local.name = 'createServerCell'

// Also update where we import from
path.node.source.value =
'@redwoodjs/web/dist/components/cell/createServerCell.js'
}
}
},
Program: {
enter() {
// Reset variables as they're still in scope from the previous file
Expand All @@ -134,25 +86,36 @@ export default function ({ types: t }: { types: typeof types }): PluginObj {
return
}

// TODO (RSC): When we want to support `data = async () => {}` in
// client cells as well, we'll need a different heuristic here
// If we want to support `QUERY` (gql) cells on the server we'll
// also need a different heuristic
const createCellHookName = exportNames.includes('data')
? 'createServerCell'
: 'createCell'
const importFrom = exportNames.includes('data')
? '@redwoodjs/web/dist/components/cell/createServerCell'
: '@redwoodjs/web'

// Insert at the top of the file:
// + import { createCell } from '@redwoodjs/web'
path.node.body.unshift(
t.importDeclaration(
[
t.importSpecifier(
t.identifier('createCell'),
t.identifier('createCell')
t.identifier(createCellHookName),
t.identifier(createCellHookName)
),
],
t.stringLiteral('@redwoodjs/web')
t.stringLiteral(importFrom)
)
)

// Insert at the bottom of the file:
// + export default createCell({ QUERY?, Loading?, Success?, Failure?, Empty?, beforeQuery?, isEmpty, afterQuery?, displayName? })
path.node.body.push(
t.exportDefaultDeclaration(
t.callExpression(t.identifier('createCell'), [
t.callExpression(t.identifier(createCellHookName), [
t.objectExpression([
...exportNames.map((name) =>
t.objectProperty(
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/rsc/rscBuildServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export async function rscBuildServer(

const serverBuildOutput = await viteBuild({
// ...configFileConfig,
root: rwPaths.web.base,
root: rwPaths.web.src,
envPrefix: 'REDWOOD_ENV_',
publicDir: path.join(rwPaths.web.base, 'public'),
envFile: false,
Expand Down

0 comments on commit d83d52d

Please sign in to comment.