vike 0.4.146 → 0.4.147-commit-f9a91f3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/node/plugin/index.js +6 -4
- package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +3 -4
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.js +76 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +61 -40
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +104 -0
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +62 -75
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +43 -17
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +12 -70
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +11 -8
- package/dist/cjs/node/plugin/shared/{getConfigValueSourcesRelevant.js → getConfigValueSourcesNotOverriden.js} +3 -3
- package/dist/cjs/node/plugin/utils.js +2 -0
- package/dist/cjs/node/prerender/runPrerender.js +75 -67
- package/dist/cjs/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
- package/dist/cjs/node/runtime/index-common.js +3 -1
- package/dist/cjs/node/runtime/renderPage/analyzePage.js +2 -2
- package/dist/cjs/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +12 -12
- package/dist/cjs/node/runtime/renderPage/createHttpResponseObject.js +3 -3
- package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -2
- package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +1 -1
- package/dist/cjs/node/runtime/renderPage.js +75 -51
- package/dist/cjs/shared/getPageFiles/analyzePageClientSide/determineClientEntry.js +1 -0
- package/dist/cjs/shared/page-configs/loadConfigValues.js +12 -3
- package/dist/cjs/shared/page-configs/serialize/parseConfigValuesSerialized.js +19 -0
- package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +3 -12
- package/dist/cjs/shared/route/resolveRedirects.js +8 -5
- package/dist/cjs/utils/assertKeys.js +28 -0
- package/dist/cjs/utils/joinEnglish.js +3 -3
- package/dist/cjs/utils/parseUrl-extras.js +22 -8
- package/dist/cjs/utils/parseUrl.js +24 -16
- package/dist/cjs/utils/projectInfo.js +3 -2
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +25 -11
- package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
- package/dist/esm/client/client-routing-runtime/index.js +1 -0
- package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +2 -2
- package/dist/esm/client/shared/getPageContextSerializedInHtml.js +1 -1
- package/dist/esm/node/plugin/index.d.ts +1 -0
- package/dist/esm/node/plugin/index.js +1 -0
- package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +3 -4
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.d.ts +5 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.js +70 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +58 -37
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +5 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +98 -0
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +63 -76
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +43 -17
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +0 -3
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +13 -68
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +11 -8
- package/dist/esm/node/plugin/shared/getConfigValueSourcesNotOverriden.d.ts +5 -0
- package/dist/esm/node/plugin/shared/{getConfigValueSourcesRelevant.js → getConfigValueSourcesNotOverriden.js} +2 -2
- package/dist/esm/node/plugin/utils.d.ts +2 -0
- package/dist/esm/node/plugin/utils.js +2 -0
- package/dist/esm/node/prerender/runPrerender.js +75 -67
- package/dist/esm/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
- package/dist/esm/node/runtime/index-common.d.ts +1 -0
- package/dist/esm/node/runtime/index-common.js +1 -0
- package/dist/esm/node/runtime/renderPage/analyzePage.js +2 -2
- package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.d.ts +1 -1
- package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +13 -13
- package/dist/esm/node/runtime/renderPage/createHttpResponseObject.d.ts +1 -1
- package/dist/esm/node/runtime/renderPage/createHttpResponseObject.js +3 -3
- package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -2
- package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +1 -1
- package/dist/esm/node/runtime/renderPage.js +76 -52
- package/dist/esm/shared/getPageFiles/analyzePageClientSide/determineClientEntry.js +1 -0
- package/dist/esm/shared/page-configs/PageConfig.d.ts +14 -4
- package/dist/esm/shared/page-configs/loadConfigValues.js +12 -3
- package/dist/esm/shared/page-configs/serialize/parseConfigValuesSerialized.d.ts +4 -0
- package/dist/esm/shared/page-configs/serialize/parseConfigValuesSerialized.js +16 -0
- package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +4 -13
- package/dist/esm/shared/route/resolveRedirects.js +8 -5
- package/dist/esm/utils/assertKeys.d.ts +4 -0
- package/dist/esm/utils/assertKeys.js +22 -0
- package/dist/esm/utils/joinEnglish.d.ts +1 -1
- package/dist/esm/utils/joinEnglish.js +3 -3
- package/dist/esm/utils/parseUrl-extras.d.ts +3 -1
- package/dist/esm/utils/parseUrl-extras.js +21 -7
- package/dist/esm/utils/parseUrl.js +24 -16
- package/dist/esm/utils/projectInfo.d.ts +3 -1
- package/dist/esm/utils/projectInfo.js +2 -1
- package/package.json +3 -3
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +0 -28
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.d.ts +0 -5
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +0 -25
- package/dist/esm/node/plugin/shared/getConfigValueSourcesRelevant.d.ts +0 -5
|
@@ -27,7 +27,7 @@ async function getPageContextFromHooks_firstRender(pageContext) {
|
|
|
27
27
|
objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
|
|
28
28
|
{
|
|
29
29
|
const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
|
|
30
|
-
if (
|
|
30
|
+
if (onBeforeRenderClientOnlyExists(pageContextForHook)) {
|
|
31
31
|
const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
|
|
32
32
|
objectAssign(pageContextFromHooks, pageContextFromHook);
|
|
33
33
|
}
|
|
@@ -57,13 +57,17 @@ async function getPageContextFromHooks_uponNavigation(pageContext) {
|
|
|
57
57
|
}
|
|
58
58
|
async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
59
59
|
let pageContextFromHooks = {};
|
|
60
|
+
objectAssign(pageContextFromHooks, { _hasPageContextFromClient: false });
|
|
60
61
|
objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContext._pageId, pageContext));
|
|
62
|
+
let pageContextFetchedFromServer = false;
|
|
61
63
|
// Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
|
|
62
64
|
if (
|
|
63
65
|
// For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
|
|
64
66
|
!isErrorPage &&
|
|
67
|
+
// true if pageContextInit has some client data or the onBeforeRender hook is server-side only:
|
|
65
68
|
(await hasPageContextServer({ ...pageContext, ...pageContextFromHooks }))) {
|
|
66
69
|
const pageContextFromServer = await fetchPageContextFromServer(pageContext);
|
|
70
|
+
pageContextFetchedFromServer = true;
|
|
67
71
|
if (!pageContextFromServer['_isError']) {
|
|
68
72
|
objectAssign(pageContextFromHooks, pageContextFromServer);
|
|
69
73
|
}
|
|
@@ -72,6 +76,7 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
|
72
76
|
assert(errorPageId);
|
|
73
77
|
pageContextFromHooks = {};
|
|
74
78
|
objectAssign(pageContextFromHooks, {
|
|
79
|
+
_hasPageContextFromClient: false,
|
|
75
80
|
isHydration: false,
|
|
76
81
|
_pageId: errorPageId
|
|
77
82
|
});
|
|
@@ -91,25 +96,29 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
|
|
|
91
96
|
if (!isErrorPage) {
|
|
92
97
|
// Should we really call the guard() hook on the client-side? Shouldn't we make the guard() hook a server-side only hook? Or maybe make its env configurable like onBeforeRender()?
|
|
93
98
|
await executeGuardHook({
|
|
94
|
-
_hasPageContextFromClient: false,
|
|
95
99
|
...pageContext,
|
|
96
100
|
...pageContextFromHooks
|
|
97
101
|
}, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
|
|
98
102
|
}
|
|
99
103
|
}
|
|
104
|
+
// For the error page, we also execute the client-side onBeforeRender() hook, but maybe we shouldn't? The server-side does it as well (but maybe it shouldn't).
|
|
100
105
|
{
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
106
|
+
const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
|
|
107
|
+
if (onBeforeRenderClientOnlyExists(pageContextForHook) || !pageContextFetchedFromServer) {
|
|
108
|
+
// This won't do anything if no hook has been defined or if the hook's env.client is false.
|
|
109
|
+
const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
|
|
110
|
+
objectAssign(pageContextFromHooks, pageContextFromHook);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
assert(pageContextFetchedFromServer);
|
|
114
|
+
}
|
|
107
115
|
}
|
|
108
116
|
return pageContextFromHooks;
|
|
109
117
|
}
|
|
110
118
|
async function executeOnBeforeRenderHookClientSide(pageContext) {
|
|
111
119
|
const hook = getHook(pageContext, 'onBeforeRender');
|
|
112
120
|
if (!hook) {
|
|
121
|
+
// No hook defined or hook's env.client is false
|
|
113
122
|
const pageContextFromOnBeforeRender = {
|
|
114
123
|
_hasPageContextFromClient: false
|
|
115
124
|
};
|
|
@@ -153,7 +162,9 @@ async function onBeforeRenderServerOnlyExists(pageContext) {
|
|
|
153
162
|
if (pageContext._pageConfigs.length > 0) {
|
|
154
163
|
// V1
|
|
155
164
|
const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
|
|
156
|
-
|
|
165
|
+
const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
|
|
166
|
+
assert(isObject(onBeforeRenderEnv));
|
|
167
|
+
return !!onBeforeRenderEnv.server && !onBeforeRenderEnv.client;
|
|
157
168
|
}
|
|
158
169
|
else {
|
|
159
170
|
// TODO/v1-release: remove
|
|
@@ -162,14 +173,17 @@ async function onBeforeRenderServerOnlyExists(pageContext) {
|
|
|
162
173
|
return hasOnBeforeRenderServerSideOnlyHook;
|
|
163
174
|
}
|
|
164
175
|
}
|
|
165
|
-
|
|
176
|
+
function onBeforeRenderClientOnlyExists(pageContext) {
|
|
166
177
|
if (pageContext._pageConfigs.length > 0) {
|
|
167
178
|
// V1
|
|
168
179
|
const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
|
|
169
|
-
|
|
180
|
+
const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
|
|
181
|
+
assert(isObject(onBeforeRenderEnv));
|
|
182
|
+
return !!onBeforeRenderEnv.client && !onBeforeRenderEnv.server;
|
|
170
183
|
}
|
|
171
184
|
else {
|
|
172
185
|
// TODO/v1-release: remove
|
|
186
|
+
// Client-only onBeforeRender() hooks were never supported for the V0.4 design
|
|
173
187
|
return false;
|
|
174
188
|
}
|
|
175
189
|
}
|
|
@@ -14,8 +14,8 @@ function onBrowserHistoryNavigation() {
|
|
|
14
14
|
// - By user clicking on a hash link `<a href="#some-hash" />`
|
|
15
15
|
// - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
|
|
16
16
|
// - By JavaScript: `location.hash = 'some-hash'`
|
|
17
|
-
// - The `event` of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
|
|
18
|
-
window.addEventListener('popstate', () => {
|
|
17
|
+
// - The `event` argument of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
|
|
18
|
+
window.addEventListener('popstate', (ev) => {
|
|
19
19
|
const currentState = getState();
|
|
20
20
|
const scrollTarget = currentState.historyState.scrollPosition || 'scroll-to-top-or-hash';
|
|
21
21
|
const isUserLandPushStateNavigation = currentState.historyState.triggedBy === 'user';
|
|
@@ -4,7 +4,7 @@ export { getPageContextSerializedInHtml };
|
|
|
4
4
|
function getPageContextSerializedInHtml() {
|
|
5
5
|
const id = 'vike_pageContext';
|
|
6
6
|
const elem = document.getElementById(id);
|
|
7
|
-
assertUsage(elem, `The element #${id} (which
|
|
7
|
+
assertUsage(elem, `The element #${id} (which Vike automatically injects into the HTML) is missing from the DOM. This may happen if your HTML is malformed. Make sure your HTML isn't malformed, and make sure you don't remove #${id} from the HTML nor from the DOM.`);
|
|
8
8
|
const pageContextJson = elem.textContent;
|
|
9
9
|
assert(pageContextJson);
|
|
10
10
|
const pageContextSerializedInHtml = parse(pageContextJson);
|
|
@@ -2,5 +2,6 @@ export default plugin;
|
|
|
2
2
|
export { plugin };
|
|
3
3
|
export { plugin as ssr };
|
|
4
4
|
export type { ConfigVikeUserProvided as UserConfig };
|
|
5
|
+
export { PROJECT_VERSION as version } from './utils.js';
|
|
5
6
|
import type { ConfigVikeUserProvided } from '../../shared/ConfigVike.js';
|
|
6
7
|
declare function plugin(vikeConfig?: ConfigVikeUserProvided): any;
|
|
@@ -2,6 +2,7 @@ export default plugin;
|
|
|
2
2
|
export { plugin };
|
|
3
3
|
// TODO/v1-release: remove
|
|
4
4
|
export { plugin as ssr };
|
|
5
|
+
export { PROJECT_VERSION as version } from './utils.js';
|
|
5
6
|
import { assertUsage, markEnvAsVite } from './utils.js';
|
|
6
7
|
import { buildConfig } from './plugins/buildConfig.js';
|
|
7
8
|
import { previewConfig } from './plugins/previewConfig.js';
|
|
@@ -2,7 +2,7 @@ export { determineOptimizeDeps };
|
|
|
2
2
|
import { findPageFiles } from '../../shared/findPageFiles.js';
|
|
3
3
|
import { assert, getFilePathAbsolute, isNotNullish, isNpmPackageImport, unique } from '../../utils.js';
|
|
4
4
|
import { getVikeConfig } from '../importUserCode/v1-design/getVikeConfig.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getConfigValueSourcesNotOverriden } from '../../shared/getConfigValueSourcesNotOverriden.js';
|
|
6
6
|
import { analyzeClientEntries } from '../buildConfig.js';
|
|
7
7
|
import { virtualFileIdImportUserCodeClientCR, virtualFileIdImportUserCodeClientSR } from '../../../shared/virtual-files/virtualFileImportUserCode.js';
|
|
8
8
|
async function determineOptimizeDeps(config, configVike, isDev) {
|
|
@@ -30,12 +30,11 @@ async function getPageDeps(config, pageConfigs, isDev) {
|
|
|
30
30
|
// V1 design
|
|
31
31
|
{
|
|
32
32
|
pageConfigs.forEach((pageConfig) => {
|
|
33
|
-
|
|
34
|
-
configValueSourcesRelevant.forEach((configValueSource) => {
|
|
33
|
+
getConfigValueSourcesNotOverriden(pageConfig).forEach((configValueSource) => {
|
|
35
34
|
if (!configValueSource.valueIsImportedAtRuntime)
|
|
36
35
|
return;
|
|
37
36
|
const { definedAt, configEnv } = configValueSource;
|
|
38
|
-
if (configEnv
|
|
37
|
+
if (!configEnv.client)
|
|
39
38
|
return;
|
|
40
39
|
if (definedAt.filePathRelativeToUserRootDir !== null) {
|
|
41
40
|
const { filePathAbsoluteFilesystem } = definedAt;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { getConfigValuesSerialized };
|
|
2
|
+
export { assertConfigValueIsSerializable };
|
|
3
|
+
import type { ConfigEnvInternal, ConfigValueSource, DefinedAt, PageConfigBuildTime } from '../../../../../shared/page-configs/PageConfig.js';
|
|
4
|
+
declare function getConfigValuesSerialized(pageConfig: PageConfigBuildTime, isEnvMatch: (configEnv: ConfigEnvInternal, configValueSource?: ConfigValueSource) => boolean): string;
|
|
5
|
+
declare function assertConfigValueIsSerializable(value: unknown, configName: string, definedAt: DefinedAt): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export { getConfigValuesSerialized };
|
|
2
|
+
export { assertConfigValueIsSerializable };
|
|
3
|
+
import { assert, assertUsage, getPropAccessNotation } from '../../../utils.js';
|
|
4
|
+
import { isJsonSerializerError, stringify } from '@brillout/json-serializer/stringify';
|
|
5
|
+
import pc from '@brillout/picocolors';
|
|
6
|
+
import { getConfigValueFilePathToShowToUser } from '../../../../../shared/page-configs/helpers.js';
|
|
7
|
+
import { serializeConfigValue } from '../../../../../shared/page-configs/serialize/serializeConfigValue.js';
|
|
8
|
+
import { getConfigValueSourcesNotOverriden } from '../../../shared/getConfigValueSourcesNotOverriden.js';
|
|
9
|
+
function getConfigValuesSerialized(pageConfig, isEnvMatch) {
|
|
10
|
+
const lines = [];
|
|
11
|
+
Object.entries(pageConfig.configValuesComputed).forEach(([configName, configValuesComputed]) => {
|
|
12
|
+
const { value, configEnv } = configValuesComputed;
|
|
13
|
+
if (!isEnvMatch(configEnv))
|
|
14
|
+
return;
|
|
15
|
+
// configValeSources has higher precedence
|
|
16
|
+
if (pageConfig.configValueSources[configName])
|
|
17
|
+
return;
|
|
18
|
+
const configValue = pageConfig.configValues[configName];
|
|
19
|
+
assert(configValue);
|
|
20
|
+
const { definedAt } = configValue;
|
|
21
|
+
const valueSerialized = getConfigValueSerialized(value, configName, definedAt);
|
|
22
|
+
serializeConfigValue(lines, configName, { definedAt, valueSerialized });
|
|
23
|
+
});
|
|
24
|
+
getConfigValueSourcesNotOverriden(pageConfig).forEach((configValueSource) => {
|
|
25
|
+
const { configName, configEnv } = configValueSource;
|
|
26
|
+
const configValue = pageConfig.configValues[configName];
|
|
27
|
+
if (!configValue)
|
|
28
|
+
return;
|
|
29
|
+
if (!isEnvMatch(configEnv, configValueSource)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const { value, definedAt } = configValue;
|
|
33
|
+
const valueSerialized = getConfigValueSerialized(value, configName, definedAt);
|
|
34
|
+
serializeConfigValue(lines, configName, { definedAt, valueSerialized });
|
|
35
|
+
});
|
|
36
|
+
const code = lines.join('\n');
|
|
37
|
+
return code;
|
|
38
|
+
}
|
|
39
|
+
function assertConfigValueIsSerializable(value, configName, definedAt) {
|
|
40
|
+
// Contains asserts
|
|
41
|
+
getConfigValueSerialized(value, configName, definedAt);
|
|
42
|
+
}
|
|
43
|
+
function getConfigValueSerialized(value, configName, definedAt) {
|
|
44
|
+
const valueName = `config${getPropAccessNotation(configName)}`;
|
|
45
|
+
let configValueSerialized;
|
|
46
|
+
try {
|
|
47
|
+
configValueSerialized = stringify(value, { valueName, forbidReactElements: true });
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
let serializationErrMsg = '';
|
|
51
|
+
if (isJsonSerializerError(err)) {
|
|
52
|
+
serializationErrMsg = err.messageCore;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// When a property getter throws an error
|
|
56
|
+
console.error('Serialization error:');
|
|
57
|
+
console.error(err);
|
|
58
|
+
serializationErrMsg = 'see serialization error printed above';
|
|
59
|
+
}
|
|
60
|
+
const configValueFilePathToShowToUser = getConfigValueFilePathToShowToUser({ definedAt });
|
|
61
|
+
assert(configValueFilePathToShowToUser);
|
|
62
|
+
assertUsage(false, [
|
|
63
|
+
`The value of the config ${pc.cyan(configName)} cannot be defined inside the file ${configValueFilePathToShowToUser}:`,
|
|
64
|
+
`its value must be defined in an another file and then imported by ${configValueFilePathToShowToUser}. (Because its value isn't serializable: ${serializationErrMsg}.)`,
|
|
65
|
+
`Only serializable config values can be defined inside +config.h.js files, see https://vike.dev/header-file.`
|
|
66
|
+
].join(' '));
|
|
67
|
+
}
|
|
68
|
+
configValueSerialized = JSON.stringify(configValueSerialized);
|
|
69
|
+
return configValueSerialized;
|
|
70
|
+
}
|
|
@@ -1,98 +1,119 @@
|
|
|
1
1
|
export { configDefinitionsBuiltIn };
|
|
2
2
|
export { configDefinitionsBuiltInGlobal };
|
|
3
|
-
import {
|
|
3
|
+
import { assert } from '../../../../utils.js';
|
|
4
4
|
const configDefinitionsBuiltIn = {
|
|
5
5
|
onRenderHtml: {
|
|
6
|
-
env:
|
|
6
|
+
env: { server: true }
|
|
7
7
|
},
|
|
8
8
|
onRenderClient: {
|
|
9
|
-
env:
|
|
9
|
+
env: { client: true }
|
|
10
10
|
},
|
|
11
11
|
onHydrationEnd: {
|
|
12
|
-
env:
|
|
12
|
+
env: { client: true }
|
|
13
13
|
},
|
|
14
14
|
onPageTransitionStart: {
|
|
15
|
-
env:
|
|
15
|
+
env: { client: true }
|
|
16
16
|
},
|
|
17
17
|
onPageTransitionEnd: {
|
|
18
|
-
env:
|
|
18
|
+
env: { client: true }
|
|
19
19
|
},
|
|
20
20
|
onBeforeRender: {
|
|
21
|
-
env:
|
|
21
|
+
env: { server: true }
|
|
22
22
|
},
|
|
23
23
|
onBeforePrerenderStart: {
|
|
24
|
-
env:
|
|
24
|
+
env: { server: true }
|
|
25
25
|
},
|
|
26
26
|
Page: {
|
|
27
|
-
env:
|
|
27
|
+
env: { server: true, client: true }
|
|
28
28
|
},
|
|
29
29
|
passToClient: {
|
|
30
|
-
env:
|
|
30
|
+
env: { server: true, config: true },
|
|
31
31
|
cumulative: true
|
|
32
32
|
},
|
|
33
33
|
route: {
|
|
34
|
-
env: '
|
|
34
|
+
env: { server: true, client: 'if-client-routing', eager: true }
|
|
35
35
|
},
|
|
36
36
|
guard: {
|
|
37
|
-
env: '
|
|
37
|
+
env: { server: true, client: 'if-client-routing' }
|
|
38
38
|
},
|
|
39
39
|
iKnowThePerformanceRisksOfAsyncRouteFunctions: {
|
|
40
|
-
env: '
|
|
40
|
+
env: { server: true, client: 'if-client-routing', eager: true }
|
|
41
41
|
},
|
|
42
42
|
filesystemRoutingRoot: {
|
|
43
|
-
env:
|
|
43
|
+
env: { config: true }
|
|
44
44
|
},
|
|
45
45
|
client: {
|
|
46
46
|
// The value of the client config is merely the file path to the client entry file, which is only needed on the sever-side
|
|
47
|
-
env:
|
|
47
|
+
env: { server: true },
|
|
48
48
|
_valueIsFilePath: true
|
|
49
49
|
},
|
|
50
50
|
clientRouting: {
|
|
51
|
-
// We could make it
|
|
52
|
-
env:
|
|
51
|
+
// We could make it { client: false } but we don't yet because of some legacy V0.4 design code
|
|
52
|
+
env: { server: true, client: true, config: true, eager: true }
|
|
53
53
|
},
|
|
54
54
|
prerender: {
|
|
55
|
-
env:
|
|
55
|
+
env: { config: true }
|
|
56
56
|
},
|
|
57
57
|
hydrationCanBeAborted: {
|
|
58
|
-
env:
|
|
58
|
+
env: { client: true }
|
|
59
59
|
},
|
|
60
60
|
prefetchStaticAssets: {
|
|
61
|
-
env:
|
|
61
|
+
env: { client: true }
|
|
62
62
|
},
|
|
63
63
|
extends: {
|
|
64
|
-
env:
|
|
64
|
+
env: { config: true }
|
|
65
65
|
},
|
|
66
66
|
meta: {
|
|
67
|
-
env:
|
|
67
|
+
env: { config: true }
|
|
68
68
|
},
|
|
69
69
|
isClientSideRenderable: {
|
|
70
|
-
env:
|
|
70
|
+
env: { server: true, client: true, eager: true },
|
|
71
71
|
_computed: (configValueSources) => isConfigSet(configValueSources, 'onRenderClient') &&
|
|
72
72
|
isConfigSet(configValueSources, 'Page') &&
|
|
73
|
-
getConfigEnv(configValueSources, 'Page')
|
|
73
|
+
!!getConfigEnv(configValueSources, 'Page')?.client
|
|
74
74
|
},
|
|
75
75
|
onBeforeRenderEnv: {
|
|
76
|
-
env:
|
|
76
|
+
env: { client: true },
|
|
77
77
|
_computed: (configValueSources) => !isConfigSet(configValueSources, 'onBeforeRender') ? null : getConfigEnv(configValueSources, 'onBeforeRender')
|
|
78
78
|
}
|
|
79
79
|
};
|
|
80
80
|
const configDefinitionsBuiltInGlobal = {
|
|
81
81
|
onPrerenderStart: {
|
|
82
|
-
env:
|
|
82
|
+
env: { server: true }
|
|
83
83
|
},
|
|
84
84
|
onBeforeRoute: {
|
|
85
|
-
env: '
|
|
85
|
+
env: { server: true, client: 'if-client-routing', eager: true }
|
|
86
86
|
},
|
|
87
87
|
prerender: {
|
|
88
|
-
env:
|
|
89
|
-
},
|
|
90
|
-
extensions: { env:
|
|
91
|
-
disableAutoFullBuild: { env:
|
|
92
|
-
includeAssetsImportedByServer: { env:
|
|
93
|
-
baseAssets: { env:
|
|
94
|
-
baseServer: { env:
|
|
95
|
-
redirects: { env:
|
|
96
|
-
trailingSlash: { env:
|
|
97
|
-
disableUrlNormalization: { env:
|
|
88
|
+
env: { config: true }
|
|
89
|
+
},
|
|
90
|
+
extensions: { env: { config: true } },
|
|
91
|
+
disableAutoFullBuild: { env: { config: true } },
|
|
92
|
+
includeAssetsImportedByServer: { env: { config: true } },
|
|
93
|
+
baseAssets: { env: { config: true } },
|
|
94
|
+
baseServer: { env: { config: true } },
|
|
95
|
+
redirects: { env: { server: true } },
|
|
96
|
+
trailingSlash: { env: { server: true } },
|
|
97
|
+
disableUrlNormalization: { env: { server: true } }
|
|
98
98
|
};
|
|
99
|
+
function getConfigEnv(configValueSources, configName) {
|
|
100
|
+
const configValueSource = getConfigValueSource(configValueSources, configName);
|
|
101
|
+
if (!configValueSource)
|
|
102
|
+
return null;
|
|
103
|
+
return configValueSource.configEnv;
|
|
104
|
+
}
|
|
105
|
+
function isConfigSet(configValueSources, configName) {
|
|
106
|
+
const configValueSource = getConfigValueSource(configValueSources, configName);
|
|
107
|
+
// Enable users to suppress global config values by overriding the config's value to null
|
|
108
|
+
if (configValueSource?.value === null)
|
|
109
|
+
return false;
|
|
110
|
+
return !!configValueSource;
|
|
111
|
+
}
|
|
112
|
+
function getConfigValueSource(configValueSources, configName) {
|
|
113
|
+
const sources = configValueSources[configName];
|
|
114
|
+
if (!sources)
|
|
115
|
+
return null;
|
|
116
|
+
const configValueSource = sources[0];
|
|
117
|
+
assert(configValueSource);
|
|
118
|
+
return configValueSource;
|
|
119
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export { crawlPlusFiles };
|
|
2
|
+
import { assertPosixPath, assert, toPosixPath, assertWarning, scriptFileExtensionList, scriptFileExtensions } from '../../../../utils.js';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import glob from 'fast-glob';
|
|
5
|
+
import { exec } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
7
|
+
const execA = promisify(exec);
|
|
8
|
+
async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem, isDev) {
|
|
9
|
+
assertPosixPath(userRootDir);
|
|
10
|
+
assertPosixPath(outDirAbsoluteFilesystem);
|
|
11
|
+
assert(outDirAbsoluteFilesystem.startsWith(userRootDir));
|
|
12
|
+
const outDir = path.posix.relative(userRootDir, outDirAbsoluteFilesystem);
|
|
13
|
+
assert(!outDir.startsWith('.'));
|
|
14
|
+
const timeBase = new Date().getTime();
|
|
15
|
+
let files = [];
|
|
16
|
+
const res = await gitLsFiles(userRootDir, outDir);
|
|
17
|
+
if (res &&
|
|
18
|
+
// Fallback to fast-glob for users that dynamically generate plus files (we assume generetad plus files to be skipped because they are usually included in .gitignore)
|
|
19
|
+
res.length > 0) {
|
|
20
|
+
files = res;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
files = await fastGlob(userRootDir, outDir);
|
|
24
|
+
}
|
|
25
|
+
{
|
|
26
|
+
const time = new Date().getTime() - timeBase;
|
|
27
|
+
if (isDev) {
|
|
28
|
+
// We only warn in dev, because while building it's expected to take a long time as fast-glob is competing for resources with other tasks
|
|
29
|
+
assertWarning(time < 2 * 1000, `Crawling your user files took an unexpected long time (${time}ms). Create a new issue on Vike's GitHub.`, {
|
|
30
|
+
onlyOnce: 'slow-page-files-search'
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const plusFiles = files.map((p) => {
|
|
35
|
+
p = toPosixPath(p);
|
|
36
|
+
assert(!p.startsWith(userRootDir));
|
|
37
|
+
const filePathRelativeToUserRootDir = path.posix.join('/', p);
|
|
38
|
+
const filePathAbsoluteFilesystem = path.posix.join(userRootDir, p);
|
|
39
|
+
return {
|
|
40
|
+
filePathRelativeToUserRootDir,
|
|
41
|
+
filePathAbsoluteFilesystem
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
return plusFiles;
|
|
45
|
+
}
|
|
46
|
+
// Same as fastGlob() but using `$ git ls-files`
|
|
47
|
+
async function gitLsFiles(userRootDir, outDir) {
|
|
48
|
+
const cmd = [
|
|
49
|
+
'git ls-files',
|
|
50
|
+
...scriptFileExtensionList.map((ext) => `"**/+*.${ext}"`),
|
|
51
|
+
...getIgnorePatterns(outDir).map((pattern) => `--exclude="${pattern}"`),
|
|
52
|
+
// --others lists untracked files only (but using .gitignore because --exclude-standard)
|
|
53
|
+
// --cached adds the tracked files to the output
|
|
54
|
+
'--others --cached --exclude-standard'
|
|
55
|
+
].join(' ');
|
|
56
|
+
let stdout;
|
|
57
|
+
try {
|
|
58
|
+
const res = await execA(cmd, { cwd: userRootDir });
|
|
59
|
+
stdout = res.stdout;
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
if (err.message.includes('not a git repository'))
|
|
63
|
+
return null;
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
let files = stdout.split('\n').filter(Boolean);
|
|
67
|
+
assert(!outDir.startsWith('/'));
|
|
68
|
+
files = files.filter(
|
|
69
|
+
// We have to repeat the same exclusion logic here because the `git ls-files` option --exclude only applies to untracked files. (We use --exclude only to speed up the command.)
|
|
70
|
+
(file) => getIgnoreFilter(file, outDir));
|
|
71
|
+
return files;
|
|
72
|
+
}
|
|
73
|
+
// Same as gitLsFiles() but using fast-glob
|
|
74
|
+
async function fastGlob(userRootDir, outDir) {
|
|
75
|
+
const files = await glob(`**/+*.${scriptFileExtensions}`, {
|
|
76
|
+
ignore: getIgnorePatterns(outDir),
|
|
77
|
+
cwd: userRootDir,
|
|
78
|
+
dot: false
|
|
79
|
+
});
|
|
80
|
+
return files;
|
|
81
|
+
}
|
|
82
|
+
// Same as getIgnoreFilter() but as glob pattern
|
|
83
|
+
function getIgnorePatterns(outDir) {
|
|
84
|
+
return [
|
|
85
|
+
'**/node_modules/**',
|
|
86
|
+
`${outDir}/**`,
|
|
87
|
+
// Allow:
|
|
88
|
+
// ```
|
|
89
|
+
// +Page.js
|
|
90
|
+
// +Page.telefunc.js
|
|
91
|
+
// ```
|
|
92
|
+
'**/*.telefunc.*'
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
// Same as getIgnorePatterns() but for Array.filter()
|
|
96
|
+
function getIgnoreFilter(file, outDir) {
|
|
97
|
+
return !file.includes('node_modules/') && !file.includes('.telefunc.') && !file.startsWith(`${outDir}/`);
|
|
98
|
+
}
|