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): Remove entries.ts file #10533

Merged
merged 6 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
4 changes: 0 additions & 4 deletions packages/project-config/src/__tests__/paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ describe('paths', () => {
viteConfig: null,
entryClient: null,
entryServer: null,
entries: null,
graphql: path.join(FIXTURE_BASEDIR, 'web', 'src', 'graphql'),
},
}
Expand Down Expand Up @@ -469,7 +468,6 @@ describe('paths', () => {
viteConfig: path.join(FIXTURE_BASEDIR, 'web', 'vite.config.ts'),
entryClient: null, // doesn't exist in example-todo-main
entryServer: null, // doesn't exist in example-todo-main
entries: null, // doesn't exist in example-todo-main
},
}

Expand Down Expand Up @@ -756,7 +754,6 @@ describe('paths', () => {
),
entryClient: null,
entryServer: null,
entries: null,
dist: path.join(FIXTURE_BASEDIR, 'web', 'dist'),
distEntryServer: path.join(
FIXTURE_BASEDIR,
Expand Down Expand Up @@ -1086,7 +1083,6 @@ describe('paths', () => {
viteConfig: path.join(FIXTURE_BASEDIR, 'web', 'vite.config.ts'),
entryClient: path.join(FIXTURE_BASEDIR, 'web/src/entry.client.tsx'),
entryServer: null,
entries: null,
},
}

Expand Down
3 changes: 0 additions & 3 deletions packages/project-config/src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export interface WebPaths {
viteConfig: string | null // because vite is opt-in only
entryClient: string | null
entryServer: string | null
entries: string | null
postcss: string
storybookConfig: string
storybookPreviewConfig: string | null
Expand Down Expand Up @@ -117,7 +116,6 @@ const PATH_WEB_DIR_CONFIG_WEBPACK = 'web/config/webpack.config.js'
const PATH_WEB_DIR_CONFIG_VITE = 'web/vite.config' // .js,.ts
const PATH_WEB_DIR_ENTRY_CLIENT = 'web/src/entry.client' // .jsx,.tsx
const PATH_WEB_DIR_ENTRY_SERVER = 'web/src/entry.server' // .jsx,.tsx
const PATH_WEB_DIR_ENTRIES = 'web/src/entries' // .js,.ts
const PATH_WEB_DIR_GRAPHQL = 'web/src/graphql' // .js,.ts

const PATH_WEB_DIR_CONFIG_POSTCSS = 'web/config/postcss.config.js'
Expand Down Expand Up @@ -259,7 +257,6 @@ export const getPaths = (BASE_DIR: string = getBaseDir()): Paths => {
types: path.join(BASE_DIR, 'web/types'),
entryClient: resolveFile(path.join(BASE_DIR, PATH_WEB_DIR_ENTRY_CLIENT)), // new vite/stream entry point for client
entryServer: resolveFile(path.join(BASE_DIR, PATH_WEB_DIR_ENTRY_SERVER)),
entries: resolveFile(path.join(BASE_DIR, PATH_WEB_DIR_ENTRIES)),
graphql: path.join(BASE_DIR, PATH_WEB_DIR_GRAPHQL),
},
}
Expand Down
4 changes: 0 additions & 4 deletions packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
"types": "./dist/index.d.ts",
"default": "./cjsWrapper.js"
},
"./entries": {
"types": "./dist/entries.d.ts",
"default": "./dist/entries.js"
},
"./client": {
"types": "./dist/client.d.ts",
"default": "./dist/client.js"
Expand Down
4 changes: 0 additions & 4 deletions packages/vite/src/buildFeServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ export const buildFeServer = async ({ verbose, webDir }: BuildOptions = {}) => {
}

if (rscEnabled) {
if (!rwPaths.web.entries) {
throw new Error('RSC entries file not found')
}

await buildRscClientAndServer()
}

Expand Down
6 changes: 3 additions & 3 deletions packages/vite/src/buildRscClientAndServer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { rscBuildAnalyze } from './rsc/rscBuildAnalyze.js'
import { rscBuildClient } from './rsc/rscBuildClient.js'
import { rscBuildClientEntriesMappings } from './rsc/rscBuildClientEntriesFile.js'
import { rscBuildCopyCssAssets } from './rsc/rscBuildCopyCssAssets.js'
import { rscBuildEntriesMappings } from './rsc/rscBuildEntriesFile.js'
import { rscBuildForServer } from './rsc/rscBuildForServer.js'
import { rscBuildRwEnvVars } from './rsc/rscBuildRwEnvVars.js'

Expand All @@ -28,9 +28,9 @@ export const buildRscClientAndServer = async () => {
// Can we do this more similar to how it's done for streaming?
await rscBuildCopyCssAssets(serverBuildOutput)

// Mappings from server to client asset file names
// Mappings from standard names to full asset names
// Used by the RSC worker
await rscBuildClientEntriesMappings(
await rscBuildEntriesMappings(
clientBuildOutput,
serverBuildOutput,
clientEntryFiles,
Expand Down
6 changes: 4 additions & 2 deletions packages/vite/src/clientSsr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ async function getEntries() {
async function getFunctionComponent<TProps>(
rscId: string,
): Promise<React.FunctionComponent<TProps>> {
const { getEntry } = (await getEntries()).default
const mod = await getEntry(rscId)
const { serverEntries } = await getEntries()
const entryPath = path.join(getPaths().web.distRsc, serverEntries[rscId])
const mod = await import(makeFilePath(entryPath))

if (typeof mod === 'function') {
return mod
Expand Down Expand Up @@ -108,6 +109,7 @@ export function renderFromDist<TProps extends Record<string, any>>(
ServerEntry = () => createElement('div', {}, 'Loading')
}

console.log('getEntries', getEntries())
Tobbe marked this conversation as resolved.
Show resolved Hide resolved
const clientEntries = (await getEntries()).clientEntries

// TODO (RSC): Try removing the proxy here and see if it's really necessary.
Expand Down
26 changes: 0 additions & 26 deletions packages/vite/src/entries.ts

This file was deleted.

49 changes: 49 additions & 0 deletions packages/vite/src/lib/entries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import path from 'node:path'

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

const getPathRelativeToSrc = (maybeAbsolutePath: string) => {
// If the path is already relative
if (!path.isAbsolute(maybeAbsolutePath)) {
return maybeAbsolutePath
}

return `./${path.relative(getPaths().web.src, maybeAbsolutePath)}`
}

const withRelativeImports = (page: PagesDependency) => {
return {
...page,
relativeImport: ensurePosixPath(getPathRelativeToSrc(page.importPath)),
}
}

export function getEntries() {
const entries: Record<string, string> = {}

// Add the various pages
const pages = processPagesDir().map(withRelativeImports)
for (const page of pages) {
entries[page.importName] = page.path
}

// Add the "ServerEntry" entry
const serverEntry = getPaths().web.entryServer
if (!serverEntry) {
throw new Error('Server Entry file not found')
}
entries['ServerEntry'] = serverEntry
Josh-Walker-GM marked this conversation as resolved.
Show resolved Hide resolved

return entries
}

export async function getEntriesFromDist(): Promise<Record<string, string>> {
const entriesDist = getPaths().web.distRscEntries
const { serverEntries } = await import(`file://${entriesDist}`)
Tobbe marked this conversation as resolved.
Show resolved Hide resolved
return serverEntries
}
8 changes: 3 additions & 5 deletions packages/vite/src/rsc/rscBuildAnalyze.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { build as viteBuild } from 'vite'

import { getPaths } from '@redwoodjs/project-config'

import { getEntries } from '../lib/entries.js'
import { onWarn } from '../lib/onWarn.js'
import { rscAnalyzePlugin } from '../plugins/vite-plugin-rsc-analyze.js'

Expand All @@ -22,10 +23,6 @@ export async function rscBuildAnalyze() {
const serverEntryFileSet = new Set<string>()
const componentImportMap = new Map<string, string[]>()

if (!rwPaths.web.entries) {
throw new Error('RSC entries file not found')
}

if (!rwPaths.web.viteConfig) {
throw new Error('Vite config not found')
}
Expand Down Expand Up @@ -76,9 +73,10 @@ export async function rscBuildAnalyze() {
// to generate these entries, rather than write to actual file.
// And so, we might as well use on-the-fly generation for regular
// builds too
Josh-Walker-GM marked this conversation as resolved.
Show resolved Hide resolved
ssr: rwPaths.web.entries,
ssr: true,
rollupOptions: {
onwarn: onWarn,
input: getEntries(),
},
},
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import fs from 'fs/promises'

import type { OutputChunk } from 'rollup'
import { normalizePath } from 'vite'

import { getPaths } from '@redwoodjs/project-config'

import { getEntries } from '../lib/entries.js'

import type { rscBuildClient } from './rscBuildClient.js'
import type { rscBuildForServer } from './rscBuildForServer.js'

Expand All @@ -14,17 +19,18 @@ import type { rscBuildForServer } from './rscBuildForServer.js'
// TODO(RSC_DC): This function should eventually be removed.
// The dev server will need this implemented as a Vite plugin,
// so worth waiting till implementation to swap out and just include the plugin for the prod build
export function rscBuildClientEntriesMappings(
export async function rscBuildEntriesMappings(
clientBuildOutput: Awaited<ReturnType<typeof rscBuildClient>>,
serverBuildOutput: Awaited<ReturnType<typeof rscBuildForServer>>,
clientEntryFiles: Record<string, string>,
) {
console.log('\n')
console.log('5. rscBuildClientEntriesMapping')
console.log('5. rscBuildEntriesMapping')
console.log('===============================\n')
Tobbe marked this conversation as resolved.
Show resolved Hide resolved

const rwPaths = getPaths()

// RSC client component to client dist asset mapping
const clientEntries: Record<string, string> = {}
for (const item of clientBuildOutput) {
const { name, fileName } = item
Expand Down Expand Up @@ -53,9 +59,26 @@ export function rscBuildClientEntriesMappings(
}

console.log('clientEntries', clientEntries)
await fs.appendFile(
rwPaths.web.distRscEntries,
`// client component mapping (dist/rsc -> dist/client)\nexport const clientEntries = ${JSON.stringify(clientEntries, undefined, 2)};\n\n`,
)

// Server component names to RSC server asset mapping
const entries = getEntries()
const serverEntries: Record<string, string> = {}
for (const [name, sourceFile] of Object.entries(entries)) {
const buildOutputItem = serverBuildOutput.find((item) => {
return (item as OutputChunk).facadeModuleId === normalizePath(sourceFile)
})
if (buildOutputItem) {
Tobbe marked this conversation as resolved.
Show resolved Hide resolved
serverEntries[name] = buildOutputItem.fileName
}
}

return fs.appendFile(
console.log('serverEntries', serverEntries)
await fs.appendFile(
rwPaths.web.distRscEntries,
`export const clientEntries=${JSON.stringify(clientEntries)};`,
`// server component mapping (src -> dist/rsc)\nexport const serverEntries = ${JSON.stringify(serverEntries, undefined, 2)};\n\n`,
)
}
12 changes: 8 additions & 4 deletions packages/vite/src/rsc/rscBuildForServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { build as viteBuild } from 'vite'

import { getPaths } from '@redwoodjs/project-config'

import { getEntries } from '../lib/entries.js'
import { onWarn } from '../lib/onWarn.js'
// import { rscCssPreinitPlugin } from '../plugins/vite-plugin-rsc-css-preinit.js'
import { rscRoutesAutoLoader } from '../plugins/vite-plugin-rsc-routes-auto-loader.js'
Expand All @@ -25,9 +26,8 @@ export async function rscBuildForServer(

const rwPaths = getPaths()

if (!rwPaths.web.entries) {
throw new Error('RSC entries file not found')
}
const entryFiles = getEntries()
const entryFilesKeys = Object.keys(entryFiles)

if (!rwPaths.web.entryServer) {
throw new Error('Server Entry file not found')
Expand Down Expand Up @@ -80,7 +80,7 @@ export async function rscBuildForServer(
rollupOptions: {
onwarn: onWarn,
input: {
entries: rwPaths.web.entries,
...entryFiles,
...clientEntryFiles,
...serverEntryFiles,
...customModules,
Expand Down Expand Up @@ -109,6 +109,10 @@ export async function rscBuildForServer(
},
entryFileNames: (chunkInfo) => {
// TODO (RSC) Probably don't want 'entries'. And definitely don't want it hardcoded
// Entries such as pages should be named like the other assets
if (entryFilesKeys.includes(chunkInfo.name)) {
return 'assets/[name]-[hash].mjs'
}
if (
chunkInfo.name === 'entries' ||
Josh-Walker-GM marked this conversation as resolved.
Show resolved Hide resolved
chunkInfo.name === 'entry.server' ||
Expand Down
32 changes: 8 additions & 24 deletions packages/vite/src/rsc/rscWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { createServer, resolveConfig } from 'vite'

import { getPaths } from '@redwoodjs/project-config'

import type { defineEntries, GetEntry } from '../entries.js'
import { getEntries, getEntriesFromDist } from '../lib/entries.js'
import { registerFwGlobalsAndShims } from '../lib/registerFwGlobalsAndShims.js'
import { StatusError } from '../lib/StatusError.js'
import { rscReloadPlugin } from '../plugins/vite-plugin-rsc-reload.js'
Expand All @@ -38,7 +38,6 @@ const { renderToPipeableStream } = RSDWServer

let absoluteClientEntries: Record<string, string> = {}

type Entries = { default: ReturnType<typeof defineEntries> }
type PipeableStream = { pipe<T extends Writable>(destination: T): T }

const handleSetClientEntries = async ({
Expand Down Expand Up @@ -198,37 +197,22 @@ type ConfigType = Omit<ResolvedConfig, 'root'> & { root: string }
const configPromise: Promise<ConfigType> = resolveConfig({}, 'serve')

const getFunctionComponent = async (rscId: string) => {
let entriesFilePath: string | null

// TODO (RSC): Get rid of this when we only use the worker in dev mode
const isDev = Object.keys(absoluteClientEntries).length === 0

let entryModule: string | undefined
if (isDev) {
entriesFilePath = getPaths().web.entries
entryModule = getEntries()[rscId]
} else {
entriesFilePath = getPaths().web.distRscEntries
}

if (!entriesFilePath) {
throw new Error('entries file not found at: ' + entriesFilePath)
const serverEntries = await getEntriesFromDist()
entryModule = path.join(getPaths().web.distRsc, serverEntries[rscId])
}

let getEntry: GetEntry

if (isDev) {
const vite = await vitePromise
const { default: entriesFileModule } =
await vite.ssrLoadModule(entriesFilePath)
getEntry = entriesFileModule.getEntry
} else {
const {
default: { getEntry: getEntryProd },
} = await (loadServerFile(entriesFilePath) as Promise<Entries>)

getEntry = getEntryProd
if (!entryModule) {
throw new StatusError('No entry found for ' + rscId, 404)
}

const mod = await getEntry(rscId)
const mod = await loadServerFile(entryModule)

if (typeof mod === 'function') {
return mod
Expand Down
Loading