Skip to content

Commit

Permalink
feat: prerender.value
Browse files Browse the repository at this point in the history
  • Loading branch information
brillout committed Feb 25, 2025
1 parent 441a37c commit 535bde1
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 70 deletions.
44 changes: 44 additions & 0 deletions docs/pages/prerender/+Page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,50 @@ You can then manually trigger pre-rendering using:
- <Link href="/api#prerender" doNotInferSectionTitle />


### `value`

When you set `prerender` to an object then you also enable pre-rendering. In other words:

```js
// pages/+config.js

export default {
// Setting it to an empty object:
prerender: {},
// Is equivalent to:
prerender: true
}
```

By setting `prerender.value` to `null` you opt-out from this. In other words:

```js
// pages/+config.js

export default {
// This:
prerender: { value: null },
// Is equivalent to that:
prerender: null
}
```

It's used by <Link href="/extensions">Vike extensions</Link> to change pre-rendering settings without enabling pre-rendering on behalf of the user.

```js
// node_modules/vike-some-extension/+config.js

export default {
prerender: {
// Change pre-rendering setting:
partial: true,
// Without enabling pre-rendering:
value: null
}
}
```


## See also

- <Link href="/pre-rendering" />
Expand Down
4 changes: 3 additions & 1 deletion test/playground/pages/+config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import vikeReact from 'vike-react/config'

export default {
title: 'Big Playground',
prerenderSetOverEffect: true,
prerender: {
// TEST: prerender.noExtraDir
value: null,
parallel: 4,
noExtraDir: true
},
redirects: {
Expand Down
5 changes: 4 additions & 1 deletion test/playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type Vike = ReturnType<typeof getVikeConfig>
// TEST: getVikeConfig()
function testVikeConfig(vike: Vike) {
assert(typeof vike.config.prerender![0] === 'object')
assert(vike.config.prerender![0].noExtraDir)
assert(vike.config.prerender![0].parallel === 4)
assert(vike.pages)
assert(vike.pages['/pages/index']!.config.prerender![0] === false)
assert(vike.pages['/pages/markdown']!.config.prerender![0])
Expand Down Expand Up @@ -65,4 +65,7 @@ function testPrerenderSettings(vike: Vike) {
const wasPrerendered = pageIdsPrerendered.includes(pageId)
assert(wasPrerendered === prerendered, debug)
})

// TEST: prerender.noExtraDir
prerenderContext.output.forEach(({ filePath }) => assert(!filePath.endsWith('index.html'), filePath))
}
5 changes: 3 additions & 2 deletions vike/node/plugin/plugins/commonConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import { isViteCliCall } from '../shared/isViteCliCall.js'
import { isVikeCliOrApi } from '../../api/context.js'
import { getVikeConfig2, type VikeConfigObject } from './importUserCode/v1-design/getVikeConfig.js'
import { assertViteRoot, getViteRoot, normalizeViteRoot } from '../../api/prepareViteApiCall.js'
import { isPrerenderEnabled, temp_disablePrerenderAutoRun } from '../../prerender/context.js'
import { temp_disablePrerenderAutoRun } from '../../prerender/context.js'
import type { PrerenderContextPublic } from '../../prerender/runPrerender.js'
import { resolvePrerenderConfigGlobal } from '../../prerender/resolvePrerenderConfig.js'
const pluginName = 'vike:commonConfig'

declare module 'vite' {
Expand Down Expand Up @@ -69,7 +70,7 @@ function commonConfig(vikeVitePluginOptions: unknown): Plugin[] {
},
// TODO/v1-release: remove https://github.com/vikejs/vike/issues/2122
configVikePromise: Promise.resolve({
prerender: isPrerenderEnabled(vikeConfig)
prerender: resolvePrerenderConfigGlobal(vikeConfig).isEnabled
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ async function loadVikeConfig(userRootDir: string, vikeVitePluginOptions: unknow
userRootDir
)

// interop vike(options) in vite.config.js
// Backwards compatibility for vike(options) in vite.config.js
temp_interopVikeVitePlugin(pageConfigGlobal, vikeVitePluginOptions, userRootDir)

// global
Expand Down Expand Up @@ -917,9 +917,7 @@ function assertMetaUsage(
})
}

// TODO/now update perma links
// https://github.com/vikejs/vike/blob/052ed41ffe67097c25026d7409f8741c820ea6c8/test/playground/vite.config.ts#L39
// https://github.com/vikejs/vike/blob/052ed41ffe67097c25026d7409f8741c820ea6c8/test/playground/pages/config-meta/effect/e2e-test.ts#L16
// Test: https://github.com/vikejs/vike/blob/441a37c4c1a3b07bb8f6efb1d1f7be297a53974a/test/playground/vite.config.ts#L39
function applyEffectsConfVal(configValueSources: ConfigValueSources, configDefinitions: ConfigDefinitions) {
objectEntries(configDefinitions).forEach(([configNameEffect, configDefEffect]) => {
const sourceEffect = configValueSources[configNameEffect]?.[0]
Expand All @@ -938,6 +936,7 @@ function applyEffectsConfVal(configValueSources: ConfigValueSources, configDefin
)
})
}
// Test: https://github.com/vikejs/vike/blob/441a37c4c1a3b07bb8f6efb1d1f7be297a53974a/test/playground/pages/config-meta/effect/e2e-test.ts#L16
function applyEffectsMetaEnv(configValueSources: ConfigValueSources, configDefinitions: ConfigDefinitions) {
objectEntries(configDefinitions).forEach(([configNameEffect, configDefEffect]) => {
const sourceEffect = configValueSources[configNameEffect]?.[0]
Expand Down
7 changes: 1 addition & 6 deletions vike/node/prerender/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { isPrerenderEnabled }
export { isPrerenderAutoRunEnabled }
export { temp_disablePrerenderAutoRun }
export { isPrerendering }
Expand All @@ -9,14 +8,10 @@ import { getGlobalObject } from '../../utils/getGlobalObject.js'
import { resolvePrerenderConfigGlobal } from './resolvePrerenderConfig.js'
const globalObject = getGlobalObject<{ isDisabled?: true; isPrerendering?: true }>('prerender/context.ts', {})

function isPrerenderEnabled(vikeConfig: VikeConfigObject) {
const prerenderConfigGlobal = resolvePrerenderConfigGlobal(vikeConfig)
return !!prerenderConfigGlobal
}
function isPrerenderAutoRunEnabled(vikeConfig: VikeConfigObject) {
const prerenderConfigGlobal = resolvePrerenderConfigGlobal(vikeConfig)
return (
isPrerenderEnabled(vikeConfig) &&
prerenderConfigGlobal.isEnabled &&
!(prerenderConfigGlobal || {}).disableAutoRun &&
!globalObject.isDisabled &&
vikeConfig.global.config.disableAutoFullBuild !== 'prerender'
Expand Down
38 changes: 18 additions & 20 deletions vike/node/prerender/resolvePrerenderConfig.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
export { resolvePrerenderConfigGlobal }
export { resolvePrerenderConfigLocal }

import type { ConfigResolved } from '../../shared/page-configs/Config/PageContextConfig.js'
import { VikeConfigObject } from '../plugin/plugins/importUserCode/v1-design/getVikeConfig.js'
import { assert, isArray } from './utils.js'
import { assert, isArray, objectAssign } from './utils.js'
import { getConfigValueBuildTime } from '../../shared/page-configs/getConfigValueBuildTime.js'
import type { PageConfigBuildTime } from '../../shared/page-configs/PageConfig.js'
import { getConfigValueFilePathToShowToUser } from '../../shared/page-configs/helpers.js'

type PrerenderConfigSemiResolved = ConfigResolved['prerender']
type PrerenderConfigGlobal = false | Exclude<Required<NonNullable<PrerenderConfigSemiResolved>[number]>, boolean>

// TODO/now:
// - prerender.value

function resolvePrerenderConfigGlobal(vikeConfig: VikeConfigObject): PrerenderConfigGlobal {
function resolvePrerenderConfigGlobal(vikeConfig: VikeConfigObject) {
const prerenderConfigs = vikeConfig.global.config.prerender
if (
!prerenderConfigs &&
!vikeConfig.pageConfigs.some((pageConfig) => resolvePrerenderConfigLocal(pageConfig)?.value)
) {
return false
}

let prerenderConfigList = prerenderConfigs || []
// Needed because of backwards compatibility of `vike({prerender:true})` in `vite.config.js`; after we remove it we can remove this line.
prerenderConfigList = prerenderConfigList.filter(isObject2)
assert(prerenderConfigList.every(isObject2)) // Help TS
const prerenderConfigGlobal: PrerenderConfigGlobal = {
const prerenderConfigGlobal = {
partial: pickFirst(prerenderConfigList.map((c) => c.partial)) ?? false,
noExtraDir: pickFirst(prerenderConfigList.map((c) => c.noExtraDir)) ?? false,
parallel: pickFirst(prerenderConfigList.map((c) => c.parallel)) ?? true,
disableAutoRun: pickFirst(prerenderConfigList.map((c) => c.disableAutoRun)) ?? false
}

const prerenderConfigGlobalLocalValue = prerenderConfigList.map((c) => c.value).filter((v) => v !== null)
const defaultLocalValue =
pickFirst(prerenderConfigGlobalLocalValue) ??
(prerenderConfigGlobalLocalValue.length > 0 ||
// Backwards compatibility for with vike({ prerender: true }) in vite.config.js
prerenderConfigs?.some((p) => p === true) ||
false)
objectAssign(prerenderConfigGlobal, {
defaultLocalValue,
isEnabled:
defaultLocalValue || vikeConfig.pageConfigs.some((pageConfig) => resolvePrerenderConfigLocal(pageConfig)?.value)
})

return prerenderConfigGlobal
}
function resolvePrerenderConfigLocal(pageConfig: PageConfigBuildTime) {
Expand All @@ -43,9 +43,7 @@ function resolvePrerenderConfigLocal(pageConfig: PageConfigBuildTime) {
const value = values[0]
assert(typeof value === 'boolean')
assert(isArray(configValue.definedAtData))
const configValueFilePathToShowToUser = getConfigValueFilePathToShowToUser(configValue.definedAtData[0]!)
assert(configValueFilePathToShowToUser)
const prerenderConfigLocal = { value, configValueFilePathToShowToUser }
const prerenderConfigLocal = { value }
return prerenderConfigLocal
}

Expand Down
61 changes: 25 additions & 36 deletions vike/node/prerender/runPrerender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,7 @@ type HtmlFile = {
pageId: string | null
}

type DoNotPrerenderList = ({ pageId: string; setByConfigFile: string } & (
| {
// TODO/v1-release: remove 0.4 case
setByConfigName: 'doNotPrerender'
setByConfigValue: true
}
| {
setByConfigName: 'prerender'
setByConfigValue: false
}
))[]
type DoNotPrerenderList = { pageId: string }[]
type ProvidedByHook = null | {
hookFilePath: string
hookName: 'onBeforePrerenderStart' | 'prerender'
Expand Down Expand Up @@ -219,17 +209,18 @@ async function runPrerender(options: PrerenderOptions = {}, standaloneTrigger?:
const { root } = viteConfig
const prerenderConfigGlobal = resolvePrerenderConfigGlobal(vikeConfig)
validatePrerenderConfig(prerenderConfigGlobal)
if (!prerenderConfigGlobal) {
const { partial, noExtraDir, parallel, defaultLocalValue, isEnabled } = prerenderConfigGlobal
if (!isEnabled) {
assert(standaloneTrigger)
// TODO/now: make it assertUsage() and remove dist/server/entry.mjs whenever possible
assertWarning(
prerenderConfigGlobal,
`You're executing ${pc.cyan(standaloneTrigger)} but the config ${pc.cyan('prerender')} isn't set to true`,
`You're executing ${pc.cyan(standaloneTrigger)} but you didn't enable pre-rendering. Use the config ${pc.cyan('prerender')} (${pc.underline('https://vike.dev/prerender')}) to enable it.`,
{
onlyOnce: true
}
)
}
const { partial = false, noExtraDir = false, parallel = true } = prerenderConfigGlobal || {}

const concurrencyLimit = pLimit(
parallel === false || parallel === 0 ? 1 : parallel === true || parallel === undefined ? cpus().length : parallel
Expand All @@ -248,7 +239,13 @@ async function runPrerender(options: PrerenderOptions = {}, standaloneTrigger?:
}

const doNotPrerenderList: DoNotPrerenderList = []
await collectDoNoPrerenderList(vikeConfig.pageConfigs, doNotPrerenderList, concurrencyLimit, globalContext)
await collectDoNoPrerenderList(
vikeConfig.pageConfigs,
doNotPrerenderList,
defaultLocalValue,
concurrencyLimit,
globalContext
)

await callOnBeforePrerenderStartHooks(prerenderContext, globalContext, concurrencyLimit, doNotPrerenderList)

Expand Down Expand Up @@ -286,21 +283,23 @@ async function runPrerender(options: PrerenderOptions = {}, standaloneTrigger?:
async function collectDoNoPrerenderList(
pageConfigs: PageConfigBuildTime[],
doNotPrerenderList: DoNotPrerenderList,
defaultLocalValue: boolean,
concurrencyLimit: PLimit,
globalContext: GlobalContextInternal
) {
// V1 design
pageConfigs.forEach((pageConfig) => {
const prerenderConfigLocal = resolvePrerenderConfigLocal(pageConfig)
if (!prerenderConfigLocal) return
const { value, configValueFilePathToShowToUser } = prerenderConfigLocal
if (value === false) {
doNotPrerenderList.push({
pageId: pageConfig.pageId,
setByConfigName: 'prerender',
setByConfigValue: false,
setByConfigFile: configValueFilePathToShowToUser
})
const { pageId } = pageConfig
if (!prerenderConfigLocal) {
if (!defaultLocalValue) {
doNotPrerenderList.push({ pageId })
}
} else {
const { value } = prerenderConfigLocal
if (value === false) {
doNotPrerenderList.push({ pageId })
}
}
})

Expand Down Expand Up @@ -341,12 +340,7 @@ async function collectDoNoPrerenderList(
return
} else {
// Don't pre-render `pageId`
doNotPrerenderList.push({
pageId,
setByConfigFile: p.filePath,
setByConfigName: 'doNotPrerender',
setByConfigValue: doNotPrerender
})
doNotPrerenderList.push({ pageId })
}
}
})
Expand Down Expand Up @@ -855,16 +849,11 @@ function warnContradictoryNoPrerenderList(
const isContradictory = !!doNotPrerenderListEntry && providedByHook
if (!isContradictory) return
}
const { setByConfigName, setByConfigValue, setByConfigFile } = doNotPrerenderListEntry
assertWarning(
false,
`The ${providedByHook.hookName}() hook defined by ${providedByHook.hookFilePath} returns the URL ${pc.cyan(
urlOriginal
)}, while ${setByConfigFile} sets the config ${pc.cyan(setByConfigName)} to ${pc.cyan(
String(setByConfigValue)
)}. This is contradictory: either don't set the config ${pc.cyan(setByConfigName)} to ${pc.cyan(
String(setByConfigValue)
)} or remove the URL ${pc.cyan(urlOriginal)} from the list of URLs to be pre-rendered.`,
)} matching the route of the page ${pc.cyan(pageId)} which isn't configured to be pre-rendered. This is contradictory: either enable pre-rendering for ${pc.cyan(pageId)} or remove the URL ${pc.cyan(urlOriginal)} from the list of URLs to be pre-rendered.`,
{ onlyOnce: true }
)
})
Expand Down
1 change: 1 addition & 0 deletions vike/node/prerender/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * from '../../utils/isArray.js'
export * from '../../utils/isObject.js'
export * from '../../utils/changeEnumerable.js'
export * from '../../utils/makePublicCopy.js'
export * from '../../utils/isNotNullish.js'
8 changes: 8 additions & 0 deletions vike/shared/page-configs/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,14 @@ type ConfigBuiltIn = {
* @default false
*/
disableAutoRun?: boolean
/**
* Set prerender settings without enabling pre-rendering.
*
* https://vike.dev/prerender#value
*
* @default true
*/
value?: boolean | null
}

/**
Expand Down

0 comments on commit 535bde1

Please sign in to comment.