vike 0.4.148-commit-70e7518 → 0.4.149-commit-041ee42
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/plugins/devConfig/index.js +20 -9
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +25 -23
- package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +117 -81
- package/dist/cjs/node/runtime/html/injectAssets/inferHtmlTags.js +5 -5
- package/dist/cjs/node/runtime/html/injectAssets/mergeScriptTags.js +2 -1
- package/dist/cjs/node/runtime/renderPage/getPageAssets/retrieveAssetsProd.js +2 -3
- package/dist/cjs/node/runtime/renderPage/getPageAssets/sortPageAssetsForEarlyHintsHeader.js +6 -0
- package/dist/cjs/node/runtime/renderPage/inferMediaType.js +38 -0
- package/dist/cjs/shared/page-configs/assertExports.js +11 -4
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/client/shared/getPageContextSerializedInHtml.js +7 -1
- package/dist/esm/node/plugin/plugins/devConfig/index.js +20 -9
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +25 -23
- package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.d.ts +4 -0
- package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +117 -81
- package/dist/esm/node/runtime/html/injectAssets/inferHtmlTags.d.ts +2 -0
- package/dist/esm/node/runtime/html/injectAssets/inferHtmlTags.js +4 -4
- package/dist/esm/node/runtime/html/injectAssets/mergeScriptTags.js +2 -1
- package/dist/esm/node/runtime/renderPage/getPageAssets/retrieveAssetsProd.js +2 -3
- package/dist/esm/node/runtime/renderPage/getPageAssets/sortPageAssetsForEarlyHintsHeader.js +6 -0
- package/dist/esm/node/runtime/renderPage/inferMediaType.d.ts +2 -2
- package/dist/esm/node/runtime/renderPage/inferMediaType.js +38 -0
- package/dist/esm/shared/page-configs/assertExports.js +11 -4
- package/dist/esm/utils/projectInfo.d.ts +2 -2
- package/dist/esm/utils/projectInfo.js +1 -1
- package/package.json +2 -2
|
@@ -24,22 +24,33 @@ function devConfig() {
|
|
|
24
24
|
config() {
|
|
25
25
|
return {
|
|
26
26
|
appType: 'custom',
|
|
27
|
+
// TODO:v1-release: remove (AFAICT we only need to use config.optimizeDeps for the old design)
|
|
27
28
|
optimizeDeps: {
|
|
28
29
|
exclude: [
|
|
29
|
-
// We exclude
|
|
30
|
+
// We exclude Vike's client runtime to be able to use Vite's import.meta.glob()
|
|
30
31
|
'vike/client',
|
|
31
32
|
'vike/client/router',
|
|
32
33
|
'vike/routing',
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
// - Previously, we had to exclude @brillout/json-serializer and @brillout/picocolors because of pnpm, but this doesn't seem to be the case anymore.
|
|
39
|
-
// - Actually, this should be still the case? How can Vite resolve @brillout/json-serializer when using pnpm?
|
|
34
|
+
// We exclude @brillout/json-serializer and @brillout/picocolors to avoid:
|
|
35
|
+
// ```
|
|
36
|
+
// 9:28:58 AM [vite] ✨ new dependencies optimized: @brillout/json-serializer/parse
|
|
37
|
+
// 9:28:58 AM [vite] ✨ optimized dependencies changed. reloading
|
|
38
|
+
// ```
|
|
40
39
|
'@brillout/json-serializer/parse',
|
|
41
40
|
'@brillout/json-serializer/stringify',
|
|
42
|
-
'@brillout/picocolors'
|
|
41
|
+
'@brillout/picocolors',
|
|
42
|
+
// We exclude all packages that depend on any optimizeDeps.exclude entry because, otherwise, the entry cannot be resolved when using pnpm. For example:
|
|
43
|
+
// ```
|
|
44
|
+
// Failed to resolve import "@brillout/json-serializer/parse" from "../../packages/vike-react-query/dist/renderer/VikeReactQueryWrapper.js". Does the file exist?
|
|
45
|
+
// 343| // ../../node_modules/.pnpm/react-streaming@0.3.16_react-dom@18.2.0_react@18.2.0/node_modules/react-streaming/dist/esm/client/useAsync.js
|
|
46
|
+
// 344| import { parse as parse2 } from "@brillout/json-serializer/parse";
|
|
47
|
+
// ```
|
|
48
|
+
// The source map is confusing, the import actually lives at node_modules/.vite/deps/vike-react-query_renderer_VikeReactQueryWrapper.js which contains:
|
|
49
|
+
// ```js
|
|
50
|
+
// // ../../node_modules/.pnpm/react-streaming@0.3.16_react-dom@18.2.0_react@18.2.0/node_modules/react-streaming/dist/esm/client/useAsync.js
|
|
51
|
+
// import { parse as parse2 } from "@brillout/json-serializer/parse";
|
|
52
|
+
// ```
|
|
53
|
+
'react-streaming'
|
|
43
54
|
]
|
|
44
55
|
}
|
|
45
56
|
};
|
package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js
CHANGED
|
@@ -56,18 +56,8 @@ async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem, isDev) {
|
|
|
56
56
|
exports.crawlPlusFiles = crawlPlusFiles;
|
|
57
57
|
// Same as fastGlob() but using `$ git ls-files`
|
|
58
58
|
async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let stdout;
|
|
62
|
-
try {
|
|
63
|
-
const res = await execA('git rev-parse --is-inside-work-tree', { cwd: userRootDir });
|
|
64
|
-
stdout = res.stdout;
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
(0, utils_js_1.assert)(stdout.trim() === 'true');
|
|
70
|
-
}
|
|
59
|
+
if (!(await isUsingGit(userRootDir)))
|
|
60
|
+
return null;
|
|
71
61
|
const cmd = [
|
|
72
62
|
'git ls-files',
|
|
73
63
|
...utils_js_1.scriptFileExtensionList.map((ext) => `"**/+*.${ext}"`),
|
|
@@ -76,20 +66,13 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
|
|
|
76
66
|
// --cached adds the tracked files to the output
|
|
77
67
|
'--others --cached --exclude-standard'
|
|
78
68
|
].join(' ');
|
|
79
|
-
let
|
|
80
|
-
try {
|
|
81
|
-
const res = await execA(cmd, { cwd: userRootDir });
|
|
82
|
-
stdout = res.stdout;
|
|
83
|
-
}
|
|
84
|
-
catch (err) {
|
|
85
|
-
if (err.message.includes('not a git repository'))
|
|
86
|
-
return null;
|
|
87
|
-
throw err;
|
|
88
|
-
}
|
|
89
|
-
let files = stdout.split('\n').filter(Boolean);
|
|
69
|
+
let files = await runCmd(cmd, userRootDir);
|
|
90
70
|
files = files.filter(
|
|
91
71
|
// 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.)
|
|
92
72
|
(file) => getIgnoreFilter(file, outDirRelativeFromUserRootDir));
|
|
73
|
+
// Remove tracked but deleted files
|
|
74
|
+
const filesIgnore = await runCmd('git ls-files --deleted', userRootDir);
|
|
75
|
+
files = files.filter((file) => !filesIgnore.includes(file));
|
|
93
76
|
return files;
|
|
94
77
|
}
|
|
95
78
|
// Same as gitLsFiles() but using fast-glob
|
|
@@ -126,3 +109,22 @@ function getIgnoreFilter(file, outDirRelativeFromUserRootDir) {
|
|
|
126
109
|
!file.includes('.telefunc.') &&
|
|
127
110
|
(!outDirRelativeFromUserRootDir || !file.startsWith(`${outDirRelativeFromUserRootDir}/`)));
|
|
128
111
|
}
|
|
112
|
+
// Whether Git is installed and whether userRootDir is inside a Git repository
|
|
113
|
+
async function isUsingGit(userRootDir) {
|
|
114
|
+
let res;
|
|
115
|
+
try {
|
|
116
|
+
res = await execA('git rev-parse --is-inside-work-tree', { cwd: userRootDir });
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const { stdout, stderr } = res;
|
|
122
|
+
(0, utils_js_1.assert)(stderr.toString().trim() === '');
|
|
123
|
+
(0, utils_js_1.assert)(stdout.toString().trim() === 'true');
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
async function runCmd(cmd, cwd) {
|
|
127
|
+
const res = await execA(cmd, { cwd });
|
|
128
|
+
(0, utils_js_1.assert)(res.stderr === '');
|
|
129
|
+
return res.stdout.toString().trim().split('\n');
|
|
130
|
+
}
|
|
@@ -12,39 +12,37 @@ const getViteDevScripts_js_1 = require("./getViteDevScripts.js");
|
|
|
12
12
|
const mergeScriptTags_js_1 = require("./mergeScriptTags.js");
|
|
13
13
|
const globalContext_js_1 = require("../../globalContext.js");
|
|
14
14
|
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
|
|
15
|
+
const stamp = '__injectFilterEntry';
|
|
15
16
|
async function getHtmlTags(pageContext, injectToStream, injectFilter) {
|
|
16
17
|
(0, utils_js_1.assert)([true, false].includes(pageContext._isHtmlOnly));
|
|
17
18
|
const isHtmlOnly = pageContext._isHtmlOnly;
|
|
18
|
-
const
|
|
19
|
-
const { isProduction } = globalContext;
|
|
20
|
-
const injectJavaScriptDuringStream = !pageContext._pageContextPromise && !!injectToStream;
|
|
19
|
+
const { isProduction } = (0, globalContext_js_1.getGlobalContext)();
|
|
21
20
|
const pageAssets = await pageContext.__getPageAssets();
|
|
22
|
-
const stamp = Symbol('injectFilterEntryStamp');
|
|
23
|
-
const getInject = (asset) => {
|
|
24
|
-
if (!isProduction) {
|
|
25
|
-
return 'HTML_BEGIN';
|
|
26
|
-
}
|
|
27
|
-
if (asset.assetType === 'style' || asset.assetType === 'font') {
|
|
28
|
-
return 'HTML_BEGIN';
|
|
29
|
-
}
|
|
30
|
-
if (asset.assetType === 'script') {
|
|
31
|
-
return 'HTML_END';
|
|
32
|
-
}
|
|
33
|
-
return false;
|
|
34
|
-
};
|
|
35
21
|
const injectFilterEntries = pageAssets
|
|
36
22
|
.filter((asset) => {
|
|
37
23
|
if (asset.isEntry && asset.assetType === 'script') {
|
|
38
|
-
// We could
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
24
|
+
// We could allow the user to change the position of <script> but we currently don't:
|
|
25
|
+
// - Because of mergeScriptEntries()
|
|
26
|
+
// - We would need to add STREAM to to PreloadFilterInject
|
|
27
|
+
// To suppor this, we should add the JavaScript entry to injectFilterEntries (with an `src` value of `null`)
|
|
42
28
|
return false;
|
|
43
29
|
}
|
|
44
30
|
return true;
|
|
45
31
|
})
|
|
46
32
|
.map((asset) => {
|
|
47
|
-
const inject =
|
|
33
|
+
const inject = (() => {
|
|
34
|
+
if (!isProduction) {
|
|
35
|
+
// In development, we should always load assets as soon as possible, in order to eagerly process assets (e.g. applying the transform() hooks of Vite plugins) which are lazily discovered.
|
|
36
|
+
return 'HTML_BEGIN';
|
|
37
|
+
}
|
|
38
|
+
if (asset.assetType === 'style' || asset.assetType === 'font') {
|
|
39
|
+
return 'HTML_BEGIN';
|
|
40
|
+
}
|
|
41
|
+
if (asset.assetType === 'script') {
|
|
42
|
+
return 'HTML_END';
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
})();
|
|
48
46
|
const entry = {
|
|
49
47
|
...asset,
|
|
50
48
|
inject,
|
|
@@ -53,92 +51,104 @@ async function getHtmlTags(pageContext, injectToStream, injectFilter) {
|
|
|
53
51
|
};
|
|
54
52
|
return entry;
|
|
55
53
|
});
|
|
56
|
-
assertInjectFilterEntries(injectFilterEntries
|
|
54
|
+
assertInjectFilterEntries(injectFilterEntries);
|
|
55
|
+
// ==============
|
|
56
|
+
// injectFilter()
|
|
57
|
+
// ==============
|
|
57
58
|
if (injectFilter && isProduction) {
|
|
58
59
|
Object.seal(injectFilterEntries); // `Object.seal()` instead of `Object.freeze()` to allow the user to `assets.sort()`
|
|
59
60
|
Object.values(injectFilterEntries).forEach((entry) => (0, utils_js_1.freezePartial)(entry, { inject: (val) => val === false || val === 'HTML_BEGIN' || val === 'HTML_END' }));
|
|
61
|
+
// Call the user's injectFilter() hook https://vike.dev/injectFilter
|
|
60
62
|
const res = injectFilter(injectFilterEntries);
|
|
61
|
-
(0, utils_js_1.assertUsage)(res === undefined,
|
|
62
|
-
assertInjectFilterUsage(injectFilterEntries
|
|
63
|
-
injectFilterEntries.forEach((a) => {
|
|
64
|
-
/*
|
|
65
|
-
if (a.assetType === 'script' && a.isEntry) {
|
|
66
|
-
assertUsage(a.inject, `[injectFilter()] ${a.src} needs to be injected`)
|
|
67
|
-
}
|
|
68
|
-
*/
|
|
69
|
-
if (a.assetType === 'style' && a.isEntry) {
|
|
70
|
-
// In development, Vite automatically inject styles, but we still inject `<link rel="stylesheet" type="text/css" href="${src}">` tags in order to avoid FOUC (flash of unstyled content).
|
|
71
|
-
// - https://github.com/vitejs/vite/issues/2282
|
|
72
|
-
// - https://github.com/vikejs/vike/issues/261
|
|
73
|
-
(0, utils_js_1.assertWarning)(a.inject, `[injectFilter()] We recommend against not injecting ${a.src}`, {
|
|
74
|
-
onlyOnce: true
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
if (!isHtmlOnly && a.assetType === 'script') {
|
|
78
|
-
(0, utils_js_1.assertWarning)(a.inject, `[injectFilter()] We recommend against not preloading JavaScript (${a.src})`, {
|
|
79
|
-
onlyOnce: true
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
});
|
|
63
|
+
(0, utils_js_1.assertUsage)(res === undefined, `injectFilter() should return ${picocolors_1.default.cyan('undefined')}, see https://vike.dev/injectFilter`);
|
|
64
|
+
assertInjectFilterUsage(injectFilterEntries);
|
|
83
65
|
}
|
|
84
66
|
const htmlTags = [];
|
|
67
|
+
// ==============
|
|
85
68
|
// Non-JavaScript
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
69
|
+
// ==============
|
|
70
|
+
injectFilterEntries
|
|
71
|
+
.filter((asset) => asset.assetType !== 'script' && asset.inject)
|
|
72
|
+
.forEach((asset) => {
|
|
73
|
+
if (!asset.inject)
|
|
74
|
+
return;
|
|
75
|
+
const htmlTag = asset.isEntry ? (0, inferHtmlTags_js_1.inferAssetTag)(asset) : (0, inferHtmlTags_js_1.inferPreloadTag)(asset);
|
|
76
|
+
htmlTags.push({ htmlTag, position: asset.inject });
|
|
77
|
+
});
|
|
78
|
+
// ==========
|
|
92
79
|
// JavaScript
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
// ==========
|
|
81
|
+
// In order to avoid the race-condition depicted in https://github.com/vikejs/vike/issues/567
|
|
82
|
+
// 1. <script id="vike_pageContext" type="application/json"> must appear before the entry <script> (which loads Vike's client runtime).
|
|
83
|
+
// 2. <script id="vike_pageContext" type="application/json"> can't be async nor defer.
|
|
84
|
+
// Additionally:
|
|
85
|
+
// 3. the entry <script> can't be defer, otherwise progressive hydration while SSR streaming won't work.
|
|
86
|
+
// 4. the entry <script> should be towards the end of the HTML as performance-wise it's more interesting to parse
|
|
87
|
+
// <div id="page-view"> before running the entry <script> which initiates the hydration.
|
|
88
|
+
// See https://github.com/vikejs/vike/pull/1271
|
|
89
|
+
const positionJavaScriptEntry = (() => {
|
|
90
|
+
if (pageContext._pageContextPromise) {
|
|
91
|
+
(0, utils_js_1.assertWarning)(!injectToStream, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time as partial hydration won't work", { onlyOnce: true });
|
|
92
|
+
// If there is a pageContext._pageContextPromise (which is resolved after the stream has ended) then the pageContext JSON data needs to await for it: https://vike.dev/stream#initial-data-after-stream-end
|
|
93
|
+
return 'HTML_END';
|
|
94
|
+
}
|
|
95
|
+
if (injectToStream) {
|
|
96
|
+
// If there is a stream then, in order to support partial hydration, inject the JavaScript during the stream after React(/Vue/Solid/...) resolved the first suspense boundary
|
|
97
|
+
return 'STREAM';
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return 'HTML_END';
|
|
101
|
+
}
|
|
102
|
+
})();
|
|
103
|
+
// <script id="vike_pageContext" type="application/json">
|
|
104
|
+
if (!isHtmlOnly) {
|
|
98
105
|
htmlTags.push({
|
|
99
|
-
htmlTag:
|
|
100
|
-
|
|
106
|
+
htmlTag: () =>
|
|
107
|
+
// Needs to be called after resolvePageContextPromise()
|
|
108
|
+
getPageContextJsonScriptTag(pageContext),
|
|
109
|
+
position: positionJavaScriptEntry
|
|
101
110
|
});
|
|
102
111
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const position = asset.inject === 'HTML_END' ? positionScript : asset.inject;
|
|
107
|
-
htmlTags.push({ htmlTag, position });
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
// `pageContext` JSON data
|
|
111
|
-
if (!isHtmlOnly) {
|
|
112
|
-
// Don't allow the user to manipulate with injectFilter(): injecting <script type="application/json"> before the stream can break the app when:
|
|
113
|
-
// - using https://vike.dev/stream#initial-data-after-stream-end
|
|
114
|
-
// - `pageContext` is modified during the stream, e.g. https://github.com/brillout/vike-with-pinia which uses https://vuejs.org/api/composition-api-lifecycle.html#onserverprefetch
|
|
115
|
-
// The <script> tags are handled separately by vike down below.
|
|
112
|
+
// The JavaScript entry <script> tag
|
|
113
|
+
const scriptEntry = await mergeScriptEntries(pageAssets, isProduction);
|
|
114
|
+
if (scriptEntry) {
|
|
116
115
|
htmlTags.push({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
position: positionJsonData
|
|
116
|
+
htmlTag: scriptEntry,
|
|
117
|
+
position: positionJavaScriptEntry
|
|
120
118
|
});
|
|
121
119
|
}
|
|
120
|
+
// Preload tags
|
|
121
|
+
injectFilterEntries
|
|
122
|
+
.filter((asset) => asset.assetType === 'script')
|
|
123
|
+
.forEach((asset) => {
|
|
124
|
+
(0, utils_js_1.assert)(!asset.isEntry); // Users cannot re-order JavaScript entries, see creation of injectFilterEntries
|
|
125
|
+
const htmlTag = (0, inferHtmlTags_js_1.inferPreloadTag)(asset);
|
|
126
|
+
if (!asset.inject)
|
|
127
|
+
return;
|
|
128
|
+
// Ideally, instead of this conditional ternary operator, we should add STREAM to PreloadFilterInject (or a better fitting name such as HTML_STREAM)
|
|
129
|
+
const position = asset.inject === 'HTML_END' ? positionJavaScriptEntry : asset.inject;
|
|
130
|
+
htmlTags.push({ htmlTag, position });
|
|
131
|
+
});
|
|
122
132
|
return htmlTags;
|
|
123
133
|
}
|
|
124
134
|
exports.getHtmlTags = getHtmlTags;
|
|
125
|
-
async function
|
|
126
|
-
const
|
|
135
|
+
async function mergeScriptEntries(pageAssets, isProduction) {
|
|
136
|
+
const scriptEntries = pageAssets.filter((pageAsset) => pageAsset.isEntry && pageAsset.assetType === 'script');
|
|
127
137
|
const viteScripts = await (0, getViteDevScripts_js_1.getViteDevScripts)();
|
|
128
|
-
const scriptTagsHtml = `${viteScripts}${
|
|
138
|
+
const scriptTagsHtml = `${viteScripts}${scriptEntries.map((asset) => (0, inferHtmlTags_js_1.inferAssetTag)(asset)).join('')}`;
|
|
129
139
|
const scriptTag = (0, mergeScriptTags_js_1.mergeScriptTags)(scriptTagsHtml, isProduction);
|
|
130
140
|
return scriptTag;
|
|
131
141
|
}
|
|
132
|
-
function
|
|
142
|
+
function getPageContextJsonScriptTag(pageContext) {
|
|
133
143
|
const pageContextSerialized = (0, sanitizeJson_js_1.sanitizeJson)((0, serializePageContextClientSide_js_1.serializePageContextClientSide)(pageContext));
|
|
134
144
|
const htmlTag = `<script id="vike_pageContext" type="application/json">${pageContextSerialized}</script>`;
|
|
135
145
|
// @ts-expect-error
|
|
136
146
|
pageContext._pageContextHtmlTag = htmlTag;
|
|
137
147
|
return htmlTag;
|
|
138
148
|
}
|
|
139
|
-
function assertInjectFilterEntries(injectFilterEntries
|
|
149
|
+
function assertInjectFilterEntries(injectFilterEntries) {
|
|
140
150
|
try {
|
|
141
|
-
|
|
151
|
+
checkForWrongUsage(injectFilterEntries);
|
|
142
152
|
}
|
|
143
153
|
catch (err) {
|
|
144
154
|
if (err?.message.includes('[Wrong Usage]')) {
|
|
@@ -147,7 +157,11 @@ function assertInjectFilterEntries(injectFilterEntries, stamp) {
|
|
|
147
157
|
throw err;
|
|
148
158
|
}
|
|
149
159
|
}
|
|
150
|
-
function assertInjectFilterUsage(injectFilterEntries
|
|
160
|
+
function assertInjectFilterUsage(injectFilterEntries) {
|
|
161
|
+
checkForWrongUsage(injectFilterEntries);
|
|
162
|
+
checkForWarnings(injectFilterEntries);
|
|
163
|
+
}
|
|
164
|
+
function checkForWrongUsage(injectFilterEntries) {
|
|
151
165
|
injectFilterEntries.forEach((entry, i) => {
|
|
152
166
|
(0, utils_js_1.assertUsage)((0, utils_js_1.isObject)(entry), `[injectFilter()] Entry ${i} isn't an object`);
|
|
153
167
|
(0, utils_js_1.assertUsage)(typeof entry.src === 'string', `[injectFilter()] Entry ${i} is missing property ${picocolors_1.default.cyan('src')}`);
|
|
@@ -156,6 +170,28 @@ function assertInjectFilterUsage(injectFilterEntries, stamp) {
|
|
|
156
170
|
(0, utils_js_1.assert)(entry.assetType === null || typeof entry.assetType === 'string');
|
|
157
171
|
(0, utils_js_1.assert)(entry.mediaType === null || typeof entry.mediaType === 'string');
|
|
158
172
|
(0, utils_js_1.assert)(typeof entry.isEntry === 'boolean');
|
|
159
|
-
(0, utils_js_1.assert)(Object.keys(entry).length ===
|
|
173
|
+
(0, utils_js_1.assert)(Object.keys(entry).length === 6);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function checkForWarnings(injectFilterEntries) {
|
|
177
|
+
injectFilterEntries.forEach((a) => {
|
|
178
|
+
/*
|
|
179
|
+
if (a.assetType === 'script' && a.isEntry) {
|
|
180
|
+
assertUsage(a.inject, `[injectFilter()] ${a.src} needs to be injected`)
|
|
181
|
+
}
|
|
182
|
+
*/
|
|
183
|
+
if (a.assetType === 'style' && a.isEntry) {
|
|
184
|
+
// In development, Vite automatically inject styles, but we still inject `<link rel="stylesheet" type="text/css" href="${src}">` tags in order to avoid FOUC (flash of unstyled content).
|
|
185
|
+
// - https://github.com/vitejs/vite/issues/2282
|
|
186
|
+
// - https://github.com/vikejs/vike/issues/261
|
|
187
|
+
(0, utils_js_1.assertWarning)(a.inject, `[injectFilter()] We recommend against not injecting ${a.src}`, {
|
|
188
|
+
onlyOnce: true
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
if (a.assetType === 'script') {
|
|
192
|
+
(0, utils_js_1.assertWarning)(a.inject, `[injectFilter()] We recommend against not preloading JavaScript (${a.src})`, {
|
|
193
|
+
onlyOnce: true
|
|
194
|
+
});
|
|
195
|
+
}
|
|
160
196
|
});
|
|
161
197
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.inferEarlyHintLink = exports.inferPreloadTag = exports.inferAssetTag = void 0;
|
|
3
|
+
exports.scriptAttrs = exports.inferEarlyHintLink = exports.inferPreloadTag = exports.inferAssetTag = void 0;
|
|
4
4
|
const utils_js_1 = require("../../utils.js");
|
|
5
|
+
// We can't use `defer` here. With `defer`, the entry script won't start before `</body>` has been parsed, preventing partial hydration during SSR streaming, see https://github.com/vikejs/vike/pull/1271
|
|
6
|
+
const scriptAttrs = 'type="module" async';
|
|
7
|
+
exports.scriptAttrs = scriptAttrs;
|
|
5
8
|
function inferPreloadTag(pageAsset) {
|
|
6
9
|
const { src, assetType, mediaType } = pageAsset;
|
|
7
10
|
const rel = getRel(pageAsset);
|
|
@@ -22,10 +25,7 @@ function inferAssetTag(pageAsset) {
|
|
|
22
25
|
const { src, assetType, mediaType } = pageAsset;
|
|
23
26
|
if (assetType === 'script') {
|
|
24
27
|
(0, utils_js_1.assert)(mediaType === 'text/javascript');
|
|
25
|
-
|
|
26
|
-
// - in dev: https://github.com/vikejs/vike/issues/524
|
|
27
|
-
// - in prod: https://github.com/vikejs/vike/issues/567
|
|
28
|
-
return `<script type="module" src="${src}" defer></script>`;
|
|
28
|
+
return `<script src="${src}" ${scriptAttrs}></script>`;
|
|
29
29
|
}
|
|
30
30
|
if (assetType === 'style') {
|
|
31
31
|
return `<link rel="stylesheet" type="text/css" href="${src}">`;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.mergeScriptTags = void 0;
|
|
4
4
|
const utils_js_1 = require("../../utils.js");
|
|
5
|
+
const inferHtmlTags_js_1 = require("./inferHtmlTags.js");
|
|
5
6
|
const scriptRE = /(<script\b(?:\s[^>]*>|>))(.*?)<\/script>/gims;
|
|
6
7
|
const srcRE = /\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s'">]+))/im;
|
|
7
8
|
const typeRE = /\btype\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s'">]+))/im;
|
|
@@ -34,7 +35,7 @@ function mergeScriptTags(scriptTagsHtml, isProduction) {
|
|
|
34
35
|
}
|
|
35
36
|
});
|
|
36
37
|
if (contents.length > 0) {
|
|
37
|
-
scriptTag += `<script
|
|
38
|
+
scriptTag += `<script ${inferHtmlTags_js_1.scriptAttrs}>\n${contents.join('\n')}\n</script>`;
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -14,8 +14,7 @@ function retrieveAssetsProd(clientDependencies, clientManifest, includeAssetsImp
|
|
|
14
14
|
if (onlyAssets) {
|
|
15
15
|
if (!includeAssetsImportedByServer)
|
|
16
16
|
return;
|
|
17
|
-
// We assume that all npm packages have already built their
|
|
18
|
-
// - Bundlers (Rollup, esbuild, tsup, ...) extract the CSS out of JavaScript => we can assume JavaScript to not import any CSS/assets
|
|
17
|
+
// We assume that all npm packages have already built their files: bundlers (Rollup, esbuild, tsup, ...) extract the CSS out of JavaScript => we can assume JavaScript to not import any CSS/assets.
|
|
19
18
|
if ((0, utils_js_1.isNpmPackageImport)(id))
|
|
20
19
|
return;
|
|
21
20
|
if (id.includes('.page.server.')) {
|
|
@@ -52,7 +51,7 @@ function collectAssets(manifestKey, assetUrls, visistedAssets, manifest, onlyCol
|
|
|
52
51
|
assetUrls.add(`/${asset}`);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
|
-
// Support `config.build.cssCodeSplit: false`, https://github.com/vikejs/vike/issues/644
|
|
54
|
+
// Support `config.build.cssCodeSplit: false`, see https://github.com/vikejs/vike/issues/644
|
|
56
55
|
function collectSingleStyle(assetUrls, manifest) {
|
|
57
56
|
const style = manifest['style.css'];
|
|
58
57
|
if (style && Object.values(manifest).filter((asset) => asset.file.endsWith('.css')).length === 1) {
|
|
@@ -22,6 +22,12 @@ function sortPageAssetsForEarlyHintsHeader(pageAssets) {
|
|
|
22
22
|
if (assetType === 'image')
|
|
23
23
|
return priority;
|
|
24
24
|
priority--;
|
|
25
|
+
if (assetType === 'video')
|
|
26
|
+
return priority;
|
|
27
|
+
priority--;
|
|
28
|
+
if (assetType === 'audio')
|
|
29
|
+
return priority;
|
|
30
|
+
priority--;
|
|
25
31
|
// Others
|
|
26
32
|
if (assetType !== 'script')
|
|
27
33
|
return priority;
|
|
@@ -36,6 +36,44 @@ function inferMediaType(href) {
|
|
|
36
36
|
if (href.endsWith('.woff2')) {
|
|
37
37
|
return { assetType: 'font', mediaType: 'font/woff2' };
|
|
38
38
|
}
|
|
39
|
+
// Videos
|
|
40
|
+
if (href.endsWith('.mp4')) {
|
|
41
|
+
return { assetType: 'video', mediaType: 'video/mp4' };
|
|
42
|
+
}
|
|
43
|
+
if (href.endsWith('.webm')) {
|
|
44
|
+
return { assetType: 'video', mediaType: 'video/webm' };
|
|
45
|
+
}
|
|
46
|
+
if (href.endsWith('.ogv')) {
|
|
47
|
+
return { assetType: 'video', mediaType: 'video/ogg' };
|
|
48
|
+
}
|
|
49
|
+
if (href.endsWith('.mpeg') || href.endsWith('.mpg')) {
|
|
50
|
+
return { assetType: 'video', mediaType: 'video/mpeg' };
|
|
51
|
+
}
|
|
52
|
+
if (href.endsWith('.avi')) {
|
|
53
|
+
return { assetType: 'video', mediaType: 'video/x-msvideo' };
|
|
54
|
+
}
|
|
55
|
+
if (href.endsWith('.mov') || href.endsWith('.qt')) {
|
|
56
|
+
return { assetType: 'video', mediaType: 'video/quicktime' };
|
|
57
|
+
}
|
|
58
|
+
// Audios
|
|
59
|
+
if (href.endsWith('.mp3')) {
|
|
60
|
+
return { assetType: 'audio', mediaType: 'audio/mpeg' };
|
|
61
|
+
}
|
|
62
|
+
if (href.endsWith('.wav')) {
|
|
63
|
+
return { assetType: 'audio', mediaType: 'audio/wav' };
|
|
64
|
+
}
|
|
65
|
+
if (href.endsWith('.ogg')) {
|
|
66
|
+
return { assetType: 'audio', mediaType: 'audio/ogg' };
|
|
67
|
+
}
|
|
68
|
+
if (href.endsWith('.m4a')) {
|
|
69
|
+
return { assetType: 'audio', mediaType: 'audio/aac' };
|
|
70
|
+
}
|
|
71
|
+
if (href.endsWith('midi') || href.endsWith('.mid')) {
|
|
72
|
+
return { assetType: 'audio', mediaType: 'audio/midi' };
|
|
73
|
+
}
|
|
74
|
+
if (href.endsWith('.flac')) {
|
|
75
|
+
return { assetType: 'audio', mediaType: 'audio/flac' };
|
|
76
|
+
}
|
|
39
77
|
return null;
|
|
40
78
|
}
|
|
41
79
|
exports.inferMediaType = inferMediaType;
|
|
@@ -34,13 +34,20 @@ function assertExports(fileExports, filePathToShowToUser, configName) {
|
|
|
34
34
|
if (exportsRelevant.length === 1) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const exportDefault = picocolors_1.default.cyan('export default');
|
|
38
|
+
const exportConfigName = picocolors_1.default.cyan(`export { ${configName} }`);
|
|
39
|
+
if (exportsRelevant.length === 0) {
|
|
40
|
+
let errMsg = `${filePathToShowToUser} doesn't export any value, but it should have a ${exportDefault}`;
|
|
40
41
|
if (configName)
|
|
41
|
-
errMsg += ` or ${
|
|
42
|
+
errMsg += ` or ${exportConfigName}`;
|
|
42
43
|
(0, utils_js_1.assertUsage)(false, errMsg);
|
|
43
44
|
}
|
|
45
|
+
else {
|
|
46
|
+
(0, utils_js_1.assert)(exportsRelevant.length === 2);
|
|
47
|
+
(0, utils_js_1.assertWarning)(false, `${filePathToShowToUser} remove ${exportConfigName} or ${exportDefault}`, {
|
|
48
|
+
onlyOnce: true
|
|
49
|
+
});
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
else {
|
|
46
53
|
// !configName => isConfigFile
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PROJECT_VERSION = exports.projectInfo = void 0;
|
|
4
4
|
const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
|
|
5
|
-
const PROJECT_VERSION = '0.4.
|
|
5
|
+
const PROJECT_VERSION = '0.4.149-commit-041ee42';
|
|
6
6
|
exports.PROJECT_VERSION = PROJECT_VERSION;
|
|
7
7
|
const projectInfo = {
|
|
8
8
|
projectName: 'Vike',
|
|
@@ -2,9 +2,15 @@ import { parse } from '@brillout/json-serializer/parse';
|
|
|
2
2
|
import { hasProp, assert, assertUsage, objectAssign } from '../server-routing-runtime/utils.js';
|
|
3
3
|
export { getPageContextSerializedInHtml };
|
|
4
4
|
function getPageContextSerializedInHtml() {
|
|
5
|
+
// elem should exist because:
|
|
6
|
+
// 1. <script id="vike_pageContext" type="application/json"> appears before the <script> that loads Vike's client runtime (which includes this file)
|
|
7
|
+
// 2. <script id="vike_pageContext" type="application/json"> is neither async nor defer
|
|
8
|
+
// See https://github.com/vikejs/vike/pull/1271
|
|
5
9
|
const id = 'vike_pageContext';
|
|
6
10
|
const elem = document.getElementById(id);
|
|
7
|
-
assertUsage(elem,
|
|
11
|
+
assertUsage(elem,
|
|
12
|
+
// It seems like it can be missing because of malformed HTML: https://github.com/vikejs/vike/issues/913
|
|
13
|
+
`Couldn't find #${id} (which Vike automatically injects in the HTML): make sure it exists (i.e. don't remove it and make sure your HTML isn't malformed)`);
|
|
8
14
|
const pageContextJson = elem.textContent;
|
|
9
15
|
assert(pageContextJson);
|
|
10
16
|
const pageContextSerializedInHtml = parse(pageContextJson);
|
|
@@ -22,22 +22,33 @@ function devConfig() {
|
|
|
22
22
|
config() {
|
|
23
23
|
return {
|
|
24
24
|
appType: 'custom',
|
|
25
|
+
// TODO:v1-release: remove (AFAICT we only need to use config.optimizeDeps for the old design)
|
|
25
26
|
optimizeDeps: {
|
|
26
27
|
exclude: [
|
|
27
|
-
// We exclude
|
|
28
|
+
// We exclude Vike's client runtime to be able to use Vite's import.meta.glob()
|
|
28
29
|
'vike/client',
|
|
29
30
|
'vike/client/router',
|
|
30
31
|
'vike/routing',
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
// - Previously, we had to exclude @brillout/json-serializer and @brillout/picocolors because of pnpm, but this doesn't seem to be the case anymore.
|
|
37
|
-
// - Actually, this should be still the case? How can Vite resolve @brillout/json-serializer when using pnpm?
|
|
32
|
+
// We exclude @brillout/json-serializer and @brillout/picocolors to avoid:
|
|
33
|
+
// ```
|
|
34
|
+
// 9:28:58 AM [vite] ✨ new dependencies optimized: @brillout/json-serializer/parse
|
|
35
|
+
// 9:28:58 AM [vite] ✨ optimized dependencies changed. reloading
|
|
36
|
+
// ```
|
|
38
37
|
'@brillout/json-serializer/parse',
|
|
39
38
|
'@brillout/json-serializer/stringify',
|
|
40
|
-
'@brillout/picocolors'
|
|
39
|
+
'@brillout/picocolors',
|
|
40
|
+
// We exclude all packages that depend on any optimizeDeps.exclude entry because, otherwise, the entry cannot be resolved when using pnpm. For example:
|
|
41
|
+
// ```
|
|
42
|
+
// Failed to resolve import "@brillout/json-serializer/parse" from "../../packages/vike-react-query/dist/renderer/VikeReactQueryWrapper.js". Does the file exist?
|
|
43
|
+
// 343| // ../../node_modules/.pnpm/react-streaming@0.3.16_react-dom@18.2.0_react@18.2.0/node_modules/react-streaming/dist/esm/client/useAsync.js
|
|
44
|
+
// 344| import { parse as parse2 } from "@brillout/json-serializer/parse";
|
|
45
|
+
// ```
|
|
46
|
+
// The source map is confusing, the import actually lives at node_modules/.vite/deps/vike-react-query_renderer_VikeReactQueryWrapper.js which contains:
|
|
47
|
+
// ```js
|
|
48
|
+
// // ../../node_modules/.pnpm/react-streaming@0.3.16_react-dom@18.2.0_react@18.2.0/node_modules/react-streaming/dist/esm/client/useAsync.js
|
|
49
|
+
// import { parse as parse2 } from "@brillout/json-serializer/parse";
|
|
50
|
+
// ```
|
|
51
|
+
'react-streaming'
|
|
41
52
|
]
|
|
42
53
|
}
|
|
43
54
|
};
|
package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js
CHANGED
|
@@ -50,18 +50,8 @@ async function crawlPlusFiles(userRootDir, outDirAbsoluteFilesystem, isDev) {
|
|
|
50
50
|
}
|
|
51
51
|
// Same as fastGlob() but using `$ git ls-files`
|
|
52
52
|
async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let stdout;
|
|
56
|
-
try {
|
|
57
|
-
const res = await execA('git rev-parse --is-inside-work-tree', { cwd: userRootDir });
|
|
58
|
-
stdout = res.stdout;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
assert(stdout.trim() === 'true');
|
|
64
|
-
}
|
|
53
|
+
if (!(await isUsingGit(userRootDir)))
|
|
54
|
+
return null;
|
|
65
55
|
const cmd = [
|
|
66
56
|
'git ls-files',
|
|
67
57
|
...scriptFileExtensionList.map((ext) => `"**/+*.${ext}"`),
|
|
@@ -70,20 +60,13 @@ async function gitLsFiles(userRootDir, outDirRelativeFromUserRootDir) {
|
|
|
70
60
|
// --cached adds the tracked files to the output
|
|
71
61
|
'--others --cached --exclude-standard'
|
|
72
62
|
].join(' ');
|
|
73
|
-
let
|
|
74
|
-
try {
|
|
75
|
-
const res = await execA(cmd, { cwd: userRootDir });
|
|
76
|
-
stdout = res.stdout;
|
|
77
|
-
}
|
|
78
|
-
catch (err) {
|
|
79
|
-
if (err.message.includes('not a git repository'))
|
|
80
|
-
return null;
|
|
81
|
-
throw err;
|
|
82
|
-
}
|
|
83
|
-
let files = stdout.split('\n').filter(Boolean);
|
|
63
|
+
let files = await runCmd(cmd, userRootDir);
|
|
84
64
|
files = files.filter(
|
|
85
65
|
// 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.)
|
|
86
66
|
(file) => getIgnoreFilter(file, outDirRelativeFromUserRootDir));
|
|
67
|
+
// Remove tracked but deleted files
|
|
68
|
+
const filesIgnore = await runCmd('git ls-files --deleted', userRootDir);
|
|
69
|
+
files = files.filter((file) => !filesIgnore.includes(file));
|
|
87
70
|
return files;
|
|
88
71
|
}
|
|
89
72
|
// Same as gitLsFiles() but using fast-glob
|
|
@@ -120,3 +103,22 @@ function getIgnoreFilter(file, outDirRelativeFromUserRootDir) {
|
|
|
120
103
|
!file.includes('.telefunc.') &&
|
|
121
104
|
(!outDirRelativeFromUserRootDir || !file.startsWith(`${outDirRelativeFromUserRootDir}/`)));
|
|
122
105
|
}
|
|
106
|
+
// Whether Git is installed and whether userRootDir is inside a Git repository
|
|
107
|
+
async function isUsingGit(userRootDir) {
|
|
108
|
+
let res;
|
|
109
|
+
try {
|
|
110
|
+
res = await execA('git rev-parse --is-inside-work-tree', { cwd: userRootDir });
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
const { stdout, stderr } = res;
|
|
116
|
+
assert(stderr.toString().trim() === '');
|
|
117
|
+
assert(stdout.toString().trim() === 'true');
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
async function runCmd(cmd, cwd) {
|
|
121
|
+
const res = await execA(cmd, { cwd });
|
|
122
|
+
assert(res.stderr === '');
|
|
123
|
+
return res.stdout.toString().trim().split('\n');
|
|
124
|
+
}
|
|
@@ -15,6 +15,10 @@ type InjectFilterEntry = {
|
|
|
15
15
|
src: string;
|
|
16
16
|
assetType: null | PageAsset['assetType'];
|
|
17
17
|
mediaType: null | PageAsset['mediaType'];
|
|
18
|
+
/** Whether src is a root in the dependency graph.
|
|
19
|
+
* - For JavaScript this means whether src is imported by a dynamic import() statement.
|
|
20
|
+
* - All CSS files have `isEntry: true`
|
|
21
|
+
*/
|
|
18
22
|
isEntry: boolean;
|
|
19
23
|
inject: PreloadFilterInject;
|
|
20
24
|
};
|
|
@@ -7,39 +7,37 @@ import { getViteDevScripts } from './getViteDevScripts.js';
|
|
|
7
7
|
import { mergeScriptTags } from './mergeScriptTags.js';
|
|
8
8
|
import { getGlobalContext } from '../../globalContext.js';
|
|
9
9
|
import pc from '@brillout/picocolors';
|
|
10
|
+
const stamp = '__injectFilterEntry';
|
|
10
11
|
async function getHtmlTags(pageContext, injectToStream, injectFilter) {
|
|
11
12
|
assert([true, false].includes(pageContext._isHtmlOnly));
|
|
12
13
|
const isHtmlOnly = pageContext._isHtmlOnly;
|
|
13
|
-
const
|
|
14
|
-
const { isProduction } = globalContext;
|
|
15
|
-
const injectJavaScriptDuringStream = !pageContext._pageContextPromise && !!injectToStream;
|
|
14
|
+
const { isProduction } = getGlobalContext();
|
|
16
15
|
const pageAssets = await pageContext.__getPageAssets();
|
|
17
|
-
const stamp = Symbol('injectFilterEntryStamp');
|
|
18
|
-
const getInject = (asset) => {
|
|
19
|
-
if (!isProduction) {
|
|
20
|
-
return 'HTML_BEGIN';
|
|
21
|
-
}
|
|
22
|
-
if (asset.assetType === 'style' || asset.assetType === 'font') {
|
|
23
|
-
return 'HTML_BEGIN';
|
|
24
|
-
}
|
|
25
|
-
if (asset.assetType === 'script') {
|
|
26
|
-
return 'HTML_END';
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
};
|
|
30
16
|
const injectFilterEntries = pageAssets
|
|
31
17
|
.filter((asset) => {
|
|
32
18
|
if (asset.isEntry && asset.assetType === 'script') {
|
|
33
|
-
// We could
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
19
|
+
// We could allow the user to change the position of <script> but we currently don't:
|
|
20
|
+
// - Because of mergeScriptEntries()
|
|
21
|
+
// - We would need to add STREAM to to PreloadFilterInject
|
|
22
|
+
// To suppor this, we should add the JavaScript entry to injectFilterEntries (with an `src` value of `null`)
|
|
37
23
|
return false;
|
|
38
24
|
}
|
|
39
25
|
return true;
|
|
40
26
|
})
|
|
41
27
|
.map((asset) => {
|
|
42
|
-
const inject =
|
|
28
|
+
const inject = (() => {
|
|
29
|
+
if (!isProduction) {
|
|
30
|
+
// In development, we should always load assets as soon as possible, in order to eagerly process assets (e.g. applying the transform() hooks of Vite plugins) which are lazily discovered.
|
|
31
|
+
return 'HTML_BEGIN';
|
|
32
|
+
}
|
|
33
|
+
if (asset.assetType === 'style' || asset.assetType === 'font') {
|
|
34
|
+
return 'HTML_BEGIN';
|
|
35
|
+
}
|
|
36
|
+
if (asset.assetType === 'script') {
|
|
37
|
+
return 'HTML_END';
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
})();
|
|
43
41
|
const entry = {
|
|
44
42
|
...asset,
|
|
45
43
|
inject,
|
|
@@ -48,91 +46,103 @@ async function getHtmlTags(pageContext, injectToStream, injectFilter) {
|
|
|
48
46
|
};
|
|
49
47
|
return entry;
|
|
50
48
|
});
|
|
51
|
-
assertInjectFilterEntries(injectFilterEntries
|
|
49
|
+
assertInjectFilterEntries(injectFilterEntries);
|
|
50
|
+
// ==============
|
|
51
|
+
// injectFilter()
|
|
52
|
+
// ==============
|
|
52
53
|
if (injectFilter && isProduction) {
|
|
53
54
|
Object.seal(injectFilterEntries); // `Object.seal()` instead of `Object.freeze()` to allow the user to `assets.sort()`
|
|
54
55
|
Object.values(injectFilterEntries).forEach((entry) => freezePartial(entry, { inject: (val) => val === false || val === 'HTML_BEGIN' || val === 'HTML_END' }));
|
|
56
|
+
// Call the user's injectFilter() hook https://vike.dev/injectFilter
|
|
55
57
|
const res = injectFilter(injectFilterEntries);
|
|
56
|
-
assertUsage(res === undefined,
|
|
57
|
-
assertInjectFilterUsage(injectFilterEntries
|
|
58
|
-
injectFilterEntries.forEach((a) => {
|
|
59
|
-
/*
|
|
60
|
-
if (a.assetType === 'script' && a.isEntry) {
|
|
61
|
-
assertUsage(a.inject, `[injectFilter()] ${a.src} needs to be injected`)
|
|
62
|
-
}
|
|
63
|
-
*/
|
|
64
|
-
if (a.assetType === 'style' && a.isEntry) {
|
|
65
|
-
// In development, Vite automatically inject styles, but we still inject `<link rel="stylesheet" type="text/css" href="${src}">` tags in order to avoid FOUC (flash of unstyled content).
|
|
66
|
-
// - https://github.com/vitejs/vite/issues/2282
|
|
67
|
-
// - https://github.com/vikejs/vike/issues/261
|
|
68
|
-
assertWarning(a.inject, `[injectFilter()] We recommend against not injecting ${a.src}`, {
|
|
69
|
-
onlyOnce: true
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
if (!isHtmlOnly && a.assetType === 'script') {
|
|
73
|
-
assertWarning(a.inject, `[injectFilter()] We recommend against not preloading JavaScript (${a.src})`, {
|
|
74
|
-
onlyOnce: true
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
});
|
|
58
|
+
assertUsage(res === undefined, `injectFilter() should return ${pc.cyan('undefined')}, see https://vike.dev/injectFilter`);
|
|
59
|
+
assertInjectFilterUsage(injectFilterEntries);
|
|
78
60
|
}
|
|
79
61
|
const htmlTags = [];
|
|
62
|
+
// ==============
|
|
80
63
|
// Non-JavaScript
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
64
|
+
// ==============
|
|
65
|
+
injectFilterEntries
|
|
66
|
+
.filter((asset) => asset.assetType !== 'script' && asset.inject)
|
|
67
|
+
.forEach((asset) => {
|
|
68
|
+
if (!asset.inject)
|
|
69
|
+
return;
|
|
70
|
+
const htmlTag = asset.isEntry ? inferAssetTag(asset) : inferPreloadTag(asset);
|
|
71
|
+
htmlTags.push({ htmlTag, position: asset.inject });
|
|
72
|
+
});
|
|
73
|
+
// ==========
|
|
87
74
|
// JavaScript
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
75
|
+
// ==========
|
|
76
|
+
// In order to avoid the race-condition depicted in https://github.com/vikejs/vike/issues/567
|
|
77
|
+
// 1. <script id="vike_pageContext" type="application/json"> must appear before the entry <script> (which loads Vike's client runtime).
|
|
78
|
+
// 2. <script id="vike_pageContext" type="application/json"> can't be async nor defer.
|
|
79
|
+
// Additionally:
|
|
80
|
+
// 3. the entry <script> can't be defer, otherwise progressive hydration while SSR streaming won't work.
|
|
81
|
+
// 4. the entry <script> should be towards the end of the HTML as performance-wise it's more interesting to parse
|
|
82
|
+
// <div id="page-view"> before running the entry <script> which initiates the hydration.
|
|
83
|
+
// See https://github.com/vikejs/vike/pull/1271
|
|
84
|
+
const positionJavaScriptEntry = (() => {
|
|
85
|
+
if (pageContext._pageContextPromise) {
|
|
86
|
+
assertWarning(!injectToStream, "[getHtmlTags()] We recommend against using streaming and a pageContext promise at the same time as partial hydration won't work", { onlyOnce: true });
|
|
87
|
+
// If there is a pageContext._pageContextPromise (which is resolved after the stream has ended) then the pageContext JSON data needs to await for it: https://vike.dev/stream#initial-data-after-stream-end
|
|
88
|
+
return 'HTML_END';
|
|
89
|
+
}
|
|
90
|
+
if (injectToStream) {
|
|
91
|
+
// If there is a stream then, in order to support partial hydration, inject the JavaScript during the stream after React(/Vue/Solid/...) resolved the first suspense boundary
|
|
92
|
+
return 'STREAM';
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return 'HTML_END';
|
|
96
|
+
}
|
|
97
|
+
})();
|
|
98
|
+
// <script id="vike_pageContext" type="application/json">
|
|
99
|
+
if (!isHtmlOnly) {
|
|
93
100
|
htmlTags.push({
|
|
94
|
-
htmlTag:
|
|
95
|
-
|
|
101
|
+
htmlTag: () =>
|
|
102
|
+
// Needs to be called after resolvePageContextPromise()
|
|
103
|
+
getPageContextJsonScriptTag(pageContext),
|
|
104
|
+
position: positionJavaScriptEntry
|
|
96
105
|
});
|
|
97
106
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const position = asset.inject === 'HTML_END' ? positionScript : asset.inject;
|
|
102
|
-
htmlTags.push({ htmlTag, position });
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// `pageContext` JSON data
|
|
106
|
-
if (!isHtmlOnly) {
|
|
107
|
-
// Don't allow the user to manipulate with injectFilter(): injecting <script type="application/json"> before the stream can break the app when:
|
|
108
|
-
// - using https://vike.dev/stream#initial-data-after-stream-end
|
|
109
|
-
// - `pageContext` is modified during the stream, e.g. https://github.com/brillout/vike-with-pinia which uses https://vuejs.org/api/composition-api-lifecycle.html#onserverprefetch
|
|
110
|
-
// The <script> tags are handled separately by vike down below.
|
|
107
|
+
// The JavaScript entry <script> tag
|
|
108
|
+
const scriptEntry = await mergeScriptEntries(pageAssets, isProduction);
|
|
109
|
+
if (scriptEntry) {
|
|
111
110
|
htmlTags.push({
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
position: positionJsonData
|
|
111
|
+
htmlTag: scriptEntry,
|
|
112
|
+
position: positionJavaScriptEntry
|
|
115
113
|
});
|
|
116
114
|
}
|
|
115
|
+
// Preload tags
|
|
116
|
+
injectFilterEntries
|
|
117
|
+
.filter((asset) => asset.assetType === 'script')
|
|
118
|
+
.forEach((asset) => {
|
|
119
|
+
assert(!asset.isEntry); // Users cannot re-order JavaScript entries, see creation of injectFilterEntries
|
|
120
|
+
const htmlTag = inferPreloadTag(asset);
|
|
121
|
+
if (!asset.inject)
|
|
122
|
+
return;
|
|
123
|
+
// Ideally, instead of this conditional ternary operator, we should add STREAM to PreloadFilterInject (or a better fitting name such as HTML_STREAM)
|
|
124
|
+
const position = asset.inject === 'HTML_END' ? positionJavaScriptEntry : asset.inject;
|
|
125
|
+
htmlTags.push({ htmlTag, position });
|
|
126
|
+
});
|
|
117
127
|
return htmlTags;
|
|
118
128
|
}
|
|
119
|
-
async function
|
|
120
|
-
const
|
|
129
|
+
async function mergeScriptEntries(pageAssets, isProduction) {
|
|
130
|
+
const scriptEntries = pageAssets.filter((pageAsset) => pageAsset.isEntry && pageAsset.assetType === 'script');
|
|
121
131
|
const viteScripts = await getViteDevScripts();
|
|
122
|
-
const scriptTagsHtml = `${viteScripts}${
|
|
132
|
+
const scriptTagsHtml = `${viteScripts}${scriptEntries.map((asset) => inferAssetTag(asset)).join('')}`;
|
|
123
133
|
const scriptTag = mergeScriptTags(scriptTagsHtml, isProduction);
|
|
124
134
|
return scriptTag;
|
|
125
135
|
}
|
|
126
|
-
function
|
|
136
|
+
function getPageContextJsonScriptTag(pageContext) {
|
|
127
137
|
const pageContextSerialized = sanitizeJson(serializePageContextClientSide(pageContext));
|
|
128
138
|
const htmlTag = `<script id="vike_pageContext" type="application/json">${pageContextSerialized}</script>`;
|
|
129
139
|
// @ts-expect-error
|
|
130
140
|
pageContext._pageContextHtmlTag = htmlTag;
|
|
131
141
|
return htmlTag;
|
|
132
142
|
}
|
|
133
|
-
function assertInjectFilterEntries(injectFilterEntries
|
|
143
|
+
function assertInjectFilterEntries(injectFilterEntries) {
|
|
134
144
|
try {
|
|
135
|
-
|
|
145
|
+
checkForWrongUsage(injectFilterEntries);
|
|
136
146
|
}
|
|
137
147
|
catch (err) {
|
|
138
148
|
if (err?.message.includes('[Wrong Usage]')) {
|
|
@@ -141,7 +151,11 @@ function assertInjectFilterEntries(injectFilterEntries, stamp) {
|
|
|
141
151
|
throw err;
|
|
142
152
|
}
|
|
143
153
|
}
|
|
144
|
-
function assertInjectFilterUsage(injectFilterEntries
|
|
154
|
+
function assertInjectFilterUsage(injectFilterEntries) {
|
|
155
|
+
checkForWrongUsage(injectFilterEntries);
|
|
156
|
+
checkForWarnings(injectFilterEntries);
|
|
157
|
+
}
|
|
158
|
+
function checkForWrongUsage(injectFilterEntries) {
|
|
145
159
|
injectFilterEntries.forEach((entry, i) => {
|
|
146
160
|
assertUsage(isObject(entry), `[injectFilter()] Entry ${i} isn't an object`);
|
|
147
161
|
assertUsage(typeof entry.src === 'string', `[injectFilter()] Entry ${i} is missing property ${pc.cyan('src')}`);
|
|
@@ -150,6 +164,28 @@ function assertInjectFilterUsage(injectFilterEntries, stamp) {
|
|
|
150
164
|
assert(entry.assetType === null || typeof entry.assetType === 'string');
|
|
151
165
|
assert(entry.mediaType === null || typeof entry.mediaType === 'string');
|
|
152
166
|
assert(typeof entry.isEntry === 'boolean');
|
|
153
|
-
assert(Object.keys(entry).length ===
|
|
167
|
+
assert(Object.keys(entry).length === 6);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function checkForWarnings(injectFilterEntries) {
|
|
171
|
+
injectFilterEntries.forEach((a) => {
|
|
172
|
+
/*
|
|
173
|
+
if (a.assetType === 'script' && a.isEntry) {
|
|
174
|
+
assertUsage(a.inject, `[injectFilter()] ${a.src} needs to be injected`)
|
|
175
|
+
}
|
|
176
|
+
*/
|
|
177
|
+
if (a.assetType === 'style' && a.isEntry) {
|
|
178
|
+
// In development, Vite automatically inject styles, but we still inject `<link rel="stylesheet" type="text/css" href="${src}">` tags in order to avoid FOUC (flash of unstyled content).
|
|
179
|
+
// - https://github.com/vitejs/vite/issues/2282
|
|
180
|
+
// - https://github.com/vikejs/vike/issues/261
|
|
181
|
+
assertWarning(a.inject, `[injectFilter()] We recommend against not injecting ${a.src}`, {
|
|
182
|
+
onlyOnce: true
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (a.assetType === 'script') {
|
|
186
|
+
assertWarning(a.inject, `[injectFilter()] We recommend against not preloading JavaScript (${a.src})`, {
|
|
187
|
+
onlyOnce: true
|
|
188
|
+
});
|
|
189
|
+
}
|
|
154
190
|
});
|
|
155
191
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { inferAssetTag };
|
|
2
2
|
export { inferPreloadTag };
|
|
3
3
|
export { inferEarlyHintLink };
|
|
4
|
+
export { scriptAttrs };
|
|
4
5
|
import type { PageAsset } from '../../renderPage/getPageAssets.js';
|
|
6
|
+
declare const scriptAttrs = "type=\"module\" async";
|
|
5
7
|
declare function inferPreloadTag(pageAsset: PageAsset): string;
|
|
6
8
|
declare function inferAssetTag(pageAsset: PageAsset): string;
|
|
7
9
|
declare function inferEarlyHintLink(pageAsset: PageAsset): string;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export { inferAssetTag };
|
|
2
2
|
export { inferPreloadTag };
|
|
3
3
|
export { inferEarlyHintLink };
|
|
4
|
+
export { scriptAttrs };
|
|
4
5
|
import { assert } from '../../utils.js';
|
|
6
|
+
// We can't use `defer` here. With `defer`, the entry script won't start before `</body>` has been parsed, preventing partial hydration during SSR streaming, see https://github.com/vikejs/vike/pull/1271
|
|
7
|
+
const scriptAttrs = 'type="module" async';
|
|
5
8
|
function inferPreloadTag(pageAsset) {
|
|
6
9
|
const { src, assetType, mediaType } = pageAsset;
|
|
7
10
|
const rel = getRel(pageAsset);
|
|
@@ -21,10 +24,7 @@ function inferAssetTag(pageAsset) {
|
|
|
21
24
|
const { src, assetType, mediaType } = pageAsset;
|
|
22
25
|
if (assetType === 'script') {
|
|
23
26
|
assert(mediaType === 'text/javascript');
|
|
24
|
-
|
|
25
|
-
// - in dev: https://github.com/vikejs/vike/issues/524
|
|
26
|
-
// - in prod: https://github.com/vikejs/vike/issues/567
|
|
27
|
-
return `<script type="module" src="${src}" defer></script>`;
|
|
27
|
+
return `<script src="${src}" ${scriptAttrs}></script>`;
|
|
28
28
|
}
|
|
29
29
|
if (assetType === 'style') {
|
|
30
30
|
return `<link rel="stylesheet" type="text/css" href="${src}">`;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { mergeScriptTags };
|
|
2
2
|
import { assert } from '../../utils.js';
|
|
3
|
+
import { scriptAttrs } from './inferHtmlTags.js';
|
|
3
4
|
const scriptRE = /(<script\b(?:\s[^>]*>|>))(.*?)<\/script>/gims;
|
|
4
5
|
const srcRE = /\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s'">]+))/im;
|
|
5
6
|
const typeRE = /\btype\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s'">]+))/im;
|
|
@@ -32,7 +33,7 @@ function mergeScriptTags(scriptTagsHtml, isProduction) {
|
|
|
32
33
|
}
|
|
33
34
|
});
|
|
34
35
|
if (contents.length > 0) {
|
|
35
|
-
scriptTag += `<script
|
|
36
|
+
scriptTag += `<script ${scriptAttrs}>\n${contents.join('\n')}\n</script>`;
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -12,8 +12,7 @@ function retrieveAssetsProd(clientDependencies, clientManifest, includeAssetsImp
|
|
|
12
12
|
if (onlyAssets) {
|
|
13
13
|
if (!includeAssetsImportedByServer)
|
|
14
14
|
return;
|
|
15
|
-
// We assume that all npm packages have already built their
|
|
16
|
-
// - Bundlers (Rollup, esbuild, tsup, ...) extract the CSS out of JavaScript => we can assume JavaScript to not import any CSS/assets
|
|
15
|
+
// We assume that all npm packages have already built their files: bundlers (Rollup, esbuild, tsup, ...) extract the CSS out of JavaScript => we can assume JavaScript to not import any CSS/assets.
|
|
17
16
|
if (isNpmPackageImport(id))
|
|
18
17
|
return;
|
|
19
18
|
if (id.includes('.page.server.')) {
|
|
@@ -49,7 +48,7 @@ function collectAssets(manifestKey, assetUrls, visistedAssets, manifest, onlyCol
|
|
|
49
48
|
assetUrls.add(`/${asset}`);
|
|
50
49
|
}
|
|
51
50
|
}
|
|
52
|
-
// Support `config.build.cssCodeSplit: false`, https://github.com/vikejs/vike/issues/644
|
|
51
|
+
// Support `config.build.cssCodeSplit: false`, see https://github.com/vikejs/vike/issues/644
|
|
53
52
|
function collectSingleStyle(assetUrls, manifest) {
|
|
54
53
|
const style = manifest['style.css'];
|
|
55
54
|
if (style && Object.values(manifest).filter((asset) => asset.file.endsWith('.css')).length === 1) {
|
|
@@ -20,6 +20,12 @@ function sortPageAssetsForEarlyHintsHeader(pageAssets) {
|
|
|
20
20
|
if (assetType === 'image')
|
|
21
21
|
return priority;
|
|
22
22
|
priority--;
|
|
23
|
+
if (assetType === 'video')
|
|
24
|
+
return priority;
|
|
25
|
+
priority--;
|
|
26
|
+
if (assetType === 'audio')
|
|
27
|
+
return priority;
|
|
28
|
+
priority--;
|
|
23
29
|
// Others
|
|
24
30
|
if (assetType !== 'script')
|
|
25
31
|
return priority;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { inferMediaType };
|
|
2
2
|
export type { MediaType };
|
|
3
3
|
type MediaType = null | {
|
|
4
|
-
assetType: 'image' | 'script' | 'font' | 'style';
|
|
5
|
-
mediaType: 'text/javascript' | 'text/css' | 'image/jpeg' | 'image/png' | 'image/webp' | 'image/gif' | 'image/svg+xml' | 'font/ttf' | 'font/woff' | 'font/woff2';
|
|
4
|
+
assetType: 'image' | 'script' | 'font' | 'style' | 'audio' | 'video' | 'document' | 'fetch' | 'track' | 'worker' | 'embed' | 'object';
|
|
5
|
+
mediaType: 'text/javascript' | 'text/css' | 'image/jpeg' | 'image/png' | 'image/webp' | 'image/gif' | 'image/svg+xml' | 'font/ttf' | 'font/woff' | 'font/woff2' | 'video/mp4' | 'video/webm' | 'video/ogg' | 'video/mpeg' | 'video/x-msvideo' | 'video/quicktime' | 'audio/mpeg' | 'audio/wav' | 'audio/ogg' | 'audio/aac' | 'audio/midi' | 'audio/flac';
|
|
6
6
|
};
|
|
7
7
|
declare function inferMediaType(href: string): MediaType;
|
|
@@ -34,5 +34,43 @@ function inferMediaType(href) {
|
|
|
34
34
|
if (href.endsWith('.woff2')) {
|
|
35
35
|
return { assetType: 'font', mediaType: 'font/woff2' };
|
|
36
36
|
}
|
|
37
|
+
// Videos
|
|
38
|
+
if (href.endsWith('.mp4')) {
|
|
39
|
+
return { assetType: 'video', mediaType: 'video/mp4' };
|
|
40
|
+
}
|
|
41
|
+
if (href.endsWith('.webm')) {
|
|
42
|
+
return { assetType: 'video', mediaType: 'video/webm' };
|
|
43
|
+
}
|
|
44
|
+
if (href.endsWith('.ogv')) {
|
|
45
|
+
return { assetType: 'video', mediaType: 'video/ogg' };
|
|
46
|
+
}
|
|
47
|
+
if (href.endsWith('.mpeg') || href.endsWith('.mpg')) {
|
|
48
|
+
return { assetType: 'video', mediaType: 'video/mpeg' };
|
|
49
|
+
}
|
|
50
|
+
if (href.endsWith('.avi')) {
|
|
51
|
+
return { assetType: 'video', mediaType: 'video/x-msvideo' };
|
|
52
|
+
}
|
|
53
|
+
if (href.endsWith('.mov') || href.endsWith('.qt')) {
|
|
54
|
+
return { assetType: 'video', mediaType: 'video/quicktime' };
|
|
55
|
+
}
|
|
56
|
+
// Audios
|
|
57
|
+
if (href.endsWith('.mp3')) {
|
|
58
|
+
return { assetType: 'audio', mediaType: 'audio/mpeg' };
|
|
59
|
+
}
|
|
60
|
+
if (href.endsWith('.wav')) {
|
|
61
|
+
return { assetType: 'audio', mediaType: 'audio/wav' };
|
|
62
|
+
}
|
|
63
|
+
if (href.endsWith('.ogg')) {
|
|
64
|
+
return { assetType: 'audio', mediaType: 'audio/ogg' };
|
|
65
|
+
}
|
|
66
|
+
if (href.endsWith('.m4a')) {
|
|
67
|
+
return { assetType: 'audio', mediaType: 'audio/aac' };
|
|
68
|
+
}
|
|
69
|
+
if (href.endsWith('midi') || href.endsWith('.mid')) {
|
|
70
|
+
return { assetType: 'audio', mediaType: 'audio/midi' };
|
|
71
|
+
}
|
|
72
|
+
if (href.endsWith('.flac')) {
|
|
73
|
+
return { assetType: 'audio', mediaType: 'audio/flac' };
|
|
74
|
+
}
|
|
37
75
|
return null;
|
|
38
76
|
}
|
|
@@ -28,13 +28,20 @@ function assertExports(fileExports, filePathToShowToUser, configName) {
|
|
|
28
28
|
if (exportsRelevant.length === 1) {
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const exportDefault = pc.cyan('export default');
|
|
32
|
+
const exportConfigName = pc.cyan(`export { ${configName} }`);
|
|
33
|
+
if (exportsRelevant.length === 0) {
|
|
34
|
+
let errMsg = `${filePathToShowToUser} doesn't export any value, but it should have a ${exportDefault}`;
|
|
34
35
|
if (configName)
|
|
35
|
-
errMsg += ` or ${
|
|
36
|
+
errMsg += ` or ${exportConfigName}`;
|
|
36
37
|
assertUsage(false, errMsg);
|
|
37
38
|
}
|
|
39
|
+
else {
|
|
40
|
+
assert(exportsRelevant.length === 2);
|
|
41
|
+
assertWarning(false, `${filePathToShowToUser} remove ${exportConfigName} or ${exportDefault}`, {
|
|
42
|
+
onlyOnce: true
|
|
43
|
+
});
|
|
44
|
+
}
|
|
38
45
|
}
|
|
39
46
|
else {
|
|
40
47
|
// !configName => isConfigFile
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { projectInfo };
|
|
2
2
|
export type { ProjectTag };
|
|
3
3
|
export { PROJECT_VERSION };
|
|
4
|
-
declare const PROJECT_VERSION: "0.4.
|
|
4
|
+
declare const PROJECT_VERSION: "0.4.149-commit-041ee42";
|
|
5
5
|
type PackageName = typeof projectInfo.npmPackageName;
|
|
6
6
|
type ProjectVersion = typeof projectInfo.projectVersion;
|
|
7
7
|
type ProjectTag = `[${PackageName}]` | `[${PackageName}@${ProjectVersion}]`;
|
|
8
8
|
declare const projectInfo: {
|
|
9
9
|
projectName: "Vike";
|
|
10
|
-
projectVersion: "0.4.
|
|
10
|
+
projectVersion: "0.4.149-commit-041ee42";
|
|
11
11
|
npmPackageName: "vike";
|
|
12
12
|
githubRepository: "https://github.com/vikejs/vike";
|
|
13
13
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { projectInfo };
|
|
2
2
|
export { PROJECT_VERSION };
|
|
3
3
|
import { onProjectInfo } from './assertSingleInstance.js';
|
|
4
|
-
const PROJECT_VERSION = '0.4.
|
|
4
|
+
const PROJECT_VERSION = '0.4.149-commit-041ee42';
|
|
5
5
|
const projectInfo = {
|
|
6
6
|
projectName: 'Vike',
|
|
7
7
|
projectVersion: PROJECT_VERSION,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vike",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.149-commit-041ee42",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "tsc --watch",
|
|
6
6
|
"build": "rimraf dist/ && pnpm run build:esm && pnpm run build:cjs",
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
"vike": "./node/cli/bin-entry.js"
|
|
163
163
|
},
|
|
164
164
|
"devDependencies": {
|
|
165
|
-
"@brillout/release-me": "^0.1.
|
|
165
|
+
"@brillout/release-me": "^0.1.11",
|
|
166
166
|
"@types/estree": "^1.0.0",
|
|
167
167
|
"@types/jest": "^27.4.1",
|
|
168
168
|
"@types/node": "^20.1.0",
|