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

chore(refactor): vite - extract default vite config #10110

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
142 changes: 3 additions & 139 deletions packages/vite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ import fs from 'fs'
import path from 'path'

import react from '@vitejs/plugin-react'
import type { InputOption } from 'rollup'
import type { ConfigEnv, UserConfig, PluginOption } from 'vite'
import type { PluginOption } from 'vite'
import { normalizePath } from 'vite'

import { getWebSideDefaultBabelConfig } from '@redwoodjs/babel-config'
import { getConfig, getPaths } from '@redwoodjs/project-config'

import { getEnvVarDefinitions } from './envVarDefinitions'
import { getDefaultViteConfig } from './lib/getDefaultViteConfig'
import handleJsAsJsx from './plugins/vite-plugin-jsx-loader'
import removeFromBundle from './plugins/vite-plugin-remove-from-bundle'
import swapApolloProvider from './plugins/vite-plugin-swap-apollo-provider'
Expand Down Expand Up @@ -126,114 +125,7 @@ export default function redwoodPluginVite(): PluginOption[] {
},
// ---------- End Bundle injection ----------

config: (options: UserConfig, env: ConfigEnv): UserConfig => {
let apiHost = process.env.REDWOOD_API_HOST
apiHost ??= rwConfig.api.host
apiHost ??= process.env.NODE_ENV === 'production' ? '0.0.0.0' : '[::]'

let apiPort
if (process.env.REDWOOD_API_PORT) {
apiPort = parseInt(process.env.REDWOOD_API_PORT)
} else {
apiPort = rwConfig.api.port
}

return {
root: rwPaths.web.src,
// Disabling for now, let babel handle this for consistency
// resolve: {
// alias: [
// {
// find: 'src',
// replacement: redwoodPaths.web.src,
// },
// ],
// },
envPrefix: 'REDWOOD_ENV_',
publicDir: path.join(rwPaths.web.base, 'public'),
define: getEnvVarDefinitions(),
css: {
// @NOTE config path is relative to where vite.config.js is if you use relative path
// postcss: './config/',
postcss: rwPaths.web.config,
},
server: {
open: rwConfig.browser.open,
port: rwConfig.web.port,
host: true, // Listen to all hosts
proxy: {
[rwConfig.web.apiUrl]: {
target: `http://${apiHost}:${apiPort}`,
changeOrigin: false,
// Remove the `.redwood/functions` part, but leave the `/graphql`
rewrite: (path) => path.replace(rwConfig.web.apiUrl, ''),
configure: (proxy) => {
// @MARK: this is a hack to prevent showing confusing proxy errors on startup
// because Vite launches so much faster than the API server.
let waitingForApiServer = true

// Wait for 2.5s, then restore regular proxy error logging
setTimeout(() => {
waitingForApiServer = false
}, 2500)

proxy.on('error', (err, _req, res) => {
if (
waitingForApiServer &&
err.message.includes('ECONNREFUSED')
) {
err.stack =
'⌛ API Server launching, please refresh your page...'
}
const msg = {
errors: [
{
message:
'The RedwoodJS API server is not available or is currently reloading. Please refresh.',
},
],
}

res.writeHead(203, {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
})
res.write(JSON.stringify(msg))
res.end()
})
},
},
},
},
build: {
outDir: options.build?.outDir || rwPaths.web.dist,
emptyOutDir: true,
manifest: !env.ssrBuild ? 'client-build-manifest.json' : undefined,
sourcemap: !env.ssrBuild && rwConfig.web.sourceMap, // Note that this can be boolean or 'inline'
rollupOptions: {
input: getRollupInput(!!env.ssrBuild),
},
},
legacy: {
buildSsrCjsExternalHeuristics: rwConfig.experimental?.rsc?.enabled
? false
: env.ssrBuild,
},
optimizeDeps: {
esbuildOptions: {
// @MARK this is because JS projects in Redwood don't have .jsx extensions
loader: {
'.js': 'jsx',
},
// Node.js global to browser globalThis
// @MARK unsure why we need this, but required for DevFatalErrorPage atleast
define: {
global: 'globalThis',
},
},
},
}
},
config: getDefaultViteConfig(rwConfig, rwPaths),
},
// We can remove when streaming is stable
rwConfig.experimental.streamingSsr.enabled && swapApolloProvider(),
Expand All @@ -259,31 +151,3 @@ export default function redwoodPluginVite(): PluginOption[] {
}),
]
}

/**
* This function configures how vite (actually Rollup) will bundle.
*
* By default, the entry point is the index.html file - even if you don't specify it in RollupOptions
*
* With streaming SSR, out entrypoint is different - either entry.client.tsx or entry.server.tsx
* and the html file is not used at all, because it is defined in Document.tsx
*
* @param ssr {boolean} Whether to return the SSR inputs or not
* @returns Rollup input Options
*/
function getRollupInput(ssr: boolean): InputOption | undefined {
const rwConfig = getConfig()
const rwPaths = getPaths()

// @NOTE once streaming ssr is out of experimental, this will become the default
if (rwConfig.experimental.streamingSsr.enabled) {
return ssr
? {
'entry.server': rwPaths.web.entryServer as string,
Document: rwPaths.web.document, // We need the document for React's fallback
}
: (rwPaths.web.entryClient as string)
}

return rwPaths.web.html
}
149 changes: 149 additions & 0 deletions packages/vite/src/lib/getDefaultViteConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import path from 'node:path'

import type { InputOption } from 'rollup'
import type { ConfigEnv, UserConfig } from 'vite'

import type { Config, Paths } from '@redwoodjs/project-config'
import { getConfig, getPaths } from '@redwoodjs/project-config'

import { getEnvVarDefinitions } from './envVarDefinitions'

export function getDefaultViteConfig(rwConfig: Config, rwPaths: Paths) {
return (options: UserConfig, env: ConfigEnv): UserConfig => {
let apiHost = process.env.REDWOOD_API_HOST
apiHost ??= rwConfig.api.host
apiHost ??= process.env.NODE_ENV === 'production' ? '0.0.0.0' : '[::]'

let apiPort
if (process.env.REDWOOD_API_PORT) {
apiPort = parseInt(process.env.REDWOOD_API_PORT)
} else {
apiPort = rwConfig.api.port
}

return {
root: rwPaths.web.src,
// Disabling for now, let babel handle this for consistency
// resolve: {
// alias: [
// {
// find: 'src',
// replacement: redwoodPaths.web.src,
// },
// ],
// },
envPrefix: 'REDWOOD_ENV_',
publicDir: path.join(rwPaths.web.base, 'public'),
define: getEnvVarDefinitions(),
css: {
// @NOTE config path is relative to where vite.config.js is if you use relative path
// postcss: './config/',
postcss: rwPaths.web.config,
},
server: {
open: rwConfig.browser.open,
port: rwConfig.web.port,
host: true, // Listen to all hosts
proxy: {
[rwConfig.web.apiUrl]: {
target: `http://${apiHost}:${apiPort}`,
changeOrigin: false,
// Remove the `.redwood/functions` part, but leave the `/graphql`
rewrite: (path) => path.replace(rwConfig.web.apiUrl, ''),
configure: (proxy) => {
// @MARK: this is a hack to prevent showing confusing proxy errors on startup
// because Vite launches so much faster than the API server.
let waitingForApiServer = true

// Wait for 2.5s, then restore regular proxy error logging
setTimeout(() => {
waitingForApiServer = false
}, 2500)

proxy.on('error', (err, _req, res) => {
if (
waitingForApiServer &&
err.message.includes('ECONNREFUSED')
) {
err.stack =
'⌛ API Server launching, please refresh your page...'
}
const msg = {
errors: [
{
message:
'The RedwoodJS API server is not available or is currently reloading. Please refresh.',
},
],
}

res.writeHead(203, {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache',
})
res.write(JSON.stringify(msg))
res.end()
})
},
},
},
},
build: {
outDir: options.build?.outDir || rwPaths.web.dist,
emptyOutDir: true,
manifest: !env.ssrBuild ? 'client-build-manifest.json' : undefined,
sourcemap: !env.ssrBuild && rwConfig.web.sourceMap, // Note that this can be boolean or 'inline'
rollupOptions: {
input: getRollupInput(!!env.ssrBuild),
},
},
legacy: {
buildSsrCjsExternalHeuristics: rwConfig.experimental?.rsc?.enabled
? false
: env.ssrBuild,
},
optimizeDeps: {
esbuildOptions: {
// @MARK this is because JS projects in Redwood don't have .jsx extensions
loader: {
'.js': 'jsx',
},
// Node.js global to browser globalThis
// @MARK unsure why we need this, but required for DevFatalErrorPage
// at least
define: {
global: 'globalThis',
},
},
},
}
}
}

/**
* This function configures how vite (actually Rollup) will bundle.
*
* By default, the entry point is the index.html file - even if you don't specify it in RollupOptions
*
* With streaming SSR, out entrypoint is different - either entry.client.tsx or entry.server.tsx
* and the html file is not used at all, because it is defined in Document.tsx
*
* @param ssr {boolean} Whether to return the SSR inputs or not
* @returns Rollup input Options
*/
function getRollupInput(ssr: boolean): InputOption | undefined {
const rwConfig = getConfig()
const rwPaths = getPaths()

// @NOTE once streaming ssr is out of experimental, this will become the default
if (rwConfig.experimental.streamingSsr.enabled) {
return ssr
? {
'entry.server': rwPaths.web.entryServer as string,
Document: rwPaths.web.document, // We need the document for React's fallback
}
: (rwPaths.web.entryClient as string)
}

return rwPaths.web.html
}
2 changes: 1 addition & 1 deletion packages/vite/src/rsc/rscBuildClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { build as viteBuild } from 'vite'
import { getWebSideDefaultBabelConfig } from '@redwoodjs/babel-config'
import { getPaths } from '@redwoodjs/project-config'

import { getEnvVarDefinitions } from '../envVarDefinitions'
import { getEnvVarDefinitions } from '../lib/envVarDefinitions'
import { onWarn } from '../lib/onWarn'
import { ensureProcessDirWeb } from '../utils'

Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/rsc/rscBuildForServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { build as viteBuild } from 'vite'
import { getWebSideDefaultBabelConfig } from '@redwoodjs/babel-config'
import { getPaths } from '@redwoodjs/project-config'

import { getEnvVarDefinitions } from '../envVarDefinitions'
import { getEnvVarDefinitions } from '../lib/envVarDefinitions'
import { onWarn } from '../lib/onWarn'

import { rscTransformPlugin } from './rscVitePlugins'
Expand Down
Loading