vike 0.4.227-commit-ff6dcd9 → 0.4.227-commit-d082773

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.
@@ -5,55 +5,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.pluginModuleBanner = pluginModuleBanner;
7
7
  const magic_string_1 = __importDefault(require("magic-string"));
8
- const utils_js_1 = require("../../utils.js");
9
8
  const virtual_files_js_1 = require("../../../shared/virtual-files.js");
10
9
  const isViteServerBuild_js_1 = require("../../shared/isViteServerBuild.js");
11
10
  // Rollup's banner feature doesn't work with Vite: https://github.com/vitejs/vite/issues/8412
12
11
  // But, anyways, we want to prepend the banner at the beginning of each module, not at the beginning of each file (I believe that's what Rollup's banner feature does).
13
- const vikeModuleBannerPlaceholder = 'vikeModuleBannerPlaceholder';
14
12
  function pluginModuleBanner() {
15
13
  let config;
16
- let disabled = false;
17
14
  return {
18
15
  name: 'vike:pluginModuleBanner',
19
16
  enforce: 'post',
20
17
  apply: 'build',
21
18
  configResolved(config_) {
22
19
  config = config_;
23
- if (config.build.minify && config.build.minify !== 'esbuild') {
24
- // Doesn't work upon `config.build.minify === 'terser'`
25
- // https://github.com/vikejs/vike/issues/2315
26
- disabled = true;
27
- }
28
- },
29
- generateBundle: {
30
- order: 'post',
31
- handler(_options, bundle) {
32
- if (disabled)
33
- return;
34
- for (const module of Object.values(bundle)) {
35
- if (module.type === 'chunk') {
36
- if ((0, isViteServerBuild_js_1.isViteServerBuild)(config)) {
37
- const codeOld = module.code;
38
- const codeNew = codeOld.replace(/vikeModuleBannerPlaceholder\("([^"]*)"\);/g, '/* $1 [vike:pluginModuleBanner] */');
39
- if (codeNew.includes(vikeModuleBannerPlaceholder)) {
40
- console.log('codeNew', codeNew);
41
- (0, utils_js_1.assert)(false);
42
- }
43
- module.code = codeNew;
44
- }
45
- else {
46
- (0, utils_js_1.assert)(!module.code.includes(vikeModuleBannerPlaceholder));
47
- }
48
- }
49
- }
50
- }
51
20
  },
52
21
  transform: {
53
22
  order: 'post',
54
23
  handler(code, id, options) {
55
- if (disabled)
56
- return;
57
24
  if (!(0, isViteServerBuild_js_1.isViteServerBuild_safe)(config, options))
58
25
  return;
59
26
  if (id.startsWith('\0'))
@@ -62,8 +29,10 @@ function pluginModuleBanner() {
62
29
  if (id.startsWith(config.root))
63
30
  id = id.slice(config.root.length + 1);
64
31
  const s = new magic_string_1.default(code);
65
- // No need to insert a new line; Rollup formats the code and will insert a new line.
66
- s.prepend(`${vikeModuleBannerPlaceholder}(${JSON.stringify(id)}); `);
32
+ // Use legal comment so that esbuild doesn't remove it.
33
+ // - Terser still removes the comment, but I guess users use terser to minify JavaScript so I guess it's a good thing that comment is removed.
34
+ // - https://esbuild.github.io/api/#legal-comments
35
+ s.prepend(`/*! ${id} [vike:pluginModuleBanner] */\n`);
67
36
  return {
68
37
  code: s.toString(),
69
38
  map: s.generateMap({ hires: true, source: id })
@@ -38,8 +38,7 @@ function commonConfig(vikeVitePluginOptions) {
38
38
  isPrerenderingEnabled,
39
39
  isPrerenderingEnabledForAllPages,
40
40
  output: null,
41
- pageContexts: null,
42
- pageContexts404: null
41
+ pageContexts: null
43
42
  });
44
43
  (0, utils_js_1.assert)(prerenderContext.isPrerenderingEnabled === isPrerenderingEnabled);
45
44
  (0, utils_js_1.assert)(prerenderContext.isPrerenderingEnabledForAllPages === isPrerenderingEnabledForAllPages);
@@ -111,8 +111,6 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
111
111
  build.onResolve({ filter: /.*/ }, async (args) => {
112
112
  if (args.kind !== 'import-statement')
113
113
  return;
114
- if (debugEsbuildResolve.isActivated)
115
- debugEsbuildResolve('args', args);
116
114
  // Avoid infinite loop: https://github.com/evanw/esbuild/issues/3095#issuecomment-1546916366
117
115
  const useEsbuildResolver = 'useEsbuildResolver';
118
116
  if (args.pluginData?.[useEsbuildResolver])
@@ -120,6 +118,8 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
120
118
  const { path, ...opts } = args;
121
119
  opts.pluginData = { [useEsbuildResolver]: true };
122
120
  let resolved = await build.resolve(path, opts);
121
+ if (debugEsbuildResolve.isActivated)
122
+ debugEsbuildResolve('args', args);
123
123
  if (debugEsbuildResolve.isActivated)
124
124
  debugEsbuildResolve('resolved', resolved);
125
125
  // Temporary workaround for https://github.com/evanw/esbuild/issues/3973
@@ -160,11 +160,25 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
160
160
  // - vike@0.4.162 started soft-requiring Vike extensions to set the name config.
161
161
  // - In practice, it seems like it requires some (non-trivial?) refactoring.
162
162
  isVikeExtensionImport;
163
- // Externalize npm package imports
164
163
  (0, utils_js_1.assertPosixPath)(importPathResolved);
165
- const isNpmPkgImport = importPathResolved.includes('/node_modules/') ||
164
+ // `isNpmPkgImport` => `importPathOriginal` is most likely an npm package import, but it can also be a path alias that a) looks like an npm package import and b) resolves outside of `userRootDir`.
165
+ const isNpmPkgImport = (() => {
166
+ if (importPathResolved.includes('/node_modules/')) {
167
+ // So far I can't think of a use case where this assertion would fail, but let's eventually remove it to avoid artificially restricting the user.
168
+ (0, utils_js_1.assert)((0, utils_js_1.isNpmPackageImport_unreliable)(importPathOriginal));
169
+ return true;
170
+ }
166
171
  // Linked npm packages
167
- !importPathResolved.startsWith(userRootDir);
172
+ if (
173
+ // Assuming path aliases usually resolve inside `userRootDir`.
174
+ // - This isn't always the case: https://github.com/vikejs/vike/issues/2326
175
+ !importPathResolved.startsWith(userRootDir) &&
176
+ // False positive if `importPathOriginal` is a path alias that a) looks like an npm package import and b) resolves outside of `userRootDir` => we then we wrongfully assume that `importPathOriginal` is an npm package import.
177
+ (0, utils_js_1.isNpmPackageImport_unreliable)(importPathOriginal)) {
178
+ return true;
179
+ }
180
+ return false;
181
+ })();
168
182
  const isExternal = isPointerImport ||
169
183
  // Performance: npm package imports can be externalized. (We could as well let esbuild transpile /node_modules/ code but it's useless as /node_modules/ code is already built. It would unnecessarily slow down transpilation.)
170
184
  isNpmPkgImport;
@@ -188,19 +202,19 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
188
202
  filePathAbsoluteFilesystem: importPathResolved,
189
203
  userRootDir
190
204
  });
191
- // We assuming that path aliases always resolve inside `userRootDir`.
192
205
  if (filePathAbsoluteUserRootDir && !isNpmPkgImport) {
193
- // `importPathOriginal` is a path alias.
206
+ // `importPathOriginal` is most likely a path alias.
194
207
  // - We have to use esbuild's path alias resolution, because:
195
208
  // - Vike doesn't resolve path aliases at all.
196
209
  // - Node.js doesn't support `tsconfig.js#compilerOptions.paths`.
197
- // - Esbuild path alias resolution seems to be reliable, e.g. it supports `tsconfig.js#compilerOptions.paths`.
210
+ // - Esbuild path alias resolution seems reliable, e.g. it supports `tsconfig.js#compilerOptions.paths`.
211
+ (0, utils_js_1.assert)(!(0, utils_js_1.isNpmPackageImport_unreliable)(importPathOriginal));
198
212
  importPathTranspiled = importPathResolved;
199
213
  }
200
214
  else {
201
- // `importPathOriginal` is an npm package import.
215
+ // `importPathOriginal` is most likely an npm package import.
202
216
  (0, utils_js_1.assertIsNpmPackageImport)(importPathOriginal);
203
- // For less confusing error messages, let the resolution be handled by Vike or Node.js.
217
+ // For improved error messages, let the resolution be handled by Vike or Node.js.
204
218
  importPathTranspiled = importPathOriginal;
205
219
  }
206
220
  }
@@ -11,7 +11,7 @@ function resolvePrerenderConfigGlobal(vikeConfig) {
11
11
  const prerenderSettings = prerenderConfigs.filter(isObject2);
12
12
  const prerenderConfigGlobal = {
13
13
  partial: pickFirst(prerenderSettings.map((c) => c.partial)) ?? false,
14
- noExtraDir: pickFirst(prerenderSettings.map((c) => c.noExtraDir)) ?? false,
14
+ noExtraDir: pickFirst(prerenderSettings.map((c) => c.noExtraDir)) ?? null,
15
15
  keepDistServer: pickFirst(prerenderSettings.map((c) => c.keepDistServer)) ?? false,
16
16
  parallel: pickFirst(prerenderSettings.map((c) => c.parallel)) ?? true,
17
17
  disableAutoRun: pickFirst(prerenderSettings.map((c) => c.disableAutoRun)) ?? false
@@ -119,7 +119,6 @@ async function runPrerender(options = {}, standaloneTrigger) {
119
119
  const { outDirClient, outDirServer } = (0, getOutDirs_js_1.getOutDirs)(viteConfig);
120
120
  const { root } = viteConfig;
121
121
  const prerenderConfigGlobal = (0, resolvePrerenderConfig_js_1.resolvePrerenderConfigGlobal)(vikeConfig);
122
- validatePrerenderConfig(prerenderConfigGlobal);
123
122
  const { partial, noExtraDir, parallel, defaultLocalValue, isPrerenderingEnabled } = prerenderConfigGlobal;
124
123
  if (!isPrerenderingEnabled) {
125
124
  (0, utils_js_1.assert)(standaloneTrigger);
@@ -130,9 +129,8 @@ async function runPrerender(options = {}, standaloneTrigger) {
130
129
  const globalContext = await (0, globalContext_js_1.getGlobalContextInternal)();
131
130
  globalContext.pageFilesAll.forEach(assertExportNames);
132
131
  const prerenderContext = {
133
- noExtraDir: noExtraDir ?? false,
132
+ noExtraDir,
134
133
  pageContexts: [],
135
- pageContexts404: [],
136
134
  pageContextInit: options.pageContextInit ?? null,
137
135
  prerenderedPageContexts: {},
138
136
  output: []
@@ -162,7 +160,6 @@ async function runPrerender(options = {}, standaloneTrigger) {
162
160
  };
163
161
  await prerenderPages(prerenderContext, concurrencyLimit, onComplete);
164
162
  warnContradictoryNoPrerenderList(prerenderContext.prerenderedPageContexts, doNotPrerenderList);
165
- await prerenderPages404(prerenderContext, onComplete, concurrencyLimit);
166
163
  if (logLevel === 'info') {
167
164
  console.log(`${picocolors_1.default.green(`✓`)} ${prerenderedCount} HTML documents pre-rendered.`);
168
165
  }
@@ -342,16 +339,11 @@ function getUrlList404(globalContext) {
342
339
  async function createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, is404) {
343
340
  await Promise.all(urlList.map(({ urlOriginal, pageId }) => concurrencyLimit(async () => {
344
341
  // Already included in a onBeforePrerenderStart() hook
345
- if ([...prerenderContext.pageContexts, ...prerenderContext.pageContexts404].find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
342
+ if (prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
346
343
  return;
347
344
  }
348
345
  const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, null);
349
- if (is404) {
350
- prerenderContext.pageContexts404.push(pageContext);
351
- }
352
- else {
353
- prerenderContext.pageContexts.push(pageContext);
354
- }
346
+ prerenderContext.pageContexts.push(pageContext);
355
347
  })));
356
348
  }
357
349
  async function createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, providedByHook) {
@@ -563,13 +555,13 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext, concurr
563
555
  });
564
556
  // Assert URL modified by user
565
557
  await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
566
- if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook) {
558
+ if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook && !pageContext.is404) {
567
559
  pageContext._urlOriginalModifiedByHook = {
568
560
  hookFilePath,
569
561
  hookName
570
562
  };
571
563
  const pageContextFromRoute = await (0, index_js_1.route)(pageContext,
572
- // Avoid calling onBeforeRoute() twice, otherwise user's onBeforeRoute() will wrongfully believe URL doesn't have locale when onBeforeRoute() removes the local from the URL
564
+ // Avoid calling onBeforeRoute() twice, otherwise onBeforeRoute() will wrongfully believe URL doesn't have locale after onBeforeRoute() already removed the local from the URL when called the first time.
573
565
  true);
574
566
  assertRouteMatch(pageContextFromRoute, pageContext);
575
567
  }
@@ -585,12 +577,13 @@ async function prerenderPages(prerenderContext, concurrencyLimit, onComplete) {
585
577
  assertIsNotAbort(err, picocolors_1.default.cyan(pageContextBeforeRender.urlOriginal));
586
578
  throw err;
587
579
  }
588
- const { documentHtml, pageContextSerialized, pageContext } = res;
580
+ const { documentHtml, pageContext } = res;
581
+ const pageContextSerialized = pageContext.is404 ? null : res.pageContextSerialized;
589
582
  await onComplete({
590
583
  pageContext,
591
584
  htmlString: documentHtml,
592
585
  pageContextSerialized,
593
- doNotCreateExtraDirectory: prerenderContext.noExtraDir
586
+ doNotCreateExtraDirectory: prerenderContext.noExtraDir ?? pageContext.is404
594
587
  });
595
588
  })));
596
589
  }
@@ -622,25 +615,6 @@ async function warnMissingPages(prerenderedPageContexts, globalContext, doNotPre
622
615
  (0, utils_js_1.assertWarning)(partial, `Cannot pre-render page ${pageAt} because it has a non-static route, while no ${hookName}() hook returned any URL matching the page's route. You need to use a ${hookName}() hook (https://vike.dev/${hookName}) providing a list of URLs for ${pageAt} that should be pre-rendered. If you don't want to pre-render ${pageAt} then use the option prerender.partial (https://vike.dev/prerender#partial) to suppress this warning.`, { onlyOnce: true });
623
616
  });
624
617
  }
625
- async function prerenderPages404(prerenderContext, onComplete, concurrencyLimit) {
626
- await Promise.all(prerenderContext.pageContexts404.map((pageContextBeforeRender) => concurrencyLimit(async () => {
627
- let result;
628
- try {
629
- result = await (0, renderPageAlreadyRouted_js_1.prerenderPage)(pageContextBeforeRender);
630
- }
631
- catch (err) {
632
- assertIsNotAbort(err, 'the 404 page');
633
- throw err;
634
- }
635
- const { documentHtml, pageContext } = result;
636
- await onComplete({
637
- pageContext,
638
- htmlString: documentHtml,
639
- pageContextSerialized: null,
640
- doNotCreateExtraDirectory: true
641
- });
642
- })));
643
- }
644
618
  async function writeFiles({ pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
645
619
  const { urlOriginal } = pageContext;
646
620
  (0, utils_js_1.assert)(urlOriginal.startsWith('/'));
@@ -774,7 +748,7 @@ function runPrerender_forceExit() {
774
748
  assertInfo(false, "Pre-rendering was forced exit. (Didn't gracefully exit because the event queue isn't empty. This is usally fine, see ...", { onlyOnce: false })
775
749
  */
776
750
  }
777
- function assertIsNotAbort(err, urlOr404) {
751
+ function assertIsNotAbort(err, urlOriginal) {
778
752
  if (!(0, abort_js_1.isAbortError)(err))
779
753
  return;
780
754
  const pageContextAbort = err._pageContextAbort;
@@ -785,48 +759,12 @@ function assertIsNotAbort(err, urlOr404) {
785
759
  (0, utils_js_1.assert)(abortCaller);
786
760
  const abortCall = pageContextAbort._abortCall;
787
761
  (0, utils_js_1.assert)(abortCall);
788
- (0, utils_js_1.assertUsage)(false, `${picocolors_1.default.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOr404} but ${picocolors_1.default.cyan(abortCaller)} isn't supported for pre-rendered pages`);
789
- }
790
- function validatePrerenderConfig(
791
- // Guaranteed by configDef.type to be either an object or boolean
792
- prerenderConfig) {
793
- if (!prerenderConfig || typeof prerenderConfig === 'boolean')
794
- return;
795
- (0, utils_js_1.assert)((0, utils_js_1.isObject)(prerenderConfig));
796
- const wrongValue = (() => {
797
- {
798
- const p = 'partial';
799
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') && !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
800
- return { prop: p, errMsg: 'should be a boolean' };
801
- }
802
- {
803
- const p = 'noExtraDir';
804
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') && !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
805
- return { prop: p, errMsg: 'should be a boolean' };
806
- }
807
- {
808
- const p = 'disableAutoRun';
809
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') && !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
810
- return { prop: p, errMsg: 'should be a boolean' };
811
- }
812
- {
813
- const p = 'parallel';
814
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') &&
815
- !(0, utils_js_1.hasProp)(prerenderConfig, p, 'number') &&
816
- !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
817
- return { prop: p, errMsg: 'should be a boolean or a number' };
818
- }
819
- })();
820
- if (wrongValue) {
821
- const { prop, errMsg } = wrongValue;
822
- (0, utils_js_1.assertUsage)(false, `Setting ${picocolors_1.default.cyan(`prerender.${prop}`)} ${errMsg}`);
823
- }
762
+ (0, utils_js_1.assertUsage)(false, `${picocolors_1.default.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOriginal} but ${picocolors_1.default.cyan(abortCaller)} isn't supported for pre-rendered pages`);
824
763
  }
825
764
  function makePublic(prerenderContext) {
826
765
  const prerenderContextPublic = (0, utils_js_1.makePublicCopy)(prerenderContext, 'prerenderContext', [
827
766
  'output', // vite-plugin-vercel
828
- 'pageContexts', // https://vike.dev/i18n#pre-rendering
829
- 'pageContexts404' // https://vike.dev/i18n#pre-rendering
767
+ 'pageContexts' // https://vike.dev/i18n#pre-rendering
830
768
  ]);
831
769
  return prerenderContextPublic;
832
770
  }
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = void 0;
4
4
  // Automatically updated by @brillout/release-me
5
- exports.PROJECT_VERSION = '0.4.227-commit-ff6dcd9';
5
+ exports.PROJECT_VERSION = '0.4.227-commit-d082773';
@@ -24,8 +24,8 @@ function assertFilePathAbsoluteFilesystem(filePath) {
24
24
  // - For Linux users assertFilePathAbsoluteFilesystem() will erroneously succeed if `p` is a path absolute from the user root dir.
25
25
  // - But that's okay because the assertion will eventually fail for Windows users.
26
26
  // - On Linux there doesn't seem to be a way to distinguish between an absolute path starting from the filesystem root or starting from the user root directory, see comment at isFilePathAbsoluteFilesystem()
27
- (0, assert_js_1.assert)(isFilePathAbsoluteFilesystem(filePath));
28
27
  (0, path_js_1.assertPosixPath)(filePath);
28
+ (0, assert_js_1.assert)(isFilePathAbsoluteFilesystem(filePath));
29
29
  }
30
30
  /**
31
31
  * Whether `filePath` is an absolute file path starting from the filesystem root.
@@ -10,10 +10,10 @@ const assert_js_1 = require("./assert.js");
10
10
  const assertIsNotBrowser_js_1 = require("./assertIsNotBrowser.js");
11
11
  (0, assertIsNotBrowser_js_1.assertIsNotBrowser)();
12
12
  function isNpmPackageImport(str, { cannotBePathAlias }) {
13
- // We cannot distinguish path alises that look like npm package imports
14
13
  (0, assert_js_1.assert)(cannotBePathAlias);
15
14
  return isNpmPackageImport_unreliable(str);
16
15
  }
16
+ // We cannot distinguish path aliases that look like npm package imports
17
17
  function isNpmPackageImport_unreliable(str) {
18
18
  const res = parse(str);
19
19
  return res !== null;
@@ -1,54 +1,21 @@
1
1
  export { pluginModuleBanner };
2
2
  import MagicString from 'magic-string';
3
- import { assert } from '../../utils.js';
4
3
  import { removeVirtualIdTag } from '../../../shared/virtual-files.js';
5
- import { isViteServerBuild, isViteServerBuild_safe } from '../../shared/isViteServerBuild.js';
4
+ import { isViteServerBuild_safe } from '../../shared/isViteServerBuild.js';
6
5
  // Rollup's banner feature doesn't work with Vite: https://github.com/vitejs/vite/issues/8412
7
6
  // But, anyways, we want to prepend the banner at the beginning of each module, not at the beginning of each file (I believe that's what Rollup's banner feature does).
8
- const vikeModuleBannerPlaceholder = 'vikeModuleBannerPlaceholder';
9
7
  function pluginModuleBanner() {
10
8
  let config;
11
- let disabled = false;
12
9
  return {
13
10
  name: 'vike:pluginModuleBanner',
14
11
  enforce: 'post',
15
12
  apply: 'build',
16
13
  configResolved(config_) {
17
14
  config = config_;
18
- if (config.build.minify && config.build.minify !== 'esbuild') {
19
- // Doesn't work upon `config.build.minify === 'terser'`
20
- // https://github.com/vikejs/vike/issues/2315
21
- disabled = true;
22
- }
23
- },
24
- generateBundle: {
25
- order: 'post',
26
- handler(_options, bundle) {
27
- if (disabled)
28
- return;
29
- for (const module of Object.values(bundle)) {
30
- if (module.type === 'chunk') {
31
- if (isViteServerBuild(config)) {
32
- const codeOld = module.code;
33
- const codeNew = codeOld.replace(/vikeModuleBannerPlaceholder\("([^"]*)"\);/g, '/* $1 [vike:pluginModuleBanner] */');
34
- if (codeNew.includes(vikeModuleBannerPlaceholder)) {
35
- console.log('codeNew', codeNew);
36
- assert(false);
37
- }
38
- module.code = codeNew;
39
- }
40
- else {
41
- assert(!module.code.includes(vikeModuleBannerPlaceholder));
42
- }
43
- }
44
- }
45
- }
46
15
  },
47
16
  transform: {
48
17
  order: 'post',
49
18
  handler(code, id, options) {
50
- if (disabled)
51
- return;
52
19
  if (!isViteServerBuild_safe(config, options))
53
20
  return;
54
21
  if (id.startsWith('\0'))
@@ -57,8 +24,10 @@ function pluginModuleBanner() {
57
24
  if (id.startsWith(config.root))
58
25
  id = id.slice(config.root.length + 1);
59
26
  const s = new MagicString(code);
60
- // No need to insert a new line; Rollup formats the code and will insert a new line.
61
- s.prepend(`${vikeModuleBannerPlaceholder}(${JSON.stringify(id)}); `);
27
+ // Use legal comment so that esbuild doesn't remove it.
28
+ // - Terser still removes the comment, but I guess users use terser to minify JavaScript so I guess it's a good thing that comment is removed.
29
+ // - https://esbuild.github.io/api/#legal-comments
30
+ s.prepend(`/*! ${id} [vike:pluginModuleBanner] */\n`);
62
31
  return {
63
32
  code: s.toString(),
64
33
  map: s.generateMap({ hires: true, source: id })
@@ -33,8 +33,7 @@ function commonConfig(vikeVitePluginOptions) {
33
33
  isPrerenderingEnabled,
34
34
  isPrerenderingEnabledForAllPages,
35
35
  output: null,
36
- pageContexts: null,
37
- pageContexts404: null
36
+ pageContexts: null
38
37
  });
39
38
  assert(prerenderContext.isPrerenderingEnabled === isPrerenderingEnabled);
40
39
  assert(prerenderContext.isPrerenderingEnabledForAllPages === isPrerenderingEnabledForAllPages);
@@ -7,7 +7,7 @@ import fs from 'fs';
7
7
  import path from 'path';
8
8
  import pc from '@brillout/picocolors';
9
9
  import { import_ } from '@brillout/import';
10
- import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, assertWarning, isObject, toPosixPath, assertUsage, isPlainJavaScriptFile, createDebugger, assertFilePathAbsoluteFilesystem, assertIsNpmPackageImport, genPromise, isVitest, requireResolveOptional } from '../../../../utils.js';
10
+ import { assertPosixPath, getRandomId, assertIsNotProductionRuntime, assert, assertWarning, isObject, toPosixPath, assertUsage, isPlainJavaScriptFile, createDebugger, assertFilePathAbsoluteFilesystem, assertIsNpmPackageImport, genPromise, isVitest, requireResolveOptional, isNpmPackageImport_unreliable } from '../../../../utils.js';
11
11
  import { transformPointerImports } from './transformPointerImports.js';
12
12
  import sourceMapSupport from 'source-map-support';
13
13
  import { getFilePathAbsoluteUserRootDir } from '../../../../shared/getFilePath.js';
@@ -106,8 +106,6 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
106
106
  build.onResolve({ filter: /.*/ }, async (args) => {
107
107
  if (args.kind !== 'import-statement')
108
108
  return;
109
- if (debugEsbuildResolve.isActivated)
110
- debugEsbuildResolve('args', args);
111
109
  // Avoid infinite loop: https://github.com/evanw/esbuild/issues/3095#issuecomment-1546916366
112
110
  const useEsbuildResolver = 'useEsbuildResolver';
113
111
  if (args.pluginData?.[useEsbuildResolver])
@@ -115,6 +113,8 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
115
113
  const { path, ...opts } = args;
116
114
  opts.pluginData = { [useEsbuildResolver]: true };
117
115
  let resolved = await build.resolve(path, opts);
116
+ if (debugEsbuildResolve.isActivated)
117
+ debugEsbuildResolve('args', args);
118
118
  if (debugEsbuildResolve.isActivated)
119
119
  debugEsbuildResolve('resolved', resolved);
120
120
  // Temporary workaround for https://github.com/evanw/esbuild/issues/3973
@@ -155,11 +155,25 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
155
155
  // - vike@0.4.162 started soft-requiring Vike extensions to set the name config.
156
156
  // - In practice, it seems like it requires some (non-trivial?) refactoring.
157
157
  isVikeExtensionImport;
158
- // Externalize npm package imports
159
158
  assertPosixPath(importPathResolved);
160
- const isNpmPkgImport = importPathResolved.includes('/node_modules/') ||
159
+ // `isNpmPkgImport` => `importPathOriginal` is most likely an npm package import, but it can also be a path alias that a) looks like an npm package import and b) resolves outside of `userRootDir`.
160
+ const isNpmPkgImport = (() => {
161
+ if (importPathResolved.includes('/node_modules/')) {
162
+ // So far I can't think of a use case where this assertion would fail, but let's eventually remove it to avoid artificially restricting the user.
163
+ assert(isNpmPackageImport_unreliable(importPathOriginal));
164
+ return true;
165
+ }
161
166
  // Linked npm packages
162
- !importPathResolved.startsWith(userRootDir);
167
+ if (
168
+ // Assuming path aliases usually resolve inside `userRootDir`.
169
+ // - This isn't always the case: https://github.com/vikejs/vike/issues/2326
170
+ !importPathResolved.startsWith(userRootDir) &&
171
+ // False positive if `importPathOriginal` is a path alias that a) looks like an npm package import and b) resolves outside of `userRootDir` => we then we wrongfully assume that `importPathOriginal` is an npm package import.
172
+ isNpmPackageImport_unreliable(importPathOriginal)) {
173
+ return true;
174
+ }
175
+ return false;
176
+ })();
163
177
  const isExternal = isPointerImport ||
164
178
  // Performance: npm package imports can be externalized. (We could as well let esbuild transpile /node_modules/ code but it's useless as /node_modules/ code is already built. It would unnecessarily slow down transpilation.)
165
179
  isNpmPkgImport;
@@ -183,19 +197,19 @@ async function transpileWithEsbuild(filePath, userRootDir, transformImports, esb
183
197
  filePathAbsoluteFilesystem: importPathResolved,
184
198
  userRootDir
185
199
  });
186
- // We assuming that path aliases always resolve inside `userRootDir`.
187
200
  if (filePathAbsoluteUserRootDir && !isNpmPkgImport) {
188
- // `importPathOriginal` is a path alias.
201
+ // `importPathOriginal` is most likely a path alias.
189
202
  // - We have to use esbuild's path alias resolution, because:
190
203
  // - Vike doesn't resolve path aliases at all.
191
204
  // - Node.js doesn't support `tsconfig.js#compilerOptions.paths`.
192
- // - Esbuild path alias resolution seems to be reliable, e.g. it supports `tsconfig.js#compilerOptions.paths`.
205
+ // - Esbuild path alias resolution seems reliable, e.g. it supports `tsconfig.js#compilerOptions.paths`.
206
+ assert(!isNpmPackageImport_unreliable(importPathOriginal));
193
207
  importPathTranspiled = importPathResolved;
194
208
  }
195
209
  else {
196
- // `importPathOriginal` is an npm package import.
210
+ // `importPathOriginal` is most likely an npm package import.
197
211
  assertIsNpmPackageImport(importPathOriginal);
198
- // For less confusing error messages, let the resolution be handled by Vike or Node.js.
212
+ // For improved error messages, let the resolution be handled by Vike or Node.js.
199
213
  importPathTranspiled = importPathOriginal;
200
214
  }
201
215
  }
@@ -4,7 +4,7 @@ import { VikeConfigObject } from '../plugin/plugins/importUserCode/v1-design/get
4
4
  import type { PageConfigBuildTime } from '../../shared/page-configs/PageConfig.js';
5
5
  declare function resolvePrerenderConfigGlobal(vikeConfig: VikeConfigObject): {
6
6
  partial: boolean;
7
- noExtraDir: boolean;
7
+ noExtraDir: boolean | null;
8
8
  keepDistServer: boolean;
9
9
  parallel: number | boolean;
10
10
  disableAutoRun: boolean;
@@ -9,7 +9,7 @@ function resolvePrerenderConfigGlobal(vikeConfig) {
9
9
  const prerenderSettings = prerenderConfigs.filter(isObject2);
10
10
  const prerenderConfigGlobal = {
11
11
  partial: pickFirst(prerenderSettings.map((c) => c.partial)) ?? false,
12
- noExtraDir: pickFirst(prerenderSettings.map((c) => c.noExtraDir)) ?? false,
12
+ noExtraDir: pickFirst(prerenderSettings.map((c) => c.noExtraDir)) ?? null,
13
13
  keepDistServer: pickFirst(prerenderSettings.map((c) => c.keepDistServer)) ?? false,
14
14
  parallel: pickFirst(prerenderSettings.map((c) => c.parallel)) ?? true,
15
15
  disableAutoRun: pickFirst(prerenderSettings.map((c) => c.disableAutoRun)) ?? false
@@ -54,5 +54,4 @@ declare function runPrerender_forceExit(): void;
54
54
  type PrerenderContextPublic = {
55
55
  output: Output<PageContextServer>;
56
56
  pageContexts: PageContextServer[];
57
- pageContexts404: PageContextServer;
58
57
  };
@@ -4,7 +4,7 @@ export { runPrerenderFromAutoRun };
4
4
  export { runPrerender_forceExit };
5
5
  import path from 'path';
6
6
  import { route } from '../../shared/route/index.js';
7
- import { assert, assertUsage, assertWarning, hasProp, objectAssign, isObjectWithKeys, isCallable, isPropertyGetter, assertPosixPath, urlToFile, isPlainObject, pLimit, isArray, onSetupPrerender, isObject, makePublicCopy, PROJECT_VERSION, preservePropertyGetters } from './utils.js';
7
+ import { assert, assertUsage, assertWarning, hasProp, objectAssign, isObjectWithKeys, isCallable, isPropertyGetter, assertPosixPath, urlToFile, isPlainObject, pLimit, isArray, onSetupPrerender, makePublicCopy, PROJECT_VERSION, preservePropertyGetters } from './utils.js';
8
8
  import { prerenderPage, getPageContextInitEnhanced } from '../runtime/renderPage/renderPageAlreadyRouted.js';
9
9
  import pc from '@brillout/picocolors';
10
10
  import { cpus } from 'os';
@@ -81,7 +81,6 @@ async function runPrerender(options = {}, standaloneTrigger) {
81
81
  const { outDirClient, outDirServer } = getOutDirs(viteConfig);
82
82
  const { root } = viteConfig;
83
83
  const prerenderConfigGlobal = resolvePrerenderConfigGlobal(vikeConfig);
84
- validatePrerenderConfig(prerenderConfigGlobal);
85
84
  const { partial, noExtraDir, parallel, defaultLocalValue, isPrerenderingEnabled } = prerenderConfigGlobal;
86
85
  if (!isPrerenderingEnabled) {
87
86
  assert(standaloneTrigger);
@@ -92,9 +91,8 @@ async function runPrerender(options = {}, standaloneTrigger) {
92
91
  const globalContext = await getGlobalContextInternal();
93
92
  globalContext.pageFilesAll.forEach(assertExportNames);
94
93
  const prerenderContext = {
95
- noExtraDir: noExtraDir ?? false,
94
+ noExtraDir,
96
95
  pageContexts: [],
97
- pageContexts404: [],
98
96
  pageContextInit: options.pageContextInit ?? null,
99
97
  prerenderedPageContexts: {},
100
98
  output: []
@@ -124,7 +122,6 @@ async function runPrerender(options = {}, standaloneTrigger) {
124
122
  };
125
123
  await prerenderPages(prerenderContext, concurrencyLimit, onComplete);
126
124
  warnContradictoryNoPrerenderList(prerenderContext.prerenderedPageContexts, doNotPrerenderList);
127
- await prerenderPages404(prerenderContext, onComplete, concurrencyLimit);
128
125
  if (logLevel === 'info') {
129
126
  console.log(`${pc.green(`✓`)} ${prerenderedCount} HTML documents pre-rendered.`);
130
127
  }
@@ -304,16 +301,11 @@ function getUrlList404(globalContext) {
304
301
  async function createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, is404) {
305
302
  await Promise.all(urlList.map(({ urlOriginal, pageId }) => concurrencyLimit(async () => {
306
303
  // Already included in a onBeforePrerenderStart() hook
307
- if ([...prerenderContext.pageContexts, ...prerenderContext.pageContexts404].find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
304
+ if (prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
308
305
  return;
309
306
  }
310
307
  const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, null);
311
- if (is404) {
312
- prerenderContext.pageContexts404.push(pageContext);
313
- }
314
- else {
315
- prerenderContext.pageContexts.push(pageContext);
316
- }
308
+ prerenderContext.pageContexts.push(pageContext);
317
309
  })));
318
310
  }
319
311
  async function createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, providedByHook) {
@@ -525,13 +517,13 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext, concurr
525
517
  });
526
518
  // Assert URL modified by user
527
519
  await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
528
- if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook) {
520
+ if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook && !pageContext.is404) {
529
521
  pageContext._urlOriginalModifiedByHook = {
530
522
  hookFilePath,
531
523
  hookName
532
524
  };
533
525
  const pageContextFromRoute = await route(pageContext,
534
- // Avoid calling onBeforeRoute() twice, otherwise user's onBeforeRoute() will wrongfully believe URL doesn't have locale when onBeforeRoute() removes the local from the URL
526
+ // Avoid calling onBeforeRoute() twice, otherwise onBeforeRoute() will wrongfully believe URL doesn't have locale after onBeforeRoute() already removed the local from the URL when called the first time.
535
527
  true);
536
528
  assertRouteMatch(pageContextFromRoute, pageContext);
537
529
  }
@@ -547,12 +539,13 @@ async function prerenderPages(prerenderContext, concurrencyLimit, onComplete) {
547
539
  assertIsNotAbort(err, pc.cyan(pageContextBeforeRender.urlOriginal));
548
540
  throw err;
549
541
  }
550
- const { documentHtml, pageContextSerialized, pageContext } = res;
542
+ const { documentHtml, pageContext } = res;
543
+ const pageContextSerialized = pageContext.is404 ? null : res.pageContextSerialized;
551
544
  await onComplete({
552
545
  pageContext,
553
546
  htmlString: documentHtml,
554
547
  pageContextSerialized,
555
- doNotCreateExtraDirectory: prerenderContext.noExtraDir
548
+ doNotCreateExtraDirectory: prerenderContext.noExtraDir ?? pageContext.is404
556
549
  });
557
550
  })));
558
551
  }
@@ -584,25 +577,6 @@ async function warnMissingPages(prerenderedPageContexts, globalContext, doNotPre
584
577
  assertWarning(partial, `Cannot pre-render page ${pageAt} because it has a non-static route, while no ${hookName}() hook returned any URL matching the page's route. You need to use a ${hookName}() hook (https://vike.dev/${hookName}) providing a list of URLs for ${pageAt} that should be pre-rendered. If you don't want to pre-render ${pageAt} then use the option prerender.partial (https://vike.dev/prerender#partial) to suppress this warning.`, { onlyOnce: true });
585
578
  });
586
579
  }
587
- async function prerenderPages404(prerenderContext, onComplete, concurrencyLimit) {
588
- await Promise.all(prerenderContext.pageContexts404.map((pageContextBeforeRender) => concurrencyLimit(async () => {
589
- let result;
590
- try {
591
- result = await prerenderPage(pageContextBeforeRender);
592
- }
593
- catch (err) {
594
- assertIsNotAbort(err, 'the 404 page');
595
- throw err;
596
- }
597
- const { documentHtml, pageContext } = result;
598
- await onComplete({
599
- pageContext,
600
- htmlString: documentHtml,
601
- pageContextSerialized: null,
602
- doNotCreateExtraDirectory: true
603
- });
604
- })));
605
- }
606
580
  async function writeFiles({ pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
607
581
  const { urlOriginal } = pageContext;
608
582
  assert(urlOriginal.startsWith('/'));
@@ -736,7 +710,7 @@ function runPrerender_forceExit() {
736
710
  assertInfo(false, "Pre-rendering was forced exit. (Didn't gracefully exit because the event queue isn't empty. This is usally fine, see ...", { onlyOnce: false })
737
711
  */
738
712
  }
739
- function assertIsNotAbort(err, urlOr404) {
713
+ function assertIsNotAbort(err, urlOriginal) {
740
714
  if (!isAbortError(err))
741
715
  return;
742
716
  const pageContextAbort = err._pageContextAbort;
@@ -747,48 +721,12 @@ function assertIsNotAbort(err, urlOr404) {
747
721
  assert(abortCaller);
748
722
  const abortCall = pageContextAbort._abortCall;
749
723
  assert(abortCall);
750
- assertUsage(false, `${pc.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOr404} but ${pc.cyan(abortCaller)} isn't supported for pre-rendered pages`);
751
- }
752
- function validatePrerenderConfig(
753
- // Guaranteed by configDef.type to be either an object or boolean
754
- prerenderConfig) {
755
- if (!prerenderConfig || typeof prerenderConfig === 'boolean')
756
- return;
757
- assert(isObject(prerenderConfig));
758
- const wrongValue = (() => {
759
- {
760
- const p = 'partial';
761
- if (!hasProp(prerenderConfig, p, 'boolean') && !hasProp(prerenderConfig, p, 'undefined'))
762
- return { prop: p, errMsg: 'should be a boolean' };
763
- }
764
- {
765
- const p = 'noExtraDir';
766
- if (!hasProp(prerenderConfig, p, 'boolean') && !hasProp(prerenderConfig, p, 'undefined'))
767
- return { prop: p, errMsg: 'should be a boolean' };
768
- }
769
- {
770
- const p = 'disableAutoRun';
771
- if (!hasProp(prerenderConfig, p, 'boolean') && !hasProp(prerenderConfig, p, 'undefined'))
772
- return { prop: p, errMsg: 'should be a boolean' };
773
- }
774
- {
775
- const p = 'parallel';
776
- if (!hasProp(prerenderConfig, p, 'boolean') &&
777
- !hasProp(prerenderConfig, p, 'number') &&
778
- !hasProp(prerenderConfig, p, 'undefined'))
779
- return { prop: p, errMsg: 'should be a boolean or a number' };
780
- }
781
- })();
782
- if (wrongValue) {
783
- const { prop, errMsg } = wrongValue;
784
- assertUsage(false, `Setting ${pc.cyan(`prerender.${prop}`)} ${errMsg}`);
785
- }
724
+ assertUsage(false, `${pc.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOriginal} but ${pc.cyan(abortCaller)} isn't supported for pre-rendered pages`);
786
725
  }
787
726
  function makePublic(prerenderContext) {
788
727
  const prerenderContextPublic = makePublicCopy(prerenderContext, 'prerenderContext', [
789
728
  'output', // vite-plugin-vercel
790
- 'pageContexts', // https://vike.dev/i18n#pre-rendering
791
- 'pageContexts404' // https://vike.dev/i18n#pre-rendering
729
+ 'pageContexts' // https://vike.dev/i18n#pre-rendering
792
730
  ]);
793
731
  return prerenderContextPublic;
794
732
  }
@@ -27,7 +27,7 @@ declare function prerenderPage(pageContext: PageContextInitEnhanced & PageFiles
27
27
  _httpRequestId: number | null;
28
28
  _usesClientRouter: boolean;
29
29
  _pageContextAlreadyProvidedByOnPrerenderHook?: true;
30
- is404: null | boolean;
30
+ is404: boolean;
31
31
  }): Promise<{
32
32
  documentHtml: string;
33
33
  pageContextSerialized: null;
@@ -113,7 +113,7 @@ declare function prerenderPage(pageContext: PageContextInitEnhanced & PageFiles
113
113
  _httpRequestId: number | null;
114
114
  _usesClientRouter: boolean;
115
115
  _pageContextAlreadyProvidedByOnPrerenderHook?: true;
116
- is404: null | boolean;
116
+ is404: boolean;
117
117
  } & {
118
118
  isClientSideNavigation: boolean;
119
119
  _urlHandler: null;
@@ -203,7 +203,7 @@ declare function prerenderPage(pageContext: PageContextInitEnhanced & PageFiles
203
203
  _httpRequestId: number | null;
204
204
  _usesClientRouter: boolean;
205
205
  _pageContextAlreadyProvidedByOnPrerenderHook?: true;
206
- is404: null | boolean;
206
+ is404: boolean;
207
207
  } & {
208
208
  isClientSideNavigation: boolean;
209
209
  _urlHandler: null;
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.227-commit-ff6dcd9";
1
+ export declare const PROJECT_VERSION: "0.4.227-commit-d082773";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.227-commit-ff6dcd9';
2
+ export const PROJECT_VERSION = '0.4.227-commit-d082773';
@@ -19,8 +19,8 @@ function assertFilePathAbsoluteFilesystem(filePath) {
19
19
  // - For Linux users assertFilePathAbsoluteFilesystem() will erroneously succeed if `p` is a path absolute from the user root dir.
20
20
  // - But that's okay because the assertion will eventually fail for Windows users.
21
21
  // - On Linux there doesn't seem to be a way to distinguish between an absolute path starting from the filesystem root or starting from the user root directory, see comment at isFilePathAbsoluteFilesystem()
22
- assert(isFilePathAbsoluteFilesystem(filePath));
23
22
  assertPosixPath(filePath);
23
+ assert(isFilePathAbsoluteFilesystem(filePath));
24
24
  }
25
25
  /**
26
26
  * Whether `filePath` is an absolute file path starting from the filesystem root.
@@ -14,10 +14,10 @@ import { assert } from './assert.js';
14
14
  import { assertIsNotBrowser } from './assertIsNotBrowser.js';
15
15
  assertIsNotBrowser();
16
16
  function isNpmPackageImport(str, { cannotBePathAlias }) {
17
- // We cannot distinguish path alises that look like npm package imports
18
17
  assert(cannotBePathAlias);
19
18
  return isNpmPackageImport_unreliable(str);
20
19
  }
20
+ // We cannot distinguish path aliases that look like npm package imports
21
21
  function isNpmPackageImport_unreliable(str) {
22
22
  const res = parse(str);
23
23
  return res !== null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.227-commit-ff6dcd9",
3
+ "version": "0.4.227-commit-d082773",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {
@@ -123,7 +123,7 @@
123
123
  "@brillout/json-serializer": "^0.5.15",
124
124
  "@brillout/picocolors": "^1.0.26",
125
125
  "@brillout/require-shim": "^0.1.2",
126
- "@brillout/vite-plugin-server-entry": "^0.7.1",
126
+ "@brillout/vite-plugin-server-entry": "^0.7.5",
127
127
  "acorn": "^8.0.0",
128
128
  "cac": "^6.0.0",
129
129
  "es-module-lexer": "^1.0.0",