vinext 0.0.32 → 0.0.34
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/README.md +7 -6
- package/dist/config/next-config.d.ts +2 -0
- package/dist/config/next-config.js +4 -0
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.js +52 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.js +3 -330
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +444 -1265
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-ssr-entry.js +4 -460
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +8 -1
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +13 -0
- package/dist/entries/runtime-entry-module.js +27 -0
- package/dist/entries/runtime-entry-module.js.map +1 -0
- package/dist/index.js +302 -23
- package/dist/index.js.map +1 -1
- package/dist/plugins/optimize-imports.d.ts +38 -0
- package/dist/plugins/optimize-imports.js +557 -0
- package/dist/plugins/optimize-imports.js.map +1 -0
- package/dist/server/app-browser-entry.d.ts +1 -0
- package/dist/server/app-browser-entry.js +160 -0
- package/dist/server/app-browser-entry.js.map +1 -0
- package/dist/server/app-browser-stream.d.ts +33 -0
- package/dist/server/app-browser-stream.js +54 -0
- package/dist/server/app-browser-stream.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +63 -0
- package/dist/server/app-page-boundary-render.js +182 -0
- package/dist/server/app-page-boundary-render.js.map +1 -0
- package/dist/server/app-page-boundary.d.ts +57 -0
- package/dist/server/app-page-boundary.js +60 -0
- package/dist/server/app-page-boundary.js.map +1 -0
- package/dist/server/app-page-cache.d.ts +61 -0
- package/dist/server/app-page-cache.js +133 -0
- package/dist/server/app-page-cache.js.map +1 -0
- package/dist/server/app-page-execution.d.ts +46 -0
- package/dist/server/app-page-execution.js +109 -0
- package/dist/server/app-page-execution.js.map +1 -0
- package/dist/server/app-page-probe.d.ts +17 -0
- package/dist/server/app-page-probe.js +35 -0
- package/dist/server/app-page-probe.js.map +1 -0
- package/dist/server/app-page-render.d.ts +59 -0
- package/dist/server/app-page-render.js +174 -0
- package/dist/server/app-page-render.js.map +1 -0
- package/dist/server/app-page-request.d.ts +58 -0
- package/dist/server/app-page-request.js +79 -0
- package/dist/server/app-page-request.js.map +1 -0
- package/dist/server/app-page-response.d.ts +51 -0
- package/dist/server/app-page-response.js +90 -0
- package/dist/server/app-page-response.js.map +1 -0
- package/dist/server/app-page-stream.d.ts +55 -0
- package/dist/server/app-page-stream.js +65 -0
- package/dist/server/app-page-stream.js.map +1 -0
- package/dist/server/app-route-handler-cache.d.ts +42 -0
- package/dist/server/app-route-handler-cache.js +69 -0
- package/dist/server/app-route-handler-cache.js.map +1 -0
- package/dist/server/app-route-handler-execution.d.ts +64 -0
- package/dist/server/app-route-handler-execution.js +100 -0
- package/dist/server/app-route-handler-execution.js.map +1 -0
- package/dist/server/app-route-handler-policy.d.ts +51 -0
- package/dist/server/app-route-handler-policy.js +57 -0
- package/dist/server/app-route-handler-policy.js.map +1 -0
- package/dist/server/app-route-handler-response.d.ts +26 -0
- package/dist/server/app-route-handler-response.js +61 -0
- package/dist/server/app-route-handler-response.js.map +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +27 -0
- package/dist/server/app-route-handler-runtime.js +99 -0
- package/dist/server/app-route-handler-runtime.js.map +1 -0
- package/dist/server/app-ssr-entry.d.ts +19 -0
- package/dist/server/app-ssr-entry.js +105 -0
- package/dist/server/app-ssr-entry.js.map +1 -0
- package/dist/server/app-ssr-stream.d.ts +30 -0
- package/dist/server/app-ssr-stream.js +116 -0
- package/dist/server/app-ssr-stream.js.map +1 -0
- package/dist/server/prod-server.d.ts +13 -1
- package/dist/server/prod-server.js +113 -19
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/worker-utils.d.ts +0 -6
- package/dist/server/worker-utils.js +41 -5
- package/dist/server/worker-utils.js.map +1 -1
- package/dist/shims/error-boundary.js +1 -1
- package/dist/shims/font-google-base.js +1 -1
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-google.d.ts +2 -3
- package/dist/shims/font-google.js +2 -3
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/package.json +1 -1
- package/dist/shims/font-google.generated.d.ts +0 -1929
- package/dist/shims/font-google.generated.js +0 -1929
- package/dist/shims/font-google.generated.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ import { scanMetadataFiles } from "./server/metadata-routes.js";
|
|
|
25
25
|
import { manifestFileWithBase, manifestFilesWithBase, normalizeManifestFile } from "./utils/manifest-paths.js";
|
|
26
26
|
import { asyncHooksStubPlugin } from "./plugins/async-hooks-stub.js";
|
|
27
27
|
import { clientReferenceDedupPlugin } from "./plugins/client-reference-dedup.js";
|
|
28
|
+
import { createOptimizeImportsPlugin } from "./plugins/optimize-imports.js";
|
|
28
29
|
import { formatMissingCloudflarePluginError, hasWranglerConfig } from "./deploy.js";
|
|
29
30
|
import { staticExportApp, staticExportPages } from "./build/static-export.js";
|
|
30
31
|
import { createRequire } from "node:module";
|
|
@@ -33,8 +34,8 @@ import path from "node:path";
|
|
|
33
34
|
import { loadEnv, parseAst } from "vite";
|
|
34
35
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
35
36
|
import { randomBytes } from "node:crypto";
|
|
36
|
-
import tsconfigPaths from "vite-tsconfig-paths";
|
|
37
37
|
import MagicString from "magic-string";
|
|
38
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
38
39
|
import commonjs from "vite-plugin-commonjs";
|
|
39
40
|
//#region src/index.ts
|
|
40
41
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -162,6 +163,92 @@ function extractStaticValue(node) {
|
|
|
162
163
|
default: return;
|
|
163
164
|
}
|
|
164
165
|
}
|
|
166
|
+
function isRecord(value) {
|
|
167
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
168
|
+
}
|
|
169
|
+
const TSCONFIG_FILES = ["tsconfig.json", "jsconfig.json"];
|
|
170
|
+
function resolveTsconfigPathCandidate(candidate) {
|
|
171
|
+
const candidates = candidate.endsWith(".json") ? [candidate] : [
|
|
172
|
+
candidate,
|
|
173
|
+
`${candidate}.json`,
|
|
174
|
+
path.join(candidate, "tsconfig.json")
|
|
175
|
+
];
|
|
176
|
+
for (const item of candidates) if (fs.existsSync(item) && fs.statSync(item).isFile()) return item;
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
function resolveTsconfigExtends(configPath, specifier) {
|
|
180
|
+
const fromDir = path.dirname(configPath);
|
|
181
|
+
if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("\\")) return resolveTsconfigPathCandidate(path.resolve(fromDir, specifier));
|
|
182
|
+
const requireFromConfig = createRequire(configPath);
|
|
183
|
+
const candidates = [
|
|
184
|
+
specifier,
|
|
185
|
+
`${specifier}.json`,
|
|
186
|
+
path.join(specifier, "tsconfig.json")
|
|
187
|
+
];
|
|
188
|
+
for (const item of candidates) try {
|
|
189
|
+
return requireFromConfig.resolve(item);
|
|
190
|
+
} catch {}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
function materializeTsconfigPathAliases(pathsConfig, baseUrl, projectRoot) {
|
|
194
|
+
const aliases = {};
|
|
195
|
+
for (const [find, rawTargets] of Object.entries(pathsConfig)) {
|
|
196
|
+
const target = Array.isArray(rawTargets) ? rawTargets.find((value) => typeof value === "string") : typeof rawTargets === "string" ? rawTargets : null;
|
|
197
|
+
if (!target) continue;
|
|
198
|
+
if (find.includes("*") || target.includes("*")) {
|
|
199
|
+
if (!find.endsWith("/*") || !target.endsWith("/*")) continue;
|
|
200
|
+
if (find.indexOf("*") !== find.length - 1 || target.indexOf("*") !== target.length - 1) continue;
|
|
201
|
+
const aliasKey = find.slice(0, -2);
|
|
202
|
+
const targetDir = target.slice(0, -2);
|
|
203
|
+
if (!aliasKey || !targetDir) continue;
|
|
204
|
+
aliases[aliasKey] = toViteAliasReplacement(path.resolve(baseUrl, targetDir), projectRoot);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
aliases[find] = toViteAliasReplacement(path.resolve(baseUrl, target), projectRoot);
|
|
208
|
+
}
|
|
209
|
+
return aliases;
|
|
210
|
+
}
|
|
211
|
+
function toViteAliasReplacement(absolutePath, projectRoot) {
|
|
212
|
+
const normalizedPath = absolutePath.replace(/\\/g, "/");
|
|
213
|
+
const rootCandidates = new Set([projectRoot]);
|
|
214
|
+
const realRoot = tryRealpathSync(projectRoot);
|
|
215
|
+
if (realRoot) rootCandidates.add(realRoot);
|
|
216
|
+
const pathCandidates = new Set([absolutePath]);
|
|
217
|
+
const realPath = tryRealpathSync(absolutePath);
|
|
218
|
+
if (realPath) pathCandidates.add(realPath);
|
|
219
|
+
for (const rootCandidate of rootCandidates) for (const pathCandidate of pathCandidates) {
|
|
220
|
+
if (pathCandidate === rootCandidate) return "/";
|
|
221
|
+
const relativeId = relativeWithinRoot(rootCandidate, pathCandidate);
|
|
222
|
+
if (relativeId) return "/" + relativeId;
|
|
223
|
+
}
|
|
224
|
+
return normalizedPath;
|
|
225
|
+
}
|
|
226
|
+
function loadTsconfigPathAliases(configPath, projectRoot, seen = /* @__PURE__ */ new Set()) {
|
|
227
|
+
const normalizedPath = tryRealpathSync(configPath) ?? configPath;
|
|
228
|
+
if (seen.has(normalizedPath)) return {};
|
|
229
|
+
seen.add(normalizedPath);
|
|
230
|
+
let parsed = null;
|
|
231
|
+
try {
|
|
232
|
+
parsed = parseStaticObjectLiteral(fs.readFileSync(normalizedPath, "utf-8"));
|
|
233
|
+
} catch {
|
|
234
|
+
return {};
|
|
235
|
+
}
|
|
236
|
+
if (!parsed) return {};
|
|
237
|
+
let aliases = {};
|
|
238
|
+
if (typeof parsed.extends === "string") {
|
|
239
|
+
const extendedPath = resolveTsconfigExtends(normalizedPath, parsed.extends);
|
|
240
|
+
if (extendedPath) aliases = loadTsconfigPathAliases(extendedPath, projectRoot, seen);
|
|
241
|
+
}
|
|
242
|
+
const compilerOptions = isRecord(parsed.compilerOptions) ? parsed.compilerOptions : null;
|
|
243
|
+
const pathsConfig = compilerOptions && isRecord(compilerOptions.paths) ? compilerOptions.paths : null;
|
|
244
|
+
if (!pathsConfig) return aliases;
|
|
245
|
+
const baseUrl = compilerOptions && typeof compilerOptions.baseUrl === "string" ? compilerOptions.baseUrl : ".";
|
|
246
|
+
const resolvedBaseUrl = path.resolve(path.dirname(normalizedPath), baseUrl);
|
|
247
|
+
return {
|
|
248
|
+
...aliases,
|
|
249
|
+
...materializeTsconfigPathAliases(pathsConfig, resolvedBaseUrl, projectRoot)
|
|
250
|
+
};
|
|
251
|
+
}
|
|
165
252
|
/**
|
|
166
253
|
* Detect Vite major version at runtime by resolving from cwd.
|
|
167
254
|
* The plugin may be installed in a workspace root with Vite 7 but used
|
|
@@ -211,6 +298,19 @@ const POSTCSS_CONFIG_FILES = [
|
|
|
211
298
|
* parallel) all await the same in-flight scan rather than each starting their own.
|
|
212
299
|
*/
|
|
213
300
|
const _postcssCache = /* @__PURE__ */ new Map();
|
|
301
|
+
const _tsconfigAliasCache = /* @__PURE__ */ new Map();
|
|
302
|
+
function resolveTsconfigAliases(projectRoot) {
|
|
303
|
+
if (_tsconfigAliasCache.has(projectRoot)) return _tsconfigAliasCache.get(projectRoot);
|
|
304
|
+
let aliases = {};
|
|
305
|
+
for (const name of TSCONFIG_FILES) {
|
|
306
|
+
const candidate = path.join(projectRoot, name);
|
|
307
|
+
if (!fs.existsSync(candidate)) continue;
|
|
308
|
+
aliases = loadTsconfigPathAliases(candidate, projectRoot);
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
_tsconfigAliasCache.set(projectRoot, aliases);
|
|
312
|
+
return aliases;
|
|
313
|
+
}
|
|
214
314
|
/**
|
|
215
315
|
* Resolve PostCSS string plugin names in a project's PostCSS config.
|
|
216
316
|
*
|
|
@@ -278,9 +378,18 @@ const VIRTUAL_APP_SSR_ENTRY = "virtual:vinext-app-ssr-entry";
|
|
|
278
378
|
const RESOLVED_APP_SSR_ENTRY = "\0" + VIRTUAL_APP_SSR_ENTRY;
|
|
279
379
|
const VIRTUAL_APP_BROWSER_ENTRY = "virtual:vinext-app-browser-entry";
|
|
280
380
|
const RESOLVED_APP_BROWSER_ENTRY = "\0" + VIRTUAL_APP_BROWSER_ENTRY;
|
|
381
|
+
const VIRTUAL_GOOGLE_FONTS = "virtual:vinext-google-fonts";
|
|
382
|
+
const RESOLVED_VIRTUAL_GOOGLE_FONTS = "\0" + VIRTUAL_GOOGLE_FONTS;
|
|
281
383
|
/** Image file extensions handled by the vinext:image-imports plugin.
|
|
282
384
|
* Shared between the Rolldown hook filter and the transform handler regex. */
|
|
283
385
|
const IMAGE_EXTS = "png|jpe?g|gif|webp|avif|svg|ico|bmp|tiff?";
|
|
386
|
+
const GOOGLE_FONT_UTILITY_EXPORTS = new Set([
|
|
387
|
+
"buildGoogleFontsUrl",
|
|
388
|
+
"getSSRFontLinks",
|
|
389
|
+
"getSSRFontStyles",
|
|
390
|
+
"getSSRFontPreloads",
|
|
391
|
+
"createFontLoader"
|
|
392
|
+
]);
|
|
284
393
|
/**
|
|
285
394
|
* Extract the npm package name from a module ID (file path).
|
|
286
395
|
* Returns null if not in node_modules.
|
|
@@ -300,6 +409,102 @@ function getPackageName(id) {
|
|
|
300
409
|
}
|
|
301
410
|
/** Absolute path to vinext's shims directory, used by clientManualChunks. */
|
|
302
411
|
const _shimsDir = path.resolve(__dirname, "shims") + "/";
|
|
412
|
+
const _fontGoogleShimPath = resolveShimModulePath(_shimsDir, "font-google");
|
|
413
|
+
function parseGoogleFontNamedSpecifiers(specifiersStr, forceType = false) {
|
|
414
|
+
return specifiersStr.split(",").map((spec) => spec.trim()).filter(Boolean).map((raw) => {
|
|
415
|
+
const isType = forceType || raw.startsWith("type ");
|
|
416
|
+
const asParts = (isType ? raw.replace(/^type\s+/, "") : raw).split(/\s+as\s+/);
|
|
417
|
+
return {
|
|
418
|
+
imported: asParts[0]?.trim() ?? "",
|
|
419
|
+
local: (asParts[1] || asParts[0] || "").trim(),
|
|
420
|
+
isType,
|
|
421
|
+
raw
|
|
422
|
+
};
|
|
423
|
+
}).filter((spec) => spec.imported.length > 0 && spec.local.length > 0);
|
|
424
|
+
}
|
|
425
|
+
function parseGoogleFontImportClause(clause) {
|
|
426
|
+
const trimmed = clause.trim();
|
|
427
|
+
if (trimmed.startsWith("type ")) {
|
|
428
|
+
const braceStart = trimmed.indexOf("{");
|
|
429
|
+
const braceEnd = trimmed.lastIndexOf("}");
|
|
430
|
+
if (braceStart === -1 || braceEnd === -1) return {
|
|
431
|
+
defaultLocal: null,
|
|
432
|
+
namespaceLocal: null,
|
|
433
|
+
named: []
|
|
434
|
+
};
|
|
435
|
+
return {
|
|
436
|
+
defaultLocal: null,
|
|
437
|
+
namespaceLocal: null,
|
|
438
|
+
named: parseGoogleFontNamedSpecifiers(trimmed.slice(braceStart + 1, braceEnd), true)
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
const braceStart = trimmed.indexOf("{");
|
|
442
|
+
const braceEnd = trimmed.lastIndexOf("}");
|
|
443
|
+
if (braceStart !== -1 && braceEnd !== -1) return {
|
|
444
|
+
defaultLocal: trimmed.slice(0, braceStart).trim().replace(/,\s*$/, "").trim() || null,
|
|
445
|
+
namespaceLocal: null,
|
|
446
|
+
named: parseGoogleFontNamedSpecifiers(trimmed.slice(braceStart + 1, braceEnd))
|
|
447
|
+
};
|
|
448
|
+
const commaIndex = trimmed.indexOf(",");
|
|
449
|
+
if (commaIndex !== -1) {
|
|
450
|
+
const defaultLocal = trimmed.slice(0, commaIndex).trim() || null;
|
|
451
|
+
const rest = trimmed.slice(commaIndex + 1).trim();
|
|
452
|
+
if (rest.startsWith("* as ")) return {
|
|
453
|
+
defaultLocal,
|
|
454
|
+
namespaceLocal: rest.slice(5).trim() || null,
|
|
455
|
+
named: []
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
if (trimmed.startsWith("* as ")) return {
|
|
459
|
+
defaultLocal: null,
|
|
460
|
+
namespaceLocal: trimmed.slice(5).trim() || null,
|
|
461
|
+
named: []
|
|
462
|
+
};
|
|
463
|
+
return {
|
|
464
|
+
defaultLocal: trimmed || null,
|
|
465
|
+
namespaceLocal: null,
|
|
466
|
+
named: []
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
function encodeGoogleFontsVirtualId(payload) {
|
|
470
|
+
const params = new URLSearchParams();
|
|
471
|
+
if (payload.hasDefault) params.set("default", "1");
|
|
472
|
+
if (payload.fonts.length > 0) params.set("fonts", payload.fonts.join(","));
|
|
473
|
+
if (payload.utilities.length > 0) params.set("utilities", payload.utilities.join(","));
|
|
474
|
+
return `${VIRTUAL_GOOGLE_FONTS}?${params.toString()}`;
|
|
475
|
+
}
|
|
476
|
+
function parseGoogleFontsVirtualId(id) {
|
|
477
|
+
const cleanId = id.startsWith("\0") ? id.slice(1) : id;
|
|
478
|
+
if (!cleanId.startsWith(VIRTUAL_GOOGLE_FONTS)) return null;
|
|
479
|
+
const queryIndex = cleanId.indexOf("?");
|
|
480
|
+
const params = new URLSearchParams(queryIndex === -1 ? "" : cleanId.slice(queryIndex + 1));
|
|
481
|
+
return {
|
|
482
|
+
hasDefault: params.get("default") === "1",
|
|
483
|
+
fonts: params.get("fonts")?.split(",").map((value) => value.trim()).filter(Boolean) ?? [],
|
|
484
|
+
utilities: params.get("utilities")?.split(",").map((value) => value.trim()).filter(Boolean) ?? []
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
function generateGoogleFontsVirtualModule(id) {
|
|
488
|
+
const payload = parseGoogleFontsVirtualId(id);
|
|
489
|
+
if (!payload) return null;
|
|
490
|
+
const utilities = Array.from(new Set(payload.utilities));
|
|
491
|
+
const fonts = Array.from(new Set(payload.fonts));
|
|
492
|
+
const lines = [];
|
|
493
|
+
lines.push(`import { createFontLoader } from ${JSON.stringify(_fontGoogleShimPath)};`);
|
|
494
|
+
const reExports = [];
|
|
495
|
+
if (payload.hasDefault) reExports.push("default");
|
|
496
|
+
reExports.push(...utilities);
|
|
497
|
+
if (reExports.length > 0) lines.push(`export { ${reExports.join(", ")} } from ${JSON.stringify(_fontGoogleShimPath)};`);
|
|
498
|
+
for (const fontName of fonts) {
|
|
499
|
+
const family = fontName.replace(/_/g, " ");
|
|
500
|
+
lines.push(`export const ${fontName} = /*#__PURE__*/ createFontLoader(${JSON.stringify(family)});`);
|
|
501
|
+
}
|
|
502
|
+
lines.push("");
|
|
503
|
+
return lines.join("\n");
|
|
504
|
+
}
|
|
505
|
+
function propertyNameToGoogleFontFamily(prop) {
|
|
506
|
+
return prop.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
507
|
+
}
|
|
303
508
|
/**
|
|
304
509
|
* manualChunks function for client builds.
|
|
305
510
|
*
|
|
@@ -742,6 +947,7 @@ function vinext(options = {}) {
|
|
|
742
947
|
root = config.root ?? process.cwd();
|
|
743
948
|
const userResolve = config.resolve;
|
|
744
949
|
const shouldEnableNativeTsconfigPaths = viteMajorVersion >= 8 && userResolve?.tsconfigPaths === void 0;
|
|
950
|
+
const tsconfigPathAliases = resolveTsconfigAliases(root);
|
|
745
951
|
const mode = env?.mode ?? "development";
|
|
746
952
|
const dotenvVars = loadEnv(mode, config.envDir ?? root, "");
|
|
747
953
|
for (const [key, value] of Object.entries(dotenvVars)) if (process.env[key] === void 0) process.env[key] = value;
|
|
@@ -915,6 +1121,7 @@ function vinext(options = {}) {
|
|
|
915
1121
|
} },
|
|
916
1122
|
resolve: {
|
|
917
1123
|
alias: {
|
|
1124
|
+
...tsconfigPathAliases,
|
|
918
1125
|
...nextConfig.aliases,
|
|
919
1126
|
...nextShimMap
|
|
920
1127
|
},
|
|
@@ -1058,9 +1265,14 @@ function vinext(options = {}) {
|
|
|
1058
1265
|
if (cleanId === VIRTUAL_RSC_ENTRY) return RESOLVED_RSC_ENTRY;
|
|
1059
1266
|
if (cleanId === VIRTUAL_APP_SSR_ENTRY) return RESOLVED_APP_SSR_ENTRY;
|
|
1060
1267
|
if (cleanId === VIRTUAL_APP_BROWSER_ENTRY) return RESOLVED_APP_BROWSER_ENTRY;
|
|
1268
|
+
if (cleanId.startsWith(VIRTUAL_GOOGLE_FONTS + "?")) return RESOLVED_VIRTUAL_GOOGLE_FONTS + cleanId.slice(27);
|
|
1061
1269
|
if (cleanId.endsWith("/" + VIRTUAL_RSC_ENTRY) || cleanId.endsWith("\\" + VIRTUAL_RSC_ENTRY)) return RESOLVED_RSC_ENTRY;
|
|
1062
1270
|
if (cleanId.endsWith("/" + VIRTUAL_APP_SSR_ENTRY) || cleanId.endsWith("\\" + VIRTUAL_APP_SSR_ENTRY)) return RESOLVED_APP_SSR_ENTRY;
|
|
1063
1271
|
if (cleanId.endsWith("/" + VIRTUAL_APP_BROWSER_ENTRY) || cleanId.endsWith("\\" + VIRTUAL_APP_BROWSER_ENTRY)) return RESOLVED_APP_BROWSER_ENTRY;
|
|
1272
|
+
if (cleanId.includes("/" + VIRTUAL_GOOGLE_FONTS + "?") || cleanId.includes("\\" + VIRTUAL_GOOGLE_FONTS + "?")) {
|
|
1273
|
+
const queryIndex = cleanId.indexOf(VIRTUAL_GOOGLE_FONTS + "?");
|
|
1274
|
+
return RESOLVED_VIRTUAL_GOOGLE_FONTS + cleanId.slice(queryIndex + 27);
|
|
1275
|
+
}
|
|
1064
1276
|
}
|
|
1065
1277
|
},
|
|
1066
1278
|
async load(id) {
|
|
@@ -1083,6 +1295,7 @@ function vinext(options = {}) {
|
|
|
1083
1295
|
}
|
|
1084
1296
|
if (id === RESOLVED_APP_SSR_ENTRY && hasAppDir) return generateSsrEntry(hasPagesDir);
|
|
1085
1297
|
if (id === RESOLVED_APP_BROWSER_ENTRY && hasAppDir) return generateBrowserEntry();
|
|
1298
|
+
if (id.startsWith(RESOLVED_VIRTUAL_GOOGLE_FONTS + "?")) return generateGoogleFontsVirtualModule(id);
|
|
1086
1299
|
}
|
|
1087
1300
|
},
|
|
1088
1301
|
asyncHooksStubPlugin,
|
|
@@ -1570,38 +1783,82 @@ function vinext(options = {}) {
|
|
|
1570
1783
|
},
|
|
1571
1784
|
transform: {
|
|
1572
1785
|
filter: {
|
|
1573
|
-
id: {
|
|
1574
|
-
include: /\.(tsx?|jsx?|mjs)$/,
|
|
1575
|
-
exclude: /node_modules/
|
|
1576
|
-
},
|
|
1786
|
+
id: { include: /\.(tsx?|jsx?|mjs)$/ },
|
|
1577
1787
|
code: "next/font/google"
|
|
1578
1788
|
},
|
|
1579
1789
|
async handler(code, id) {
|
|
1580
|
-
if (!this._isBuild) return null;
|
|
1581
|
-
if (id.includes("node_modules")) return null;
|
|
1582
1790
|
if (id.startsWith("\0")) return null;
|
|
1583
1791
|
if (!id.match(/\.(tsx?|jsx?|mjs)$/)) return null;
|
|
1584
1792
|
if (!code.includes("next/font/google")) return null;
|
|
1585
|
-
|
|
1586
|
-
const importMatch = code.match(/import\s*\{([^}]+)\}\s*from\s*['"]next\/font\/google['"]/);
|
|
1587
|
-
if (!importMatch) return null;
|
|
1588
|
-
const importedNames = new Set(importMatch[1].split(",").map((s) => s.trim()).filter(Boolean));
|
|
1793
|
+
if (id.startsWith(_shimsDir)) return null;
|
|
1589
1794
|
const s = new MagicString(code);
|
|
1590
1795
|
let hasChanges = false;
|
|
1796
|
+
let proxyImportCounter = 0;
|
|
1797
|
+
const overwrittenRanges = [];
|
|
1798
|
+
const fontLocals = /* @__PURE__ */ new Map();
|
|
1799
|
+
const proxyObjectLocals = /* @__PURE__ */ new Set();
|
|
1800
|
+
const importRe = /^[ \t]*import\s+([^;]+?)\s+from\s*(["'])next\/font\/google\2\s*;?/gm;
|
|
1801
|
+
let importMatch;
|
|
1802
|
+
while ((importMatch = importRe.exec(code)) !== null) {
|
|
1803
|
+
const [fullMatch, clause] = importMatch;
|
|
1804
|
+
const matchStart = importMatch.index;
|
|
1805
|
+
const matchEnd = matchStart + fullMatch.length;
|
|
1806
|
+
const parsed = parseGoogleFontImportClause(clause);
|
|
1807
|
+
const utilityImports = parsed.named.filter((spec) => !spec.isType && GOOGLE_FONT_UTILITY_EXPORTS.has(spec.imported));
|
|
1808
|
+
const fontImports = parsed.named.filter((spec) => !spec.isType && !GOOGLE_FONT_UTILITY_EXPORTS.has(spec.imported));
|
|
1809
|
+
if (parsed.defaultLocal) proxyObjectLocals.add(parsed.defaultLocal);
|
|
1810
|
+
for (const fontImport of fontImports) fontLocals.set(fontImport.local, fontImport.imported);
|
|
1811
|
+
if (fontImports.length > 0) {
|
|
1812
|
+
const virtualId = encodeGoogleFontsVirtualId({
|
|
1813
|
+
hasDefault: Boolean(parsed.defaultLocal),
|
|
1814
|
+
fonts: Array.from(new Set(fontImports.map((spec) => spec.imported))),
|
|
1815
|
+
utilities: Array.from(new Set(utilityImports.map((spec) => spec.imported)))
|
|
1816
|
+
});
|
|
1817
|
+
s.overwrite(matchStart, matchEnd, `import ${clause} from ${JSON.stringify(virtualId)};`);
|
|
1818
|
+
overwrittenRanges.push([matchStart, matchEnd]);
|
|
1819
|
+
hasChanges = true;
|
|
1820
|
+
continue;
|
|
1821
|
+
}
|
|
1822
|
+
if (parsed.namespaceLocal) {
|
|
1823
|
+
const proxyImportName = `__vinext_google_fonts_proxy_${proxyImportCounter++}`;
|
|
1824
|
+
const replacementLines = [`import ${proxyImportName} from ${JSON.stringify(_fontGoogleShimPath)};`];
|
|
1825
|
+
if (parsed.defaultLocal) replacementLines.push(`var ${parsed.defaultLocal} = ${proxyImportName};`);
|
|
1826
|
+
replacementLines.push(`var ${parsed.namespaceLocal} = ${proxyImportName};`);
|
|
1827
|
+
s.overwrite(matchStart, matchEnd, replacementLines.join("\n"));
|
|
1828
|
+
overwrittenRanges.push([matchStart, matchEnd]);
|
|
1829
|
+
proxyObjectLocals.add(parsed.namespaceLocal);
|
|
1830
|
+
hasChanges = true;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
const exportRe = /^[ \t]*export\s*\{([^}]+)\}\s*from\s*(["'])next\/font\/google\2\s*;?/gm;
|
|
1834
|
+
let exportMatch;
|
|
1835
|
+
while ((exportMatch = exportRe.exec(code)) !== null) {
|
|
1836
|
+
const [fullMatch, specifiers] = exportMatch;
|
|
1837
|
+
const matchStart = exportMatch.index;
|
|
1838
|
+
const matchEnd = matchStart + fullMatch.length;
|
|
1839
|
+
const namedExports = parseGoogleFontNamedSpecifiers(specifiers);
|
|
1840
|
+
const utilityExports = namedExports.filter((spec) => !spec.isType && GOOGLE_FONT_UTILITY_EXPORTS.has(spec.imported));
|
|
1841
|
+
const fontExports = namedExports.filter((spec) => !spec.isType && !GOOGLE_FONT_UTILITY_EXPORTS.has(spec.imported));
|
|
1842
|
+
if (fontExports.length === 0) continue;
|
|
1843
|
+
const virtualId = encodeGoogleFontsVirtualId({
|
|
1844
|
+
hasDefault: false,
|
|
1845
|
+
fonts: Array.from(new Set(fontExports.map((spec) => spec.imported))),
|
|
1846
|
+
utilities: Array.from(new Set(utilityExports.map((spec) => spec.imported)))
|
|
1847
|
+
});
|
|
1848
|
+
s.overwrite(matchStart, matchEnd, `export { ${specifiers.trim()} } from ${JSON.stringify(virtualId)};`);
|
|
1849
|
+
overwrittenRanges.push([matchStart, matchEnd]);
|
|
1850
|
+
hasChanges = true;
|
|
1851
|
+
}
|
|
1591
1852
|
const cacheDir = this._cacheDir;
|
|
1592
1853
|
const fontCache = this._fontCache;
|
|
1593
|
-
|
|
1594
|
-
while ((match = fontCallRe.exec(code)) !== null) {
|
|
1595
|
-
const [fullMatch, fontName, optionsStr] = match;
|
|
1596
|
-
if (!importedNames.has(fontName)) continue;
|
|
1597
|
-
const family = fontName.replace(/_/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
1854
|
+
async function injectSelfHostedCss(callStart, callEnd, optionsStr, family, calleeSource) {
|
|
1598
1855
|
let options = {};
|
|
1599
1856
|
try {
|
|
1600
1857
|
const parsed = parseStaticObjectLiteral(optionsStr);
|
|
1601
|
-
if (!parsed)
|
|
1858
|
+
if (!parsed) return;
|
|
1602
1859
|
options = parsed;
|
|
1603
1860
|
} catch {
|
|
1604
|
-
|
|
1861
|
+
return;
|
|
1605
1862
|
}
|
|
1606
1863
|
const weights = options.weight ? Array.isArray(options.weight) ? options.weight : [options.weight] : [];
|
|
1607
1864
|
const styles = options.style ? Array.isArray(options.style) ? options.style : [options.style] : [];
|
|
@@ -1625,16 +1882,37 @@ function vinext(options = {}) {
|
|
|
1625
1882
|
localCSS = await fetchAndCacheFont(cssUrl, family, cacheDir);
|
|
1626
1883
|
fontCache.set(cssUrl, localCSS);
|
|
1627
1884
|
} catch {
|
|
1628
|
-
|
|
1885
|
+
return;
|
|
1629
1886
|
}
|
|
1630
|
-
const matchStart = match.index;
|
|
1631
|
-
const matchEnd = matchStart + fullMatch.length;
|
|
1632
1887
|
const escapedCSS = JSON.stringify(localCSS);
|
|
1633
1888
|
const closingBrace = optionsStr.lastIndexOf("}");
|
|
1634
|
-
const replacement = `${
|
|
1635
|
-
s.overwrite(
|
|
1889
|
+
const replacement = `${calleeSource}(${optionsStr.slice(0, closingBrace) + (optionsStr.slice(0, closingBrace).trim().endsWith("{") ? "" : ", ") + `_selfHostedCSS: ${escapedCSS}` + optionsStr.slice(closingBrace)})`;
|
|
1890
|
+
s.overwrite(callStart, callEnd, replacement);
|
|
1636
1891
|
hasChanges = true;
|
|
1637
1892
|
}
|
|
1893
|
+
if (this._isBuild) {
|
|
1894
|
+
const namedCallRe = /\b([A-Za-z_$][A-Za-z0-9_$]*)\s*\(\s*(\{[^}]*\})\s*\)/g;
|
|
1895
|
+
let namedCallMatch;
|
|
1896
|
+
while ((namedCallMatch = namedCallRe.exec(code)) !== null) {
|
|
1897
|
+
const [fullMatch, localName, optionsStr] = namedCallMatch;
|
|
1898
|
+
const importedName = fontLocals.get(localName);
|
|
1899
|
+
if (!importedName) continue;
|
|
1900
|
+
const callStart = namedCallMatch.index;
|
|
1901
|
+
const callEnd = callStart + fullMatch.length;
|
|
1902
|
+
if (overwrittenRanges.some(([start, end]) => callStart < end && callEnd > start)) continue;
|
|
1903
|
+
await injectSelfHostedCss(callStart, callEnd, optionsStr, importedName.replace(/_/g, " "), localName);
|
|
1904
|
+
}
|
|
1905
|
+
const memberCallRe = /\b([A-Za-z_$][A-Za-z0-9_$]*)\.([A-Za-z_$][A-Za-z0-9_$]*)\s*\(\s*(\{[^}]*\})\s*\)/g;
|
|
1906
|
+
let memberCallMatch;
|
|
1907
|
+
while ((memberCallMatch = memberCallRe.exec(code)) !== null) {
|
|
1908
|
+
const [fullMatch, objectName, propName, optionsStr] = memberCallMatch;
|
|
1909
|
+
if (!proxyObjectLocals.has(objectName)) continue;
|
|
1910
|
+
const callStart = memberCallMatch.index;
|
|
1911
|
+
const callEnd = callStart + fullMatch.length;
|
|
1912
|
+
if (overwrittenRanges.some(([start, end]) => callStart < end && callEnd > start)) continue;
|
|
1913
|
+
await injectSelfHostedCss(callStart, callEnd, optionsStr, propertyNameToGoogleFontFamily(propName), `${objectName}.${propName}`);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1638
1916
|
if (!hasChanges) return null;
|
|
1639
1917
|
return {
|
|
1640
1918
|
code: s.toString(),
|
|
@@ -1685,6 +1963,7 @@ function vinext(options = {}) {
|
|
|
1685
1963
|
}
|
|
1686
1964
|
}
|
|
1687
1965
|
},
|
|
1966
|
+
createOptimizeImportsPlugin(() => nextConfig, () => root),
|
|
1688
1967
|
{
|
|
1689
1968
|
name: "vinext:use-cache",
|
|
1690
1969
|
transform: {
|