vike 0.4.150-commit-d9acc70 → 0.4.150-commit-d0822a3

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.
Files changed (59) hide show
  1. package/dist/cjs/node/plugin/index.js +0 -2
  2. package/dist/cjs/node/plugin/plugins/autoFullBuild.js +3 -2
  3. package/dist/cjs/node/plugin/plugins/buildConfig.js +17 -36
  4. package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -1
  5. package/dist/cjs/node/plugin/plugins/config/resolveExtensions.js +1 -1
  6. package/dist/cjs/node/plugin/plugins/config/stemUtils.js +1 -1
  7. package/dist/cjs/node/plugin/plugins/devConfig/determineFsAllowList.js +1 -1
  8. package/dist/cjs/node/plugin/plugins/importBuild/getVikeManifest.js +38 -0
  9. package/dist/cjs/node/plugin/plugins/importBuild/index.js +50 -18
  10. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +7 -0
  11. package/dist/cjs/node/plugin/utils.js +1 -0
  12. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +2 -1
  13. package/dist/cjs/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +33 -0
  14. package/dist/cjs/node/runtime/renderPage/getPageAssets.js +1 -1
  15. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +4 -4
  16. package/dist/cjs/utils/getDependencyPackageJson.js +1 -1
  17. package/dist/cjs/utils/getFilePathAbsolute.js +1 -1
  18. package/dist/cjs/utils/injectRollupInputs.js +29 -0
  19. package/dist/cjs/utils/isPlainObject.js +1 -1
  20. package/dist/cjs/utils/projectInfo.js +1 -1
  21. package/dist/cjs/utils/requireResolve.js +1 -1
  22. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +105 -66
  23. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +1 -1
  24. package/dist/esm/node/plugin/index.js +0 -2
  25. package/dist/esm/node/plugin/plugins/autoFullBuild.js +3 -2
  26. package/dist/esm/node/plugin/plugins/buildConfig.js +17 -36
  27. package/dist/esm/node/plugin/plugins/commonConfig.js +1 -1
  28. package/dist/esm/node/plugin/plugins/config/resolveExtensions.js +1 -1
  29. package/dist/esm/node/plugin/plugins/config/stemUtils.js +1 -1
  30. package/dist/esm/node/plugin/plugins/devConfig/determineFsAllowList.js +1 -1
  31. package/dist/esm/node/plugin/plugins/importBuild/getVikeManifest.d.ts +5 -0
  32. package/dist/esm/node/plugin/plugins/importBuild/getVikeManifest.js +32 -0
  33. package/dist/esm/node/plugin/plugins/importBuild/index.js +52 -20
  34. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +7 -0
  35. package/dist/esm/node/plugin/utils.d.ts +1 -0
  36. package/dist/esm/node/plugin/utils.js +1 -0
  37. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +2 -1
  38. package/dist/esm/node/runtime/renderPage/{executeOnBeforeRenderHook.d.ts → executeOnBeforeRenderAndDataHooks.d.ts} +2 -2
  39. package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +30 -0
  40. package/dist/esm/node/runtime/renderPage/getPageAssets.js +1 -1
  41. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +4 -4
  42. package/dist/esm/shared/VikeNamespace.d.ts +2 -1
  43. package/dist/esm/shared/page-configs/Config.d.ts +22 -5
  44. package/dist/esm/shared/types.d.ts +5 -0
  45. package/dist/esm/types/index.d.ts +1 -1
  46. package/dist/esm/utils/getDependencyPackageJson.js +1 -1
  47. package/dist/esm/utils/getFilePathAbsolute.js +1 -1
  48. package/dist/esm/utils/injectRollupInputs.d.ts +7 -0
  49. package/dist/esm/utils/injectRollupInputs.js +26 -0
  50. package/dist/esm/utils/isPlainObject.js +1 -1
  51. package/dist/esm/utils/projectInfo.d.ts +2 -2
  52. package/dist/esm/utils/projectInfo.js +1 -1
  53. package/dist/esm/utils/requireResolve.js +1 -1
  54. package/package.json +9 -2
  55. package/dist/cjs/node/plugin/plugins/manifest.js +0 -59
  56. package/dist/cjs/node/runtime/renderPage/executeOnBeforeRenderHook.js +0 -23
  57. package/dist/esm/node/plugin/plugins/manifest.d.ts +0 -3
  58. package/dist/esm/node/plugin/plugins/manifest.js +0 -53
  59. package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderHook.js +0 -20
@@ -25,10 +25,10 @@ async function getPageContextFromHooks_firstRender(pageContext) {
25
25
  _hasPageContextFromClient: false
26
26
  });
27
27
  objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
28
- {
28
+ for (const hookName of ['data', 'onBeforeRender']) {
29
29
  const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
30
- if (onBeforeRenderClientOnlyExists(pageContextForHook)) {
31
- const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
30
+ if (hookClientOnlyExists(hookName, pageContextForHook)) {
31
+ const pageContextFromHook = await executeHookClientSide(hookName, pageContextForHook);
32
32
  objectAssign(pageContextFromHooks, pageContextFromHook);
33
33
  }
34
34
  }
@@ -56,31 +56,34 @@ async function getPageContextFromHooks_uponNavigation(pageContext) {
56
56
  return pageContextFromHooks;
57
57
  }
58
58
  async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
59
- let pageContextFromHooks = {};
60
- objectAssign(pageContextFromHooks, { _hasPageContextFromClient: false });
61
- objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContext._pageId, pageContext));
62
- let pageContextFetchedFromServer = false;
63
- // Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
59
+ const getPageContextFromHooksInit = async (pageId) => {
60
+ const pageContextFromHooks = {
61
+ _hasPageContextFromClient: false,
62
+ _pageId: pageId
63
+ };
64
+ const pageContextFromPageFiles = await loadPageFilesClientSide(pageId, pageContext);
65
+ objectAssign(pageContextFromHooks, pageContextFromPageFiles);
66
+ return pageContextFromHooks;
67
+ };
68
+ let pageContextFromHooks = await getPageContextFromHooksInit(pageContext._pageId);
69
+ let hasPageContextFromServer = false;
70
+ // If pageContextInit has some client data or if one of the hooks guard(), data() or onBeforeRender() is server-side
71
+ // only, then we need to fetch pageContext from the server.
72
+ // We do it before executing any client-side hook, because it contains pageContextInit which may be needed for guard() / data() / onBeforeRender(), for example pageContextInit.user is crucial for guard()
64
73
  if (
65
74
  // For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
66
75
  !isErrorPage &&
67
- // true if pageContextInit has some client data or the onBeforeRender hook is server-side only:
76
+ // true if pageContextInit has some client data or at least one of the data() and onBeforeRender() hooks is server-side only:
68
77
  (await hasPageContextServer({ ...pageContext, ...pageContextFromHooks }))) {
69
78
  const pageContextFromServer = await fetchPageContextFromServer(pageContext);
70
- pageContextFetchedFromServer = true;
79
+ hasPageContextFromServer = true;
71
80
  if (!pageContextFromServer['_isError']) {
72
81
  objectAssign(pageContextFromHooks, pageContextFromServer);
73
82
  }
74
83
  else {
75
84
  const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
76
85
  assert(errorPageId);
77
- pageContextFromHooks = {};
78
- objectAssign(pageContextFromHooks, {
79
- _hasPageContextFromClient: false,
80
- isHydration: false,
81
- _pageId: errorPageId
82
- });
83
- objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
86
+ pageContextFromHooks = await getPageContextFromHooksInit(errorPageId);
84
87
  assert(hasProp(pageContextFromServer, 'is404', 'boolean'));
85
88
  assert(hasProp(pageContextFromServer, 'pageProps', 'object'));
86
89
  assert(hasProp(pageContextFromServer.pageProps, 'is404', 'boolean'));
@@ -89,54 +92,73 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
89
92
  objectAssign(pageContextFromHooks, pageContextFromServer);
90
93
  }
91
94
  }
92
- else {
93
- objectAssign(pageContextFromHooks, { _hasPageContextFromServer: false });
94
- // We don't need to call guard() on the client-side if we fetch pageContext from the server side. (Because the `${url}.pageContext.json` HTTP request will already trigger the routing and guard() hook on the serve-side.)
95
- // We cannot call guard() before retrieving pageContext from server, since the server-side may define pageContextInit.user which is paramount for guard() hooks
96
- if (!isErrorPage) {
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()?
98
- await executeGuardHook({
99
- ...pageContext,
100
- ...pageContextFromHooks
101
- }, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
102
- }
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).
105
- {
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);
95
+ // At this point, we need to call the client-side guard(), data() and onBeforeRender() hooks, if they exist on client
96
+ // env. However if we have fetched pageContext from the server, some of them might have run already on the
97
+ // server-side, so we run only the client-only ones in this case.
98
+ // Note: for the error page, we also execute the client-side data() and onBeforeRender() hooks, but maybe we
99
+ // shouldn't? The server-side does it as well (but maybe it shouldn't).
100
+ for (const hookName of ['guard', 'data', 'onBeforeRender']) {
101
+ const pageContextForHook = {
102
+ _hasPageContextFromServer: hasPageContextFromServer,
103
+ ...pageContext,
104
+ ...pageContextFromHooks
105
+ };
106
+ if (hookName === 'guard') {
107
+ if (!isErrorPage &&
108
+ // We don't need to call guard() on the client-side if we fetch pageContext from the server side. (Because the `${url}.pageContext.json` HTTP request will already trigger the routing and guard() hook on the server-side.)
109
+ !hasPageContextFromServer) {
110
+ // Should we really call the guard() hook on the client-side? Shouldn't we make the guard() hook a server-side
111
+ // only hook? Or maybe make its env configurable like data() and onBeforeRender()?
112
+ await executeGuardHook(pageContextForHook, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
113
+ }
111
114
  }
112
115
  else {
113
- assert(pageContextFetchedFromServer);
116
+ assert(hookName === 'data' || hookName === 'onBeforeRender');
117
+ if (hookClientOnlyExists(hookName, pageContextForHook) || !hasPageContextFromServer) {
118
+ // This won't do anything if no hook has been defined or if the hook's env.client is false.
119
+ const pageContextFromHook = await executeHookClientSide(hookName, pageContextForHook);
120
+ objectAssign(pageContextFromHooks, pageContextFromHook);
121
+ }
122
+ else {
123
+ assert(hasPageContextFromServer);
124
+ }
114
125
  }
115
126
  }
127
+ objectAssign(pageContextFromHooks, {
128
+ _hasPageContextFromServer: hasPageContextFromServer
129
+ });
116
130
  return pageContextFromHooks;
117
131
  }
118
- async function executeOnBeforeRenderHookClientSide(pageContext) {
119
- const hook = getHook(pageContext, 'onBeforeRender');
132
+ async function executeHookClientSide(hookName, pageContext) {
133
+ const hook = getHook(pageContext, hookName);
120
134
  if (!hook) {
121
135
  // No hook defined or hook's env.client is false
122
- const pageContextFromOnBeforeRender = {
123
- _hasPageContextFromClient: false
136
+ return null;
137
+ }
138
+ const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide(pageContext, true);
139
+ const hookResult = await executeHook(() => hook.hookFn(pageContextForUserConsumption), hook);
140
+ const pageContextFromHook = {};
141
+ if (hookName === 'onBeforeRender') {
142
+ assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
143
+ // Note: hookResult looks like { pageContext: { ... } }
144
+ const pageContextFromOnBeforeRender = hookResult?.pageContext;
145
+ if (pageContextFromOnBeforeRender) {
146
+ objectAssign(pageContextFromHook, { _hasPageContextFromClient: true });
147
+ objectAssign(pageContextFromHook, pageContextFromOnBeforeRender);
148
+ }
149
+ }
150
+ else {
151
+ assert(hookName === 'data');
152
+ // Note: hookResult can be anything (e.g. an object) and is to be assigned to pageContext.data
153
+ const pageContextFromData = {
154
+ data: hookResult
124
155
  };
125
- return pageContextFromOnBeforeRender;
156
+ if (hookResult) {
157
+ objectAssign(pageContextFromHook, { _hasPageContextFromClient: true });
158
+ }
159
+ objectAssign(pageContextFromHook, pageContextFromData);
126
160
  }
127
- const onBeforeRender = hook.hookFn;
128
- const pageContextFromOnBeforeRender = {
129
- _hasPageContextFromClient: true
130
- };
131
- const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide({
132
- ...pageContext,
133
- ...pageContextFromOnBeforeRender
134
- }, true);
135
- const hookResult = await executeHook(() => onBeforeRender(pageContextForUserConsumption), hook);
136
- assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
137
- const pageContextFromHook = hookResult?.pageContext;
138
- objectAssign(pageContextFromOnBeforeRender, pageContextFromHook);
139
- return pageContextFromOnBeforeRender;
161
+ return pageContextFromHook;
140
162
  }
141
163
  // Workaround for the fact that the client-side cannot known whether a pageContext JSON request is needed in order to fetch pageContextInit data passed to the client.
142
164
  // - The workaround is reliable as long as the user sets additional pageContextInit to undefined instead of not defining the property:
@@ -155,35 +177,53 @@ function setPageContextInitHasClientData(pageContext) {
155
177
  globalObject.pageContextInitHasClientData = true;
156
178
  }
157
179
  }
180
+ // TODO/v1-release: make it sync
158
181
  async function hasPageContextServer(pageContext) {
159
- return !!globalObject.pageContextInitHasClientData || (await onBeforeRenderServerOnlyExists(pageContext));
182
+ return (!!globalObject.pageContextInitHasClientData ||
183
+ (await hookServerOnlyExists('data', pageContext)) ||
184
+ (await hookServerOnlyExists('onBeforeRender', pageContext)));
160
185
  }
161
- async function onBeforeRenderServerOnlyExists(pageContext) {
186
+ // TODO/v1-release: make it sync
187
+ /**
188
+ * @param hookName
189
+ * @param pageContext
190
+ * @returns `true` if the given page has a `hookName` hook defined with a server-only env.
191
+ */
192
+ async function hookServerOnlyExists(hookName, pageContext) {
162
193
  if (pageContext._pageConfigs.length > 0) {
163
194
  // V1
164
195
  const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
165
- const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
166
- assert(isObject(onBeforeRenderEnv));
167
- return !!onBeforeRenderEnv.server && !onBeforeRenderEnv.client;
196
+ const hookEnv = getConfigValue(pageConfig, `${hookName}Env`)?.value ?? {};
197
+ assert(isObject(hookEnv));
198
+ return !!hookEnv.server && !hookEnv.client;
168
199
  }
169
200
  else {
170
201
  // TODO/v1-release: remove
171
202
  // V0.4
203
+ // data() hooks didn't exist in the V0.4 design
204
+ if (hookName === 'data')
205
+ return false;
206
+ assert(hookName === 'onBeforeRender');
172
207
  const { hasOnBeforeRenderServerSideOnlyHook } = await analyzePageServerSide(pageContext._pageFilesAll, pageContext._pageId);
173
208
  return hasOnBeforeRenderServerSideOnlyHook;
174
209
  }
175
210
  }
176
- function onBeforeRenderClientOnlyExists(pageContext) {
211
+ /**
212
+ * @param hookName
213
+ * @param pageContext
214
+ * @returns `true` if the given page has a `hookName` hook defined with a client-only env.
215
+ */
216
+ function hookClientOnlyExists(hookName, pageContext) {
177
217
  if (pageContext._pageConfigs.length > 0) {
178
218
  // V1
179
219
  const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
180
- const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
181
- assert(isObject(onBeforeRenderEnv));
182
- return !!onBeforeRenderEnv.client && !onBeforeRenderEnv.server;
220
+ const hookEnv = getConfigValue(pageConfig, `${hookName}Env`)?.value ?? {};
221
+ assert(isObject(hookEnv));
222
+ return !!hookEnv.client && !hookEnv.server;
183
223
  }
184
224
  else {
185
225
  // TODO/v1-release: remove
186
- // Client-only onBeforeRender() hooks were never supported for the V0.4 design
226
+ // Client-only onBeforeRender() or data() hooks were never supported for the V0.4 design
187
227
  return false;
188
228
  }
189
229
  }
@@ -212,7 +252,6 @@ async function fetchPageContextFromServer(pageContext) {
212
252
  }
213
253
  assert(hasProp(pageContextFromServer, '_pageId', 'string'));
214
254
  removeBuiltInOverrides(pageContextFromServer);
215
- objectAssign(pageContextFromServer, { _hasPageContextFromServer: true });
216
255
  return pageContextFromServer;
217
256
  }
218
257
  function isAlreadyServerSideRouted(err) {
@@ -133,7 +133,7 @@ async function renderPageClientSide(renderArgs) {
133
133
  console.error(err);
134
134
  }
135
135
  else {
136
- // We swallow throw redirect()/render() called by client-side hooks onBeforeRender() and guard()
136
+ // We swallow throw redirect()/render() called by client-side hooks onBeforeRender(), data() and guard()
137
137
  // We handle the abort error down below.
138
138
  }
139
139
  if (shouldSwallowAndInterrupt(err, pageContext, isFirstRender))
@@ -8,7 +8,6 @@ import { buildConfig } from './plugins/buildConfig.js';
8
8
  import { previewConfig } from './plugins/previewConfig.js';
9
9
  import { autoFullBuild } from './plugins/autoFullBuild.js';
10
10
  import { devConfig } from './plugins/devConfig/index.js';
11
- import { manifest } from './plugins/manifest.js';
12
11
  import { packageJsonFile } from './plugins/packageJsonFile.js';
13
12
  import { removeRequireHookPlugin } from './plugins/removeRequireHookPlugin.js';
14
13
  import { importUserCode } from './plugins/importUserCode/index.js';
@@ -35,7 +34,6 @@ function plugin(vikeConfig) {
35
34
  buildConfig(),
36
35
  previewConfig(),
37
36
  ...autoFullBuild(),
38
- ...manifest(),
39
37
  packageJsonFile(),
40
38
  removeRequireHookPlugin(),
41
39
  distFileNames(),
@@ -57,9 +57,10 @@ async function triggerFullBuild(config, configVike, bundle) {
57
57
  return; // already triggered
58
58
  if (isDisabled(configVike))
59
59
  return;
60
+ /* Is this @vitejs/plugin-legacy workaround still needed? Should we re-implement it?
60
61
  // vike.json missing => it isn't a `$ vite build` call (e.g. @vitejs/plugin-legacy calls Vite's build() API) => skip
61
- if (!bundle['vike.json'])
62
- return;
62
+ if (!bundle['vike.json']) return
63
+ */
63
64
  const configFromCli = !isViteCliCall() ? null : getViteConfigFromCli();
64
65
  const configInline = {
65
66
  ...configFromCli,
@@ -1,8 +1,7 @@
1
1
  export { buildConfig };
2
2
  export { assertRollupInput };
3
3
  export { analyzeClientEntries };
4
- import { assert, resolveOutDir, isObject, viteIsSSR, getFilePathAbsolute, addOnBeforeLogHook, removeFileExtention, unique, assertPosixPath, assertUsage } from '../utils.js';
5
- import { virtualFileIdImportUserCodeServer } from '../../shared/virtual-files/virtualFileImportUserCode.js';
4
+ import { assert, resolveOutDir, viteIsSSR, getFilePathAbsolute, addOnBeforeLogHook, removeFileExtention, unique, assertPosixPath, assertUsage, injectRollupInputs, normalizeRollupInput } from '../utils.js';
6
5
  import { getVikeConfig } from './importUserCode/v1-design/getVikeConfig.js';
7
6
  import { getConfigValue } from '../../../shared/page-configs/helpers.js';
8
7
  import { findPageFiles } from '../shared/findPageFiles.js';
@@ -13,7 +12,7 @@ import { createRequire } from 'module';
13
12
  import { getClientEntryFilePath } from '../../shared/getClientEntryFilePath.js';
14
13
  import fs from 'fs/promises';
15
14
  import path from 'path';
16
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
15
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
17
16
  const importMetaUrl = import.meta.url;
18
17
  const require_ = createRequire(importMetaUrl);
19
18
  const manifestTempFile = '_temp_manifest.json';
@@ -27,14 +26,9 @@ function buildConfig() {
27
26
  order: 'post',
28
27
  async handler(config) {
29
28
  assertRollupInput(config);
30
- const userInputs = normalizeRollupInput(config.build.rollupOptions.input);
31
29
  const entries = await getEntries(config);
32
30
  assert(Object.keys(entries).length > 0);
33
- const input = {
34
- ...entries,
35
- ...userInputs
36
- };
37
- config.build.rollupOptions.input = input;
31
+ config.build.rollupOptions.input = injectRollupInputs(entries, config);
38
32
  addLogHook();
39
33
  }
40
34
  },
@@ -72,12 +66,12 @@ async function getEntries(config) {
72
66
  const { pageConfigs } = await getVikeConfig(config, false);
73
67
  assertUsage(Object.keys(pageFileEntries).length !== 0 || pageConfigs.length !== 0, 'At least one page should be defined, see https://vike.dev/add');
74
68
  if (viteIsSSR(config)) {
75
- const serverEntries = analyzeServerEntries(pageConfigs);
69
+ const pageEntries = getPageEntries(pageConfigs);
76
70
  const entries = {
77
- pageFiles: virtualFileIdImportUserCodeServer,
78
- importBuild: resolve('dist/esm/node/importBuild.js'),
71
+ // importBuild: resolve('dist/esm/node/importBuild.js'), // TODO/next-major-release: remove
79
72
  ...pageFileEntries,
80
- ...serverEntries
73
+ // Ensure Rollup generates a bundle per page: https://github.com/vikejs/vike/issues/349#issuecomment-1166247275
74
+ ...pageEntries
81
75
  };
82
76
  return entries;
83
77
  }
@@ -102,6 +96,14 @@ async function getEntries(config) {
102
96
  return entries;
103
97
  }
104
98
  }
99
+ function getPageEntries(pageConfigs) {
100
+ const pageEntries = {};
101
+ pageConfigs.forEach((pageConfig) => {
102
+ const { entryName, entryTarget } = getEntryFromPageConfig(pageConfig, false);
103
+ pageEntries[entryName] = entryTarget;
104
+ });
105
+ return pageEntries;
106
+ }
105
107
  function analyzeClientEntries(pageConfigs, config) {
106
108
  let hasClientRouting = false;
107
109
  let hasServerRouting = false;
@@ -116,6 +118,7 @@ function analyzeClientEntries(pageConfigs, config) {
116
118
  hasServerRouting = true;
117
119
  }
118
120
  {
121
+ // Ensure Rollup generates a bundle per page: https://github.com/vikejs/vike/issues/349#issuecomment-1166247275
119
122
  const { entryName, entryTarget } = getEntryFromPageConfig(pageConfig, true);
120
123
  clientEntries[entryName] = entryTarget;
121
124
  }
@@ -133,14 +136,6 @@ function analyzeClientEntries(pageConfigs, config) {
133
136
  });
134
137
  return { hasClientRouting, hasServerRouting, clientEntries };
135
138
  }
136
- function analyzeServerEntries(pageConfigs) {
137
- const serverEntries = {};
138
- pageConfigs.forEach((pageConfig) => {
139
- const { entryName, entryTarget } = getEntryFromPageConfig(pageConfig, false);
140
- serverEntries[entryName] = entryTarget;
141
- });
142
- return serverEntries;
143
- }
144
139
  // Ensure Rollup creates entries for each page file, see https://github.com/vikejs/vike/issues/350
145
140
  // (Otherwise the page files may be missing in the client manifest.json)
146
141
  async function getPageFileEntries(config, includeAssetsImportedByServer) {
@@ -196,20 +191,6 @@ function resolve(filePath) {
196
191
  // [RELATIVE_PATH_FROM_DIST] Current directory: node_modules/vike/dist/esm/node/plugin/plugins/
197
192
  return require_.resolve(`../../../../../${filePath}`);
198
193
  }
199
- function normalizeRollupInput(input) {
200
- if (!input) {
201
- return {};
202
- }
203
- // Usually `input` is an oject, but the user can set it as a `string` or `string[]`
204
- if (typeof input === 'string') {
205
- input = [input];
206
- }
207
- if (Array.isArray(input)) {
208
- return Object.fromEntries(input.map((input) => [input, input]));
209
- }
210
- assert(isObject(input));
211
- return input;
212
- }
213
194
  function addLogHook() {
214
195
  const tty = process.stdout.isTTY && !process.env.CI; // Equals https://github.com/vitejs/vite/blob/193d55c7b9cbfec5b79ebfca276d4a721e7de14d/packages/vite/src/node/plugins/reporter.ts#L27
215
196
  if (!tty)
@@ -241,5 +222,5 @@ function assertRollupInput(config) {
241
222
  const userInputs = normalizeRollupInput(config.build.rollupOptions.input);
242
223
  const htmlInputs = Object.values(userInputs).filter((entry) => entry.endsWith('.html') || entry.endsWith('.htm'));
243
224
  const htmlInput = htmlInputs[0];
244
- assertUsage(htmlInput === undefined, `The entry ${htmlInput} of config build.rollupOptions.input is an HTML entry which is forbidden when using vike, instead follow https://vike.dev/add`);
225
+ assertUsage(htmlInput === undefined, `The entry ${htmlInput} of config build.rollupOptions.input is an HTML entry which is forbidden when using Vike, instead follow https://vike.dev/add`);
245
226
  }
@@ -6,7 +6,7 @@ import pc from '@brillout/picocolors';
6
6
  import path from 'path';
7
7
  import { createRequire } from 'module';
8
8
  import { assertResolveAlias } from './commonConfig/assertResolveAlias.js';
9
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
9
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
10
10
  const importMetaUrl = import.meta.url;
11
11
  const require_ = createRequire(importMetaUrl);
12
12
  function commonConfig() {
@@ -5,7 +5,7 @@ import fs from 'fs';
5
5
  import { isValidFileType } from '../../../../shared/getPageFiles/fileTypes.js';
6
6
  import { createRequire } from 'module';
7
7
  import pc from '@brillout/picocolors';
8
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
8
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
9
9
  const importMetaUrl = import.meta.url;
10
10
  const require_ = createRequire(importMetaUrl);
11
11
  function resolveExtensions(configs, config) {
@@ -4,7 +4,7 @@ import path from 'path';
4
4
  import { assert, assertUsage, assertWarning, toPosixPath, assertPosixPath, getDependencyRootDir, findUserPackageJsonPath } from '../../utils.js';
5
5
  import { import_ } from '@brillout/import';
6
6
  import { createRequire } from 'module';
7
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
7
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
8
8
  const importMetaUrl = import.meta.url;
9
9
  const require_ = createRequire(importMetaUrl);
10
10
  async function getStemPackages(userAppRootDir) {
@@ -6,7 +6,7 @@ import { assert } from '../../utils.js';
6
6
  import { createRequire } from 'module';
7
7
  import { dirname } from 'path';
8
8
  import { fileURLToPath } from 'url';
9
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
9
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
10
10
  const importMetaUrl = import.meta.url;
11
11
  const require_ = createRequire(importMetaUrl);
12
12
  const __dirname_ = dirname(fileURLToPath(importMetaUrl));
@@ -0,0 +1,5 @@
1
+ export { getVikeManifest };
2
+ import { ResolvedConfig } from 'vite';
3
+ import { type PluginManifest } from '../../../shared/assertPluginManifest.js';
4
+ import type { ConfigVikeResolved } from '../../../../shared/ConfigVike.js';
5
+ declare function getVikeManifest(config: ResolvedConfig, configVike: ConfigVikeResolved): PluginManifest;
@@ -0,0 +1,32 @@
1
+ export { getVikeManifest };
2
+ import { projectInfo, toPosixPath, assertPosixPath, isNotNullish } from '../../utils.js';
3
+ import { assertPluginManifest } from '../../../shared/assertPluginManifest.js';
4
+ import { isUsingClientRouter } from '../extractExportNamesPlugin.js';
5
+ import path from 'path';
6
+ import { getRuntimeManifest } from '../../../runtime/globalContext.js';
7
+ function getVikeManifest(config, configVike) {
8
+ const runtimeManifest = getRuntimeManifest(configVike);
9
+ const manifest = {
10
+ version: projectInfo.projectVersion,
11
+ usesClientRouter: isUsingClientRouter(),
12
+ manifestKeyMap: getManifestKeyMap(configVike, config),
13
+ ...runtimeManifest
14
+ };
15
+ assertPluginManifest(manifest);
16
+ return manifest;
17
+ }
18
+ function getManifestKeyMap(configVike, config) {
19
+ const manifestKeyMap = {};
20
+ configVike.extensions
21
+ .map(({ pageConfigsDistFiles }) => pageConfigsDistFiles)
22
+ .flat()
23
+ .filter(isNotNullish)
24
+ .forEach(({ importPath, filePath }) => {
25
+ // Recreating https://github.com/vitejs/vite/blob/8158ece72b66307e7b607b98496891610ca70ea2/packages/vite/src/node/plugins/manifest.ts#L38
26
+ const filePathRelative = path.posix.relative(config.root, toPosixPath(filePath));
27
+ assertPosixPath(filePathRelative);
28
+ assertPosixPath(importPath);
29
+ manifestKeyMap[importPath] = filePathRelative;
30
+ });
31
+ return manifestKeyMap;
32
+ }
@@ -1,54 +1,86 @@
1
1
  export { importBuild };
2
- import { importBuild as importBuild_ } from '@brillout/vite-plugin-import-build/plugin.js';
3
- import { getOutDirs, projectInfo, toPosixPath } from '../../utils.js';
2
+ import { importBuild as importBuild_, findImportBuildBundleEntry } from '@brillout/vite-plugin-import-build/plugin.js';
3
+ import { assert, getOutDirs, projectInfo, toPosixPath, viteIsSSR } from '../../utils.js';
4
4
  import path from 'path';
5
5
  import { createRequire } from 'module';
6
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
6
+ import { getConfigVike } from '../../../shared/getConfigVike.js';
7
+ import { getVikeManifest } from './getVikeManifest.js';
8
+ import fs from 'fs/promises';
9
+ import { virtualFileIdImportUserCodeServer } from '../../../shared/virtual-files/virtualFileImportUserCode.js';
10
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
7
11
  const importMetaUrl = import.meta.url;
8
12
  const require_ = createRequire(importMetaUrl);
13
+ const ASSETS_MAP = '__VITE_ASSETS_MAP__';
9
14
  function importBuild() {
10
15
  let config;
16
+ let configVike;
11
17
  return [
12
18
  {
13
19
  name: 'vike:importBuild:config',
14
20
  enforce: 'post',
15
- configResolved(config_) {
21
+ async configResolved(config_) {
16
22
  config = config_;
23
+ configVike = await getConfigVike(config);
24
+ },
25
+ async writeBundle(options, bundle) {
26
+ if (!viteIsSSR(config))
27
+ return;
28
+ await replace_ASSETS_MAP(options, bundle);
17
29
  }
18
30
  },
19
31
  importBuild_({
20
- getImporterCode: ({ findBuildEntry }) => {
21
- const pageFilesEntry = findBuildEntry('pageFiles');
22
- return getImporterCode(config, pageFilesEntry);
32
+ getImporterCode: () => {
33
+ return getEntryCode(config, configVike);
23
34
  },
24
35
  libraryName: projectInfo.projectName
25
36
  })
26
37
  ];
27
38
  }
28
- function getImporterCode(config, pageFilesEntry) {
39
+ function getEntryCode(config, configVike) {
29
40
  const importPath = getImportPath(config);
30
- // The only reason we went for using CJS require() instead of ESM import() is because import() doesn't support .json files
41
+ const vikeManifest = getVikeManifest(config, configVike);
31
42
  const importerCode = [
32
- '(async () => {',
33
- ` const { setImportBuildGetters } = await import('${importPath}');`,
43
+ ` import { setImportBuildGetters } from '${importPath}';`,
44
+ ` import * as pageFiles from '${virtualFileIdImportUserCodeServer}';`,
34
45
  ' setImportBuildGetters({',
35
- ` pageFiles: () => import('./${pageFilesEntry}'),`,
46
+ ` pageFiles: () => pageFiles,`,
36
47
  // TODO: rename clientManifest -> assetManifest
37
- // TODO: rename PluginManifest -> vikeManifest
38
- // TODO: use virtual file instead of generating vike.json
39
- " clientManifest: () => require('../assets.json'),",
40
- " pluginManifest: () => require('../client/vike.json'),",
48
+ ` clientManifest: () => { return ${ASSETS_MAP} },`,
49
+ // TODO: rename pluginManifest -> vikeManifest
50
+ ` pluginManifest: () => (${JSON.stringify(vikeManifest, null, 2)}),`,
41
51
  ' });',
42
- '})()',
43
52
  ''
44
53
  ].join('\n');
45
54
  return importerCode;
46
55
  }
56
+ async function replace_ASSETS_MAP(options, bundle) {
57
+ const { dir } = options;
58
+ assert(dir);
59
+ // I guess importBuild won't be found in the bundle when using @vitejs/plugin-legacy
60
+ const importBuildEntry = findImportBuildBundleEntry(bundle);
61
+ const importBuildFilePath = path.join(dir, importBuildEntry.fileName);
62
+ const assetsJsonFilePath = path.join(dir, '..', 'assets.json');
63
+ const [assetsJsonString, importBuildFileContent] = await Promise.all([
64
+ await fs.readFile(assetsJsonFilePath, 'utf8'),
65
+ await fs.readFile(importBuildFilePath, 'utf8')
66
+ ]);
67
+ const importBuildFileContentFixed = importBuildFileContent.replace(ASSETS_MAP, assetsJsonString);
68
+ assert(importBuildFileContentFixed !== importBuildFileContent);
69
+ await fs.writeFile(importBuildFilePath, importBuildFileContentFixed);
70
+ }
47
71
  function getImportPath(config) {
72
+ // We resolve filePathAbsolute even if we don't use it: we use require.resolve() as an assertion that the relative path is correct
48
73
  const filePathAbsolute = toPosixPath(
49
74
  // [RELATIVE_PATH_FROM_DIST] Current file: node_modules/vike/dist/esm/node/plugin/plugins/importBuild/index.js
50
75
  require_.resolve(`../../../../../../dist/esm/node/runtime/globalContext/loadImportBuild.js`));
51
- const { outDirServer } = getOutDirs(config);
52
- const filePathRelative = path.posix.relative(outDirServer, filePathAbsolute);
53
- return filePathRelative;
76
+ if (
77
+ // Let's implement a new config if a user needs the import to be a relative path instead of 'vike/__internal/loadImportBuild' (AFAIK a relative path is needed only if a framework has npm package 'vike' as direct dependency instead of a peer dependency and if the user of that framework uses pnpm)
78
+ true) {
79
+ return 'vike/__internal/loadImportBuild';
80
+ }
81
+ else {
82
+ const { outDirServer } = getOutDirs(config);
83
+ const filePathRelative = path.posix.relative(outDirServer, filePathAbsolute);
84
+ return filePathRelative;
85
+ }
54
86
  }
@@ -36,6 +36,9 @@ const configDefinitionsBuiltIn = {
36
36
  guard: {
37
37
  env: { server: true, client: 'if-client-routing' }
38
38
  },
39
+ data: {
40
+ env: { server: true }
41
+ },
39
42
  iKnowThePerformanceRisksOfAsyncRouteFunctions: {
40
43
  env: { server: true, client: 'if-client-routing', eager: true }
41
44
  },
@@ -76,6 +79,10 @@ const configDefinitionsBuiltIn = {
76
79
  env: { client: true },
77
80
  _computed: (configValueSources) => !isConfigSet(configValueSources, 'onBeforeRender') ? null : getConfigEnv(configValueSources, 'onBeforeRender')
78
81
  },
82
+ dataEnv: {
83
+ env: { client: true },
84
+ _computed: (configValueSources) => !isConfigSet(configValueSources, 'data') ? null : getConfigEnv(configValueSources, 'data')
85
+ },
79
86
  hooksTimeout: {
80
87
  env: { server: true, client: true }
81
88
  }
@@ -18,3 +18,4 @@ export * from '../../utils/getPropAccessNotation.js';
18
18
  export * from '../../utils/mergeCumulativeValues.js';
19
19
  export * from '../../utils/deepEqual.js';
20
20
  export * from '../../utils/assertKeys.js';
21
+ export * from '../../utils/injectRollupInputs.js';
@@ -24,3 +24,4 @@ export * from '../../utils/getPropAccessNotation.js';
24
24
  export * from '../../utils/mergeCumulativeValues.js';
25
25
  export * from '../../utils/deepEqual.js';
26
26
  export * from '../../utils/assertKeys.js';
27
+ export * from '../../utils/injectRollupInputs.js';
@@ -16,7 +16,8 @@ const PASS_TO_CLIENT = [
16
16
  '_abortCaller',
17
17
  */
18
18
  '_pageContextInitHasClientData',
19
- '_pageId'
19
+ '_pageId',
20
+ 'data' // for data() hook
20
21
  ];
21
22
  const PASS_TO_CLIENT_ERROR_PAGE = ['pageProps', 'is404', '_isError'];
22
23
  function serializePageContextClientSide(pageContext) {