diff --git a/docs/headingsDetached.ts b/docs/headingsDetached.ts
index df12168542..2bc66368cb 100644
--- a/docs/headingsDetached.ts
+++ b/docs/headingsDetached.ts
@@ -272,6 +272,10 @@ function tools(): HeadingDetachedDefinition[] {
function misc(): HeadingDetachedDefinition[] {
return [
+ {
+ title: "Warning: don't define global config locally",
+ url: '/warning/global-config'
+ },
{
title: 'Consulting',
url: '/consulting'
diff --git a/docs/pages/warning/global-config/+Page.mdx b/docs/pages/warning/global-config/+Page.mdx
new file mode 100644
index 0000000000..bae17663dd
--- /dev/null
+++ b/docs/pages/warning/global-config/+Page.mdx
@@ -0,0 +1,55 @@
+import { CodeBlockTransformer, Link } from '@brillout/docpress'
+
+A config is called *global* when it always applies to all pages (it cannot be applied to only a subset of pages).
+
+For example, the Base URL settings are global: changing the Base URL affects your whole app (all your pages).
+
+> There isn't any config inheritance for global configs.
+
+Consequently, it doesn't make sense to define a global config in a local `+` file.
+
+```js
+// /pages/tags/+config.js
+
+// This is a local config file: it applies only to a subset of pages.
+
+export default {
+ // ❌ Defining a global setting in a local +config.js
+ baseServer: '/blog/'
+}
+```
+
+```js
+// /pages/+config.js
+
+// This is a global config file: it applies to all pages.
+
+export default {
+ // ✅ Defining a global setting in a global +config.js
+ baseServer: '/blog/'
+}
+```
+
+If you get the following warning then move your config to a global location.
+
+
+```
+[vike][Warning] /pages/index/+config.js (which is a local config file) sets the config `baseServer` but it's a global config: define `baseServer` at a global config file such as /pages/+config.js instead.
+```
+
+
+
+> Some settings (e.g. `prerender`) are mixed: certains values can be defined only globally (e.g. `prerender.partial`) while other values can be defined locally (e.g. `false`).
+>
+> If you get the following warning, it's because you're defining a global value in a local `+` file.
+>
+>
+> ```
+> [vike][Warning] /pages/about/+config.ts (which is a local config file) sets the config `prerender` to a value that is global: define global values at a global config file such as /pages/+config.ts instead.
+> ```
+>
+
+## See also
+
+-
+-
diff --git a/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts b/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
index ac793b745b..bf750c2df3 100644
--- a/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
+++ b/vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
@@ -526,13 +526,14 @@ function assertPageConfigGlobal(
interfaceFilesAll: InterfaceFilesByLocationId
) {
Object.entries(pageConfigGlobal.configValueSources).forEach(([configName, sources]) => {
- assertGlobalConfigLocation(configName, sources, interfaceFilesAll)
+ assertGlobalConfigLocation(configName, sources, interfaceFilesAll, pageConfigGlobal.configDefinitions)
})
}
function assertGlobalConfigLocation(
configName: string,
sources: ConfigValueSource[],
- interfaceFilesAll: InterfaceFilesByLocationId
+ interfaceFilesAll: InterfaceFilesByLocationId,
+ configDefinitionsGlobal: ConfigDefinitions
) {
const locationIdsAll = objectKeys(interfaceFilesAll)
@@ -563,16 +564,24 @@ function assertGlobalConfigLocation(
if (!filePathAbsoluteUserRootDir) return
assert(!interfaceFile.isConfigExtension)
- assertWarning(
- isGlobalLocation(source.locationId, locationIdsAll),
- [
- `${filePathAbsoluteUserRootDir} sets the config ${pc.cyan(configName)} but it's a global config:`,
+ if (!isGlobalLocation(source.locationId, locationIdsAll)) {
+ const configDef = configDefinitionsGlobal[configName]
+ assert(configDef)
+ const isConditionallyGlobal = isCallable(configDef.global)
+ const errBeg =
+ `${filePathAbsoluteUserRootDir} (which is a local config file) sets the config ${pc.cyan(configName)}` as const
+ const errMid = !isConditionallyGlobal
+ ? ("but it's a global config" as const)
+ : ('to a value that is global' as const)
+ const what = isConditionallyGlobal ? ('global values' as const) : pc.cyan(configName)
+ const errEnd =
configFilePathsGlobal.length > 0
- ? `define ${pc.cyan(configName)} at ${joinEnglish(configFilePathsGlobal, 'or')} instead.`
- : `create a global config (e.g. /pages/+config.js) and define ${pc.cyan(configName)} there instead.`
- ].join(' '),
- { onlyOnce: true }
- )
+ ? (`define ${what} at a global config file such as ${joinEnglish(configFilePathsGlobal, 'or')} instead` as const)
+ : (`create a global config file (e.g. /pages/+config.js) and define ${what} there instead` as const)
+ // When updating this error message => also update error message at https://vike.dev/warning/global-config
+ const errMsg = `${errBeg} ${errMid}: ${errEnd} (https://vike.dev/warning/global-config).` as const
+ assertWarning(false, errMsg, { onlyOnce: true })
+ }
})
}
function assertPageConfigs(pageConfigs: PageConfigBuildTime[]) {