Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rsc-streaming): Integrating RSC builds with Streaming and Client side hydration #10031

Merged
merged 106 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
e5f7606
just adding some comments for my understanding
dac09 Feb 14, 2024
b7870ee
Add some TODOS
dac09 Feb 14, 2024
a6809a9
Combine builds - rename some functions
dac09 Feb 15, 2024
3147a63
[Paths] Update paths to build into separate client, server and rsc fo…
dac09 Feb 15, 2024
391a145
Rename rscBuildServer -> rscBuildForWorker
dac09 Feb 15, 2024
c43d08a
WIP: getDefines
dac09 Feb 15, 2024
86a4e41
Re-enable routes autoloader
dac09 Feb 16, 2024
979bdd8
Build manifest log
dac09 Feb 16, 2024
a59b10c
Remove viteclient.serve from fixtures and template for RSC
dac09 Feb 16, 2024
fbc3384
Merge branch 'main' of github.com:redwoodjs/redwood into feat/rsc-build
dac09 Feb 16, 2024
b283f05
Serve all static files in the dist.client folder
dac09 Feb 16, 2024
1a882dd
Merge branch 'main' of github.com:redwoodjs/redwood into feat/rsc-build
dac09 Feb 19, 2024
93a3e68
Remove console logs
dac09 Feb 19, 2024
ec3925b
Rename server -> renderFromRscServer
dac09 Feb 19, 2024
fcd596f
Merge branch 'main' of github.com:redwoodjs/redwood into feat/rsc-build
dac09 Feb 19, 2024
5e767b2
Remove index.html requirement
dac09 Feb 19, 2024
7ff0461
Merge branch 'main' into feat/rsc-build
dac09 Feb 19, 2024
310f8eb
Only change client path when ssr or rsc enabled
dac09 Feb 20, 2024
68e6244
Merge branch 'feat/rsc-build' of github.com:dac09/redwood into feat/r…
dac09 Feb 20, 2024
dcade00
FIx entry lookup in fe server
dac09 Feb 20, 2024
29250e0
Add apollo dependency to RSC fixture
dac09 Feb 20, 2024
238e2a5
Merge branch 'main' into feat/rsc-build
dac09 Feb 20, 2024
def1dd9
Unhardcode new paths, add it to rwPaths package
dac09 Feb 20, 2024
ce81604
Merge branch 'feat/rsc-build' of github.com:dac09/redwood into feat/r…
dac09 Feb 20, 2024
43117fa
Merge branch 'main' into feat/rsc-build
Tobbe Feb 23, 2024
46f9499
Apply suggestions from code review
Tobbe Feb 23, 2024
051decf
Tobbe review changes
Tobbe Feb 23, 2024
cc4024e
Rename build functions
dac09 Feb 23, 2024
5a7c550
Fix paths test with new paths
dac09 Feb 23, 2024
9be7278
Another rename of build functions
dac09 Feb 23, 2024
274955d
Lint
dac09 Feb 23, 2024
8cb6645
Remove duplicated file
dac09 Feb 23, 2024
81ddb6e
Update some more comments
dac09 Feb 23, 2024
ffca103
Code comment tweaks/fixes
Tobbe Feb 23, 2024
d624776
Remove `serve` from test fixture
Tobbe Feb 23, 2024
246e045
node-loader should look in distRsc now, not distServer
Tobbe Feb 23, 2024
c4b42ab
doc comment formatting
Tobbe Feb 23, 2024
e81d557
innerText
Tobbe Feb 24, 2024
924d771
no more 'as string', and startsWith instead of includes
Tobbe Feb 24, 2024
229fe35
Remove outdated todo comment. And other comment formatting
Tobbe Feb 24, 2024
c4f59bc
Revert startsWith change
Tobbe Feb 24, 2024
a000c38
Merge branch 'main' into feat/rsc-build
dac09 Feb 24, 2024
4e29a13
@tobbe.dev/rsc-test@0.0.4
Tobbe Feb 25, 2024
881edb6
@tobbe.dev/rsc-test@0.0.5
Tobbe Feb 25, 2024
87d0daf
Merge branch 'main' into feat/rsc-build
dac09 Feb 27, 2024
142f0b7
Update setupRscExternal readme
dac09 Feb 27, 2024
4bf3b03
Merge branch 'main' into feat/rsc-build
Tobbe Feb 27, 2024
ec6497d
emptyOutDir
Tobbe Feb 28, 2024
25b7ede
Consolidate vite settings for rsc build (#262)
dac09 Feb 28, 2024
374ac5e
Allow mjs entry server and document. As string is OK
dac09 Feb 28, 2024
f88424e
Empty outdir for ssr build
dac09 Feb 28, 2024
bb05d58
Silence rscBuildAnalyze
dac09 Feb 28, 2024
92e13bf
Move react plugin into their individual files
dac09 Feb 29, 2024
e717397
Ok
dac09 Feb 29, 2024
a9c2f6b
Merge branch 'main' of github.com:redwoodjs/redwood into feat/rsc-build
dac09 Feb 29, 2024
73961ba
Also change SPA web build
dac09 Feb 29, 2024
afb02ce
Lint
dac09 Feb 29, 2024
b4a7661
Revert "Ok"
dac09 Feb 29, 2024
20488fb
RSC: Make babel insert `renderFromRscServer` calls into Routes.tsx (#…
Tobbe Feb 29, 2024
e556b99
Merge branch 'main' into feat/rsc-build
Tobbe Feb 29, 2024
f22679d
Consistent rsc build logging
Tobbe Feb 29, 2024
44a86bf
Merge branch 'feat/rsc-build' of github.com:dac09/redwood into feat/r…
dac09 Feb 29, 2024
f9799ff
Revert "Move react plugin into their individual files"
dac09 Feb 29, 2024
9e2c3f7
Revert "Also change SPA web build"
dac09 Feb 29, 2024
8e435b4
More bad merging
dac09 Feb 29, 2024
6eb5ca9
MjsOrJs Resolution of paths
dac09 Feb 29, 2024
91cf5af
Remove log
dac09 Feb 29, 2024
350fadc
getMergedConfig
dac09 Feb 29, 2024
089daa9
Undo accidentally changing vscode settings
dac09 Feb 29, 2024
8e05e7f
Remove comment on entries
dac09 Feb 29, 2024
8db7877
Clarify comment on entries vs inputs
dac09 Feb 29, 2024
69abdd8
Remove TODO
dac09 Feb 29, 2024
df5b52f
Merge branch 'main' into feat/rsc-build
Tobbe Feb 29, 2024
e19ed76
chore(refactor): vite - extract into buildRouteHooks.ts (#10080)
Tobbe Feb 29, 2024
9e1f15b
Merge branch 'main' into feat/rsc-build
Tobbe Feb 29, 2024
b37a9c3
Merge branch 'main' into feat/rsc-build
Tobbe Mar 2, 2024
68f34ef
rscEnabled naming everywhere
Tobbe Mar 2, 2024
0b3a49c
getMergedConfig comment format
Tobbe Mar 2, 2024
18b6fd7
More comment formatting
Tobbe Mar 2, 2024
d5eb5d9
paths.ts: Move helper to esm section
Tobbe Mar 2, 2024
91861fd
Merge branch 'main' into feat/rsc-build
Tobbe Mar 2, 2024
49a788e
Merge branch 'main' into feat/rsc-build
Tobbe Mar 3, 2024
ce0e708
Merge branch 'main' into feat/rsc-build
Tobbe Mar 3, 2024
ec443aa
Merge branch 'main' into feat/rsc-build
Tobbe Mar 3, 2024
89040b4
Merge branch 'main' into feat/rsc-build
Tobbe Mar 3, 2024
22d4065
Remove duplicated comment (exists further down)
Tobbe Mar 3, 2024
14b1f47
Only comment about swc in one place
Tobbe Mar 3, 2024
df2ba4c
Merge branch 'main' into feat/rsc-build
Tobbe Mar 3, 2024
e9beff0
Remove handled TODO
Tobbe Mar 3, 2024
7941053
Merge branch 'main' into feat/rsc-build
Tobbe Mar 4, 2024
3e3f7b9
Merge branch 'main' into feat/rsc-build
Tobbe Mar 4, 2024
71851bb
Remove redundant cwd check
Tobbe Mar 4, 2024
72f56a0
Comment on ensureProcessDirWeb()
Tobbe Mar 4, 2024
ba48fc3
Merge branch 'main' into feat/rsc-build
Tobbe Mar 4, 2024
5ac8c2b
Merge branch 'feat/rsc-build' of github.com:dac09/redwood into feat/r…
dac09 Mar 4, 2024
99ca8dc
Hack: Skip calling renderFromRscServer during SSR
dac09 Mar 4, 2024
ab9713e
Undo settings.json
dac09 Mar 4, 2024
f6f0b4d
runFeServer: Always look for client-build-manifest in distClient
Tobbe Mar 4, 2024
ae5c998
Update comments
dac09 Mar 4, 2024
76dda62
Merge branch 'main' into feat/rsc-build
Tobbe Mar 4, 2024
c760de4
Merge branch 'main' into feat/rsc-build
Tobbe Mar 4, 2024
f8ec673
node:path
Tobbe Mar 4, 2024
7935477
streamingSsrEnabled rscEnabled
Tobbe Mar 4, 2024
1be4ef1
chore(style): getDefaultViteConfig source format
Tobbe Mar 4, 2024
394a23a
Merge branch 'tobbe-default-vite-config-tweaks' into feat/rsc-build
Tobbe Mar 4, 2024
17b0374
Merge branch 'main' into feat/rsc-build
Tobbe Mar 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions __fixtures__/test-project-rsa/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
]
},
"dependencies": {
"@apollo/experimental-nextjs-app-support": "0.0.0-commit-b8a73fe",
"@redwoodjs/forms": "7.0.0-canary.717",
"@redwoodjs/router": "7.0.0-canary.717",
"@redwoodjs/web": "7.0.0-canary.717",
Expand Down
4 changes: 0 additions & 4 deletions __fixtures__/test-project-rsa/web/src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@
// 'src/pages/Admin/BooksPage/BooksPage.js' -> AdminBooksPage

import { Router, Route, Set } from '@redwoodjs/router'
import { serve } from '@redwoodjs/vite/client'

import NavigationLayout from './layouts/NavigationLayout/NavigationLayout'
import NotFoundPage from './pages/NotFoundPage/NotFoundPage'

const AboutPage = serve('AboutPage')
const HomePage = serve('HomePage')

const Routes = () => {
return (
<Router>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ import * as babel from '@babel/core'
import { getPaths } from '@redwoodjs/project-config'

import babelRoutesAutoLoader from '../babel-plugin-redwood-routes-auto-loader'
import type { PluginOptions as RoutesAutoLoaderOptions } from '../babel-plugin-redwood-routes-auto-loader'

const transform = (filename: string) => {
const transform = (
filename: string,
pluginOptions?: RoutesAutoLoaderOptions
) => {
const code = fs.readFileSync(filename, 'utf-8')
return babel.transform(code, {
filename,
presets: ['@babel/preset-react'],
plugins: [babelRoutesAutoLoader],
plugins: [[babelRoutesAutoLoader, pluginOptions]],
})
}

Expand Down Expand Up @@ -67,4 +71,59 @@ describe('page auto loader correctly imports pages', () => {
test('Already imported pages are left alone.', () => {
expect(result?.code).toContain(`import FooPage from 'src/pages/FooPage'`)
})

test('RSC specific code should not be added', () => {
expect(result?.code).not.toContain(
'import { renderFromRscServer } from "@redwoodjs/vite/client"'
)
})
})

describe('page auto loader handles imports for RSC', () => {
const FIXTURE_PATH = path.resolve(
__dirname,
'../../../../../__fixtures__/example-todo-main/'
)

let result: babel.BabelFileResult | null

beforeAll(() => {
process.env.RWJS_CWD = FIXTURE_PATH
result = transform(getPaths().web.routes, { forRscClient: true })
})

afterAll(() => {
delete process.env.RWJS_CWD
})

test('Pages are loaded with renderFromRscServer', () => {
const codeOutput = result?.code
expect(codeOutput).not.toContain(`const HomePage = {
name: "HomePage",
prerenderLoader: name => __webpack_require__(require.resolveWeak("./pages/HomePage/HomePage")),
LazyComponent: lazy(() => import( /* webpackChunkName: "HomePage" */"./pages/HomePage/HomePage"))
`)

expect(codeOutput).toContain(
'import { renderFromRscServer } from "@redwoodjs/vite/client"'
)

expect(codeOutput).toContain(
'const HomePage = renderFromRscServer("HomePage")'
)

// Un-imported pages get added with renderFromRscServer
// so it calls the RSC worker to get a flight response
expect(codeOutput).toContain(
'const HomePage = renderFromRscServer("HomePage")'
)
expect(codeOutput).toContain(
'const BarPage = renderFromRscServer("BarPage")'
)
})

// Not sure about this 👇 - what should the behaviour be?
test('Already imported pages are left alone.', () => {
expect(result?.code).toContain(`import FooPage from 'src/pages/FooPage'`)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import type { PluginObj, types } from '@babel/core'

import type { PagesDependency } from '@redwoodjs/project-config'
import {
ensurePosixPath,
getPaths,
importStatementPath,
processPagesDir,
getPaths,
ensurePosixPath,
getConfig,
} from '@redwoodjs/project-config'

interface PluginOptions {
prerender?: boolean
vite?: boolean
export interface PluginOptions {
forPrerender?: boolean
forVite?: boolean
forRscClient?: boolean
}

/**
Expand All @@ -39,7 +39,7 @@ const withRelativeImports = (page: PagesDependency) => {

export default function (
{ types: t }: { types: typeof types },
{ prerender = false, vite = false }: PluginOptions
{ forPrerender = false, forVite = false, forRscClient = false }: PluginOptions
): PluginObj {
// @NOTE: This var gets mutated inside the visitors
let pages = processPagesDir().map(withRelativeImports)
Expand All @@ -64,14 +64,6 @@ export default function (
)
}

if (getConfig().experimental?.rsc?.enabled) {
// TODO (RSC): Enable auto-loader for RSC
return {
name: 'babel-plugin-redwood-routes-auto-loader',
visitor: {},
}
}

return {
name: 'babel-plugin-redwood-routes-auto-loader',
visitor: {
Expand Down Expand Up @@ -102,7 +94,7 @@ export default function (
// This is to make sure that all the imported "Page modules" are normal
// imports and not asynchronous ones.
// Note that jest in a user's project does not enter this block, but our tests do
if (prerender) {
if (forPrerender) {
// Match import paths, const name could be different

const pageThatUserImported = pages.find((page) => {
Expand Down Expand Up @@ -152,67 +144,103 @@ export default function (
)
)

// For RSC Client builds add
// import { renderFromRscServer } from '@redwoodjs/vite/client'
if (forRscClient) {
nodes.unshift(
t.importDeclaration(
[
t.importSpecifier(
t.identifier('renderFromRscServer'),
t.identifier('renderFromRscServer')
),
],
t.stringLiteral('@redwoodjs/vite/client')
)
)
}

// Prepend all imports to the top of the file
for (const { importName, relativeImport } of pages) {
// const <importName> = {
// name: <importName>,
// prerenderLoader: (name) => prerenderLoaderImpl
// LazyComponent: lazy(() => import(/* webpackChunkName: "..." */ <relativeImportPath>)
// }

/**
* Real example
* const LoginPage = {
* name: "LoginPage",
* prerenderLoader: () => __webpack_require__(require.resolveWeak("./pages/LoginPage/LoginPage")), */
// LazyComponent: lazy(() => import("/* webpackChunkName: "LoginPage" *//pages/LoginPage/LoginPage.tsx"))
/*
* }
*/

const importArgument = t.stringLiteral(relativeImport)

importArgument.leadingComments = [
{
type: 'CommentBlock',
value: ` webpackChunkName: "${importName}" `,
},
]
if (forRscClient) {
// rsc CLIENT wants this format
// const AboutPage = renderFromRscServer('AboutPage')
// this basically allows the page to be rendered via flight response
nodes.push(
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier(importName),
t.callExpression(t.identifier('renderFromRscServer'), [
t.stringLiteral(importName),
])
),
])
)
} else {
// const <importName> = {
// name: <importName>,
// prerenderLoader: (name) => prerenderLoaderImpl
// LazyComponent: lazy(() => import(/* webpackChunkName: "..." */ <relativeImportPath>)
// }

/**
* Real example
* const LoginPage = {
* name: "LoginPage",
* prerenderLoader: () => __webpack_require__(require.resolveWeak("./pages/LoginPage/LoginPage")), */
// LazyComponent: lazy(() => import("/* webpackChunkName: "LoginPage" *//pages/LoginPage/LoginPage.tsx"))
/*
* }
*/
importArgument.leadingComments = [
{
type: 'CommentBlock',
value: ` webpackChunkName: "${importName}" `,
},
]

nodes.push(
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier(importName),
t.objectExpression([
t.objectProperty(
t.identifier('name'),
t.stringLiteral(importName)
),
// prerenderLoader for ssr/prerender and first load of
// prerendered pages in browser (csr)
// prerenderLoader: (name) => { prerenderLoaderImpl }
t.objectProperty(
t.identifier('prerenderLoader'),
t.arrowFunctionExpression(
[t.identifier('name')],
prerenderLoaderImpl(prerender, vite, relativeImport, t)
)
),
t.objectProperty(
t.identifier('LazyComponent'),
t.callExpression(t.identifier('lazy'), [
nodes.push(
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier(importName),
t.objectExpression([
t.objectProperty(
t.identifier('name'),
t.stringLiteral(importName)
),
// prerenderLoader for ssr/prerender and first load of
// prerendered pages in browser (csr)
// prerenderLoader: (name) => { prerenderLoaderImpl }
t.objectProperty(
t.identifier('prerenderLoader'),
t.arrowFunctionExpression(
[],
t.callExpression(t.identifier('import'), [
importArgument,
])
),
])
),
])
),
])
)
[t.identifier('name')],
prerenderLoaderImpl(
forPrerender,
forVite,
relativeImport,
t
)
)
),
t.objectProperty(
t.identifier('LazyComponent'),
t.callExpression(t.identifier('lazy'), [
t.arrowFunctionExpression(
[],
t.callExpression(t.identifier('import'), [
importArgument,
])
),
])
),
])
),
])
)
}
}

// Insert at the top of the file
Expand All @@ -225,7 +253,7 @@ export default function (

function prerenderLoaderImpl(
prerender: boolean,
vite: boolean,
forVite: boolean,
relativeImport: string,
t: typeof types
) {
Expand All @@ -243,7 +271,7 @@ function prerenderLoaderImpl(
// Manually imported pages will be bundled in the main bundle and will be
// loaded by the code in `normalizePage` in util.ts
let implForBuild
if (vite) {
if (forVite) {
implForBuild = t.objectExpression([
t.objectProperty(
t.identifier('default'),
Expand Down
25 changes: 17 additions & 8 deletions packages/babel-config/src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import path from 'path'
import * as babel from '@babel/core'
import type { TransformOptions } from '@babel/core'

// Weird import, but just doing this for typesafety. Its just a type, no harm importing from src.
import type { PluginOptions as RoutesAutoloaderOptions } from '@redwoodjs/babel-config/src/plugins/babel-plugin-redwood-routes-auto-loader'
import { getConfig, getPaths } from '@redwoodjs/project-config'

import type { RegisterHookOptions } from './common'
Expand Down Expand Up @@ -99,11 +101,20 @@ export const getWebSideBabelPlugins = (
}

export const getWebSideOverrides = (
{ prerender, forVite }: Flags = {
prerender: false,
{ forPrerender, forVite, forRscClient }: Flags = {
forPrerender: false,
forVite: false,
forRscClient: false,
}
) => {
// Bit of complexity here!
// The plugin will modify the Routes file differently based on what context we're building for
const routeLoaderOptions: RoutesAutoloaderOptions = {
forPrerender,
forVite,
forRscClient,
}

const overrides = [
{
test: /.+Cell.(js|tsx|jsx)$/,
Expand All @@ -116,10 +127,7 @@ export const getWebSideOverrides = (
plugins: [
[
require('./plugins/babel-plugin-redwood-routes-auto-loader').default,
{
prerender,
vite: forVite,
},
routeLoaderOptions,
],
],
},
Expand Down Expand Up @@ -199,8 +207,9 @@ export const getWebSideBabelConfigPath = () => {
// These flags toggle on/off certain features
export interface Flags {
forJest?: boolean // will change the alias for module-resolver plugin
prerender?: boolean // changes what babel-plugin-redwood-routes-auto-loader does
forPrerender?: boolean // changes what babel-plugin-redwood-routes-auto-loader does
forVite?: boolean
forRscClient?: boolean
}

export const getWebSideDefaultBabelConfig = (options: Flags = {}) => {
Expand Down Expand Up @@ -234,7 +243,7 @@ export const registerWebSideBabelHook = ({
// We only register for prerender currently
// Static importing pages makes sense
overrides: [
...getWebSideOverrides({ prerender: true, forVite }),
...getWebSideOverrides({ forPrerender: true, forVite }),
...overrides,
],
})
Expand Down
Loading
Loading