diff --git a/docs/pages/prerender/+Page.mdx b/docs/pages/prerender/+Page.mdx
index 1de7dc33d5f..084f28c7ed0 100644
--- a/docs/pages/prerender/+Page.mdx
+++ b/docs/pages/prerender/+Page.mdx
@@ -183,6 +183,50 @@ You can then manually trigger pre-rendering using:
-
+### `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 Vike extensions 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
-
diff --git a/test/playground/pages/+config.ts b/test/playground/pages/+config.ts
index 7162c6e1019..941617f8d76 100644
--- a/test/playground/pages/+config.ts
+++ b/test/playground/pages/+config.ts
@@ -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: {
diff --git a/test/playground/vite.config.ts b/test/playground/vite.config.ts
index 99d65dd814f..1330a470d91 100644
--- a/test/playground/vite.config.ts
+++ b/test/playground/vite.config.ts
@@ -30,7 +30,7 @@ type Vike = ReturnType
// 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])
@@ -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))
}
diff --git a/vike/node/plugin/plugins/commonConfig.ts b/vike/node/plugin/plugins/commonConfig.ts
index ca16d23f213..c31049e9df1 100644
--- a/vike/node/plugin/plugins/commonConfig.ts
+++ b/vike/node/plugin/plugins/commonConfig.ts
@@ -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' {
@@ -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
})
}
}
diff --git a/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts b/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
index 728d02f952e..6562adb5fb8 100644
--- a/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
+++ b/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
@@ -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
@@ -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]
@@ -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]
diff --git a/vike/node/prerender/context.ts b/vike/node/prerender/context.ts
index ee2991fe2b5..39f1b37fd92 100644
--- a/vike/node/prerender/context.ts
+++ b/vike/node/prerender/context.ts
@@ -1,4 +1,3 @@
-export { isPrerenderEnabled }
export { isPrerenderAutoRunEnabled }
export { temp_disablePrerenderAutoRun }
export { isPrerendering }
@@ -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'
diff --git a/vike/node/prerender/resolvePrerenderConfig.ts b/vike/node/prerender/resolvePrerenderConfig.ts
index 11359dd32bd..7e9f43798c1 100644
--- a/vike/node/prerender/resolvePrerenderConfig.ts
+++ b/vike/node/prerender/resolvePrerenderConfig.ts
@@ -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[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) {
@@ -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
}
diff --git a/vike/node/prerender/runPrerender.ts b/vike/node/prerender/runPrerender.ts
index 81905d89129..7ae5be814e9 100644
--- a/vike/node/prerender/runPrerender.ts
+++ b/vike/node/prerender/runPrerender.ts
@@ -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'
@@ -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
@@ -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)
@@ -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 })
+ }
}
})
@@ -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 })
}
}
})
@@ -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 }
)
})
diff --git a/vike/node/prerender/utils.ts b/vike/node/prerender/utils.ts
index 66d39833800..02c34b70c91 100644
--- a/vike/node/prerender/utils.ts
+++ b/vike/node/prerender/utils.ts
@@ -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'
diff --git a/vike/shared/page-configs/Config.ts b/vike/shared/page-configs/Config.ts
index faa37476733..4812b72b4c9 100644
--- a/vike/shared/page-configs/Config.ts
+++ b/vike/shared/page-configs/Config.ts
@@ -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
}
/**