vinext 0.1.1 → 0.1.2
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 +2 -5
- package/dist/build/client-build-config.d.ts +7 -1
- package/dist/build/client-build-config.js +9 -1
- package/dist/check.js +4 -3
- package/dist/client/navigation-runtime.d.ts +3 -2
- package/dist/client/window-next.d.ts +6 -4
- package/dist/config/config-matchers.d.ts +11 -4
- package/dist/config/config-matchers.js +15 -2
- package/dist/config/next-config.d.ts +13 -0
- package/dist/config/next-config.js +2 -0
- package/dist/deploy.js +9 -2
- package/dist/entries/app-rsc-entry.js +7 -1
- package/dist/entries/pages-client-entry.js +1 -1
- package/dist/entries/pages-server-entry.js +7 -6
- package/dist/index.d.ts +0 -2
- package/dist/index.js +86 -78
- package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
- package/dist/plugins/dynamic-preload-metadata.js +415 -0
- package/dist/plugins/og-assets.js +2 -2
- package/dist/plugins/optimize-imports.d.ts +8 -4
- package/dist/plugins/optimize-imports.js +16 -12
- package/dist/plugins/sass.d.ts +53 -24
- package/dist/plugins/sass.js +249 -1
- package/dist/plugins/wasm-module-import.d.ts +15 -0
- package/dist/plugins/wasm-module-import.js +50 -0
- package/dist/routing/app-route-graph.d.ts +23 -1
- package/dist/routing/app-route-graph.js +47 -8
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/app-browser-entry.js +108 -213
- package/dist/server/app-browser-error.d.ts +4 -1
- package/dist/server/app-browser-error.js +7 -1
- package/dist/server/app-browser-history-controller.d.ts +104 -0
- package/dist/server/app-browser-history-controller.js +210 -0
- package/dist/server/app-browser-navigation-controller.d.ts +3 -2
- package/dist/server/app-browser-navigation-controller.js +10 -7
- package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
- package/dist/server/app-browser-rsc-redirect.js +30 -8
- package/dist/server/app-browser-state.js +4 -7
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.js +22 -1
- package/dist/server/app-page-boundary-render.d.ts +2 -1
- package/dist/server/app-page-boundary-render.js +4 -2
- package/dist/server/app-page-cache.js +9 -7
- package/dist/server/app-page-dispatch.d.ts +8 -0
- package/dist/server/app-page-dispatch.js +18 -5
- package/dist/server/app-page-element-builder.d.ts +22 -2
- package/dist/server/app-page-element-builder.js +37 -8
- package/dist/server/app-page-execution.d.ts +1 -1
- package/dist/server/app-page-execution.js +32 -17
- package/dist/server/app-page-render.d.ts +1 -1
- package/dist/server/app-page-render.js +7 -14
- package/dist/server/app-page-request.d.ts +1 -0
- package/dist/server/app-page-request.js +3 -2
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +8 -7
- package/dist/server/app-page-stream.d.ts +1 -6
- package/dist/server/app-page-stream.js +1 -4
- package/dist/server/app-route-handler-response.js +11 -10
- package/dist/server/app-route-handler-runtime.js +12 -1
- package/dist/server/app-rsc-handler.js +1 -1
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +11 -0
- package/dist/server/app-server-action-execution.js +5 -2
- package/dist/server/app-ssr-entry.js +2 -2
- package/dist/server/app-ssr-stream.js +9 -1
- package/dist/server/dev-lockfile.js +2 -1
- package/dist/server/dev-server.js +43 -12
- package/dist/server/headers.d.ts +8 -1
- package/dist/server/headers.js +8 -1
- package/dist/server/instrumentation-runtime.d.ts +6 -0
- package/dist/server/instrumentation-runtime.js +8 -0
- package/dist/server/isr-decision.d.ts +79 -0
- package/dist/server/isr-decision.js +70 -0
- package/dist/server/metadata-route-response.js +5 -3
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +11 -7
- package/dist/server/middleware.js +1 -0
- package/dist/server/navigation-planner.d.ts +62 -1
- package/dist/server/navigation-planner.js +188 -0
- package/dist/server/navigation-trace.d.ts +11 -1
- package/dist/server/navigation-trace.js +11 -1
- package/dist/server/normalize-path.d.ts +0 -8
- package/dist/server/normalize-path.js +3 -1
- package/dist/server/otel-tracer-extension.d.ts +45 -0
- package/dist/server/otel-tracer-extension.js +89 -0
- package/dist/server/pages-api-route.d.ts +14 -3
- package/dist/server/pages-api-route.js +6 -1
- package/dist/server/pages-asset-tags.d.ts +15 -4
- package/dist/server/pages-asset-tags.js +18 -12
- package/dist/server/pages-data-route.js +5 -1
- package/dist/server/pages-node-compat.d.ts +3 -11
- package/dist/server/pages-node-compat.js +174 -121
- package/dist/server/pages-page-data.d.ts +28 -0
- package/dist/server/pages-page-data.js +61 -17
- package/dist/server/pages-page-handler.d.ts +1 -0
- package/dist/server/pages-page-handler.js +22 -6
- package/dist/server/pages-page-response.d.ts +45 -1
- package/dist/server/pages-page-response.js +66 -5
- package/dist/server/pages-readiness.d.ts +1 -1
- package/dist/server/pages-request-pipeline.d.ts +15 -1
- package/dist/server/pages-request-pipeline.js +23 -2
- package/dist/server/prod-server.d.ts +39 -1
- package/dist/server/prod-server.js +98 -34
- package/dist/shims/cache-runtime.js +9 -2
- package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
- package/dist/shims/dynamic-preload-chunks.js +77 -0
- package/dist/shims/dynamic.d.ts +4 -0
- package/dist/shims/dynamic.js +4 -2
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error.js +37 -11
- package/dist/shims/fetch-cache.d.ts +9 -1
- package/dist/shims/fetch-cache.js +11 -1
- package/dist/shims/head.js +6 -1
- package/dist/shims/headers.d.ts +16 -2
- package/dist/shims/headers.js +37 -1
- package/dist/shims/image-config.js +7 -1
- package/dist/shims/internal/app-route-detection.d.ts +6 -3
- package/dist/shims/internal/app-route-detection.js +10 -6
- package/dist/shims/internal/app-router-context.d.ts +5 -0
- package/dist/shims/metadata.d.ts +6 -2
- package/dist/shims/metadata.js +32 -14
- package/dist/shims/navigation.d.ts +7 -16
- package/dist/shims/navigation.js +33 -16
- package/dist/shims/router.js +28 -1
- package/dist/shims/script-nonce-context.d.ts +1 -1
- package/dist/shims/script-nonce-context.js +11 -3
- package/dist/shims/server.d.ts +17 -1
- package/dist/shims/server.js +31 -6
- package/dist/shims/slot.js +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -0
- package/dist/utils/client-build-manifest.js +15 -5
- package/dist/utils/client-runtime-metadata.d.ts +45 -0
- package/dist/utils/client-runtime-metadata.js +63 -0
- package/dist/utils/hash.d.ts +17 -1
- package/dist/utils/hash.js +36 -1
- package/dist/utils/lazy-chunks.d.ts +27 -1
- package/dist/utils/lazy-chunks.js +65 -1
- package/dist/utils/manifest-paths.d.ts +20 -2
- package/dist/utils/manifest-paths.js +38 -3
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +5 -1
- package/package.json +2 -2
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
import { isUnknownRecord } from "../utils/record.js";
|
|
2
|
+
import { relativeWithinRoot, tryRealpathSync } from "../build/ssr-manifest.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parseAst } from "vite";
|
|
5
|
+
import MagicString from "magic-string";
|
|
6
|
+
//#region src/plugins/dynamic-preload-metadata.ts
|
|
7
|
+
function getString(node, key) {
|
|
8
|
+
const value = node[key];
|
|
9
|
+
return typeof value === "string" ? value : null;
|
|
10
|
+
}
|
|
11
|
+
function getNumber(node, key) {
|
|
12
|
+
const value = node[key];
|
|
13
|
+
return typeof value === "number" ? value : null;
|
|
14
|
+
}
|
|
15
|
+
function getArray(node, key) {
|
|
16
|
+
const value = node[key];
|
|
17
|
+
return Array.isArray(value) ? value : [];
|
|
18
|
+
}
|
|
19
|
+
function getBoolean(node, key) {
|
|
20
|
+
return node[key] === true;
|
|
21
|
+
}
|
|
22
|
+
function nodeName(node) {
|
|
23
|
+
if (!isUnknownRecord(node)) return null;
|
|
24
|
+
const name = node.name;
|
|
25
|
+
if (typeof name === "string") return name;
|
|
26
|
+
const value = node.value;
|
|
27
|
+
return typeof value === "string" ? value : null;
|
|
28
|
+
}
|
|
29
|
+
function nodeStringValue(node) {
|
|
30
|
+
if (!isUnknownRecord(node)) return null;
|
|
31
|
+
const value = node.value;
|
|
32
|
+
return typeof value === "string" ? value : null;
|
|
33
|
+
}
|
|
34
|
+
function walkAst(value, visitor) {
|
|
35
|
+
if (!isUnknownRecord(value)) return;
|
|
36
|
+
visitor(value);
|
|
37
|
+
for (const [key, child] of Object.entries(value)) {
|
|
38
|
+
if (key === "parent") continue;
|
|
39
|
+
if (Array.isArray(child)) for (const item of child) walkAst(item, visitor);
|
|
40
|
+
else if (isUnknownRecord(child)) walkAst(child, visitor);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function importSource(node) {
|
|
44
|
+
const source = node.source;
|
|
45
|
+
if (!isUnknownRecord(source)) return null;
|
|
46
|
+
return nodeStringValue(source);
|
|
47
|
+
}
|
|
48
|
+
function isNextDynamicSource(source) {
|
|
49
|
+
return source === "next/dynamic" || source === "next/dynamic.js";
|
|
50
|
+
}
|
|
51
|
+
function collectDynamicImportLocals(ast) {
|
|
52
|
+
const locals = /* @__PURE__ */ new Set();
|
|
53
|
+
if (!isUnknownRecord(ast)) return locals;
|
|
54
|
+
for (const node of getArray(ast, "body")) {
|
|
55
|
+
if (!isUnknownRecord(node)) continue;
|
|
56
|
+
if (getString(node, "type") !== "ImportDeclaration") continue;
|
|
57
|
+
if (!isNextDynamicSource(importSource(node))) continue;
|
|
58
|
+
for (const specifier of getArray(node, "specifiers")) {
|
|
59
|
+
if (!isUnknownRecord(specifier)) continue;
|
|
60
|
+
if (getString(specifier, "type") !== "ImportDefaultSpecifier") continue;
|
|
61
|
+
const local = nodeName(specifier.local);
|
|
62
|
+
if (local) locals.add(local);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return locals;
|
|
66
|
+
}
|
|
67
|
+
function isIdentifierNameInSet(node, names) {
|
|
68
|
+
if (!isUnknownRecord(node)) return false;
|
|
69
|
+
return getString(node, "type") === "Identifier" && names.has(getString(node, "name") ?? "");
|
|
70
|
+
}
|
|
71
|
+
function isDynamicCall(node, dynamicLocals) {
|
|
72
|
+
if (getString(node, "type") !== "CallExpression") return false;
|
|
73
|
+
return isIdentifierNameInSet(node.callee, dynamicLocals);
|
|
74
|
+
}
|
|
75
|
+
function addBindingName(pattern, names) {
|
|
76
|
+
if (!isUnknownRecord(pattern)) return;
|
|
77
|
+
const type = getString(pattern, "type");
|
|
78
|
+
if (type === null) return;
|
|
79
|
+
switch (type) {
|
|
80
|
+
case "Identifier": {
|
|
81
|
+
const name = getString(pattern, "name");
|
|
82
|
+
if (name) names.add(name);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
case "AssignmentPattern":
|
|
86
|
+
addBindingName(pattern.left, names);
|
|
87
|
+
return;
|
|
88
|
+
case "RestElement":
|
|
89
|
+
addBindingName(pattern.argument, names);
|
|
90
|
+
return;
|
|
91
|
+
case "ArrayPattern":
|
|
92
|
+
for (const element of getArray(pattern, "elements")) addBindingName(element, names);
|
|
93
|
+
return;
|
|
94
|
+
case "ObjectPattern":
|
|
95
|
+
for (const property of getArray(pattern, "properties")) {
|
|
96
|
+
if (!isUnknownRecord(property)) continue;
|
|
97
|
+
if (getString(property, "type") === "RestElement") {
|
|
98
|
+
addBindingName(property.argument, names);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
addBindingName(property.value, names);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
default: return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function addVariableDeclarationBindingNames(node, names) {
|
|
108
|
+
if (!isUnknownRecord(node) || getString(node, "type") !== "VariableDeclaration") return;
|
|
109
|
+
for (const declaration of getArray(node, "declarations")) if (isUnknownRecord(declaration)) addBindingName(declaration.id, names);
|
|
110
|
+
}
|
|
111
|
+
function collectBlockScopedBindingNames(body) {
|
|
112
|
+
const names = /* @__PURE__ */ new Set();
|
|
113
|
+
for (const statement of body) {
|
|
114
|
+
if (!isUnknownRecord(statement)) continue;
|
|
115
|
+
const type = getString(statement, "type");
|
|
116
|
+
if (type === "VariableDeclaration") {
|
|
117
|
+
if (getString(statement, "kind") !== "var") addVariableDeclarationBindingNames(statement, names);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (type === "FunctionDeclaration" || type === "ClassDeclaration") {
|
|
121
|
+
const name = nodeName(statement.id);
|
|
122
|
+
if (name) names.add(name);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return names;
|
|
126
|
+
}
|
|
127
|
+
function collectSwitchScopedBindingNames(node) {
|
|
128
|
+
const names = /* @__PURE__ */ new Set();
|
|
129
|
+
for (const switchCase of getArray(node, "cases")) {
|
|
130
|
+
if (!isUnknownRecord(switchCase)) continue;
|
|
131
|
+
for (const statement of getArray(switchCase, "consequent")) for (const name of collectBlockScopedBindingNames([statement])) names.add(name);
|
|
132
|
+
}
|
|
133
|
+
return names;
|
|
134
|
+
}
|
|
135
|
+
function collectVarBindingNames(value, names) {
|
|
136
|
+
if (!isUnknownRecord(value)) return;
|
|
137
|
+
const type = getString(value, "type");
|
|
138
|
+
if (type === "FunctionDeclaration" || type === "FunctionExpression" || type === "ArrowFunctionExpression") return;
|
|
139
|
+
if (type === "VariableDeclaration" && getString(value, "kind") === "var") addVariableDeclarationBindingNames(value, names);
|
|
140
|
+
for (const [key, child] of Object.entries(value)) {
|
|
141
|
+
if (key === "parent") continue;
|
|
142
|
+
if (Array.isArray(child)) for (const item of child) collectVarBindingNames(item, names);
|
|
143
|
+
else if (isUnknownRecord(child)) collectVarBindingNames(child, names);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function collectFunctionScopeBindingNames(node) {
|
|
147
|
+
const names = /* @__PURE__ */ new Set();
|
|
148
|
+
if (getString(node, "type") === "FunctionExpression") {
|
|
149
|
+
const name = nodeName(node.id);
|
|
150
|
+
if (name) names.add(name);
|
|
151
|
+
}
|
|
152
|
+
for (const param of getArray(node, "params")) addBindingName(param, names);
|
|
153
|
+
collectVarBindingNames(node.body, names);
|
|
154
|
+
return names;
|
|
155
|
+
}
|
|
156
|
+
function collectForBindingNames(node) {
|
|
157
|
+
const names = /* @__PURE__ */ new Set();
|
|
158
|
+
addVariableDeclarationBindingNames(node.init, names);
|
|
159
|
+
addVariableDeclarationBindingNames(node.left, names);
|
|
160
|
+
return names;
|
|
161
|
+
}
|
|
162
|
+
function withoutBindings(activeNames, localNames) {
|
|
163
|
+
if (activeNames.size === 0 || localNames.size === 0) return activeNames;
|
|
164
|
+
let scoped = null;
|
|
165
|
+
for (const name of localNames) {
|
|
166
|
+
if (!activeNames.has(name)) continue;
|
|
167
|
+
scoped ??= new Set(activeNames);
|
|
168
|
+
scoped.delete(name);
|
|
169
|
+
}
|
|
170
|
+
return scoped ?? activeNames;
|
|
171
|
+
}
|
|
172
|
+
function visitChildren(node, dynamicLocals, visitor) {
|
|
173
|
+
for (const [key, child] of Object.entries(node)) {
|
|
174
|
+
if (key === "parent") continue;
|
|
175
|
+
if (Array.isArray(child)) for (const item of child) visitDynamicCalls(item, dynamicLocals, visitor);
|
|
176
|
+
else if (isUnknownRecord(child)) visitDynamicCalls(child, dynamicLocals, visitor);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function visitDynamicCalls(value, dynamicLocals, visitor) {
|
|
180
|
+
if (!isUnknownRecord(value) || dynamicLocals.size === 0) return;
|
|
181
|
+
const type = getString(value, "type");
|
|
182
|
+
if (type === "Program") {
|
|
183
|
+
const scoped = withoutBindings(dynamicLocals, collectBlockScopedBindingNames(getArray(value, "body")));
|
|
184
|
+
for (const statement of getArray(value, "body")) visitDynamicCalls(statement, scoped, visitor);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (type === "BlockStatement") {
|
|
188
|
+
const scoped = withoutBindings(dynamicLocals, collectBlockScopedBindingNames(getArray(value, "body")));
|
|
189
|
+
for (const statement of getArray(value, "body")) visitDynamicCalls(statement, scoped, visitor);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (type === "SwitchStatement") {
|
|
193
|
+
visitDynamicCalls(value.discriminant, dynamicLocals, visitor);
|
|
194
|
+
const scoped = withoutBindings(dynamicLocals, collectSwitchScopedBindingNames(value));
|
|
195
|
+
for (const switchCase of getArray(value, "cases")) visitDynamicCalls(switchCase, scoped, visitor);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (type === "FunctionDeclaration" || type === "FunctionExpression" || type === "ArrowFunctionExpression") {
|
|
199
|
+
visitChildren(value, withoutBindings(dynamicLocals, collectFunctionScopeBindingNames(value)), visitor);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (type === "ClassDeclaration" || type === "ClassExpression") {
|
|
203
|
+
const names = /* @__PURE__ */ new Set();
|
|
204
|
+
const name = nodeName(value.id);
|
|
205
|
+
if (name) names.add(name);
|
|
206
|
+
visitChildren(value, withoutBindings(dynamicLocals, names), visitor);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (type === "ForStatement" || type === "ForInStatement" || type === "ForOfStatement") {
|
|
210
|
+
visitChildren(value, withoutBindings(dynamicLocals, collectForBindingNames(value)), visitor);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (type === "CatchClause") {
|
|
214
|
+
const names = /* @__PURE__ */ new Set();
|
|
215
|
+
addBindingName(value.param, names);
|
|
216
|
+
visitChildren(value, withoutBindings(dynamicLocals, names), visitor);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (isDynamicCall(value, dynamicLocals)) visitor(value);
|
|
220
|
+
visitChildren(value, dynamicLocals, visitor);
|
|
221
|
+
}
|
|
222
|
+
function collectImportSpecifiers(node) {
|
|
223
|
+
const specifiers = [];
|
|
224
|
+
const seen = /* @__PURE__ */ new Set();
|
|
225
|
+
walkAst(node, (item) => {
|
|
226
|
+
if (getString(item, "type") === "ImportExpression") {
|
|
227
|
+
const specifier = nodeStringValue(item.source);
|
|
228
|
+
if (specifier && !seen.has(specifier)) {
|
|
229
|
+
seen.add(specifier);
|
|
230
|
+
specifiers.push(specifier);
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (getString(item, "type") !== "CallExpression") return;
|
|
235
|
+
const callee = item.callee;
|
|
236
|
+
if (!isUnknownRecord(callee) || getString(callee, "type") !== "Import") return;
|
|
237
|
+
const firstArg = getArray(item, "arguments")[0];
|
|
238
|
+
const specifier = nodeStringValue(firstArg);
|
|
239
|
+
if (specifier && !seen.has(specifier)) {
|
|
240
|
+
seen.add(specifier);
|
|
241
|
+
specifiers.push(specifier);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
return specifiers;
|
|
245
|
+
}
|
|
246
|
+
function propertyKeyName(property) {
|
|
247
|
+
if (!isUnknownRecord(property)) return null;
|
|
248
|
+
if (getBoolean(property, "computed")) return null;
|
|
249
|
+
return nodeName(property.key);
|
|
250
|
+
}
|
|
251
|
+
function objectProperties(node) {
|
|
252
|
+
if (!isUnknownRecord(node) || getString(node, "type") !== "ObjectExpression") return [];
|
|
253
|
+
return getArray(node, "properties").filter(isUnknownRecord);
|
|
254
|
+
}
|
|
255
|
+
function hasObjectProperty(node, name) {
|
|
256
|
+
return objectProperties(node).some((property) => propertyKeyName(property) === name);
|
|
257
|
+
}
|
|
258
|
+
function findObjectProperty(node, name) {
|
|
259
|
+
return objectProperties(node).find((property) => propertyKeyName(property) === name) ?? null;
|
|
260
|
+
}
|
|
261
|
+
function dynamicLoaderNode(firstArg) {
|
|
262
|
+
if (!isUnknownRecord(firstArg) || getString(firstArg, "type") !== "ObjectExpression") return firstArg;
|
|
263
|
+
return (findObjectProperty(firstArg, "loader") ?? findObjectProperty(firstArg, "modules"))?.value;
|
|
264
|
+
}
|
|
265
|
+
function findLastEndedProperty(node) {
|
|
266
|
+
const properties = objectProperties(node);
|
|
267
|
+
for (let index = properties.length - 1; index >= 0; index -= 1) if (getNumber(properties[index], "end") !== null) return properties[index];
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
function appendObjectProperty(output, objectNode, property) {
|
|
271
|
+
const start = getNumber(objectNode, "start");
|
|
272
|
+
const end = getNumber(objectNode, "end");
|
|
273
|
+
if (start === null || end === null) return false;
|
|
274
|
+
const lastProperty = findLastEndedProperty(objectNode);
|
|
275
|
+
if (!lastProperty) {
|
|
276
|
+
output.appendLeft(start + 1, property);
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
const propertyEnd = getNumber(lastProperty, "end");
|
|
280
|
+
if (propertyEnd === null) return false;
|
|
281
|
+
output.appendLeft(propertyEnd, `, ${property}`);
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
function stripComments(source) {
|
|
285
|
+
return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
|
|
286
|
+
}
|
|
287
|
+
function insertSecondOptionsArgument(output, code, callNode, firstArg, optionsLiteral) {
|
|
288
|
+
const callEnd = getNumber(callNode, "end");
|
|
289
|
+
const firstArgEnd = getNumber(firstArg, "end");
|
|
290
|
+
if (callEnd === null || firstArgEnd === null) return false;
|
|
291
|
+
const closeParen = callEnd - 1;
|
|
292
|
+
const separator = stripComments(code.slice(firstArgEnd, closeParen)).trimEnd().endsWith(",") ? " " : ", ";
|
|
293
|
+
output.appendLeft(closeParen, `${separator}${optionsLiteral}`);
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
function cleanResolvedId(id) {
|
|
297
|
+
let start = 0;
|
|
298
|
+
while (start < id.length && id.charCodeAt(start) === 0) start += 1;
|
|
299
|
+
return id.slice(start).replace(/^\/@fs\//, "/").split("?")[0].replace(/\\/g, "/");
|
|
300
|
+
}
|
|
301
|
+
const rootRealpathCache = /* @__PURE__ */ new Map();
|
|
302
|
+
function cachedRootRealpath(root) {
|
|
303
|
+
if (!rootRealpathCache.has(root)) rootRealpathCache.set(root, tryRealpathSync(root));
|
|
304
|
+
return rootRealpathCache.get(root) ?? null;
|
|
305
|
+
}
|
|
306
|
+
/** `code` offset -> human `:line:column` (1-based), for build error messages. */
|
|
307
|
+
function formatNodeLocation(code, node) {
|
|
308
|
+
const start = getNumber(node, "start");
|
|
309
|
+
if (start === null) return "";
|
|
310
|
+
const before = code.slice(0, start);
|
|
311
|
+
return `:${before.split("\n").length}:${start - before.lastIndexOf("\n")}`;
|
|
312
|
+
}
|
|
313
|
+
function toManifestModuleId(root, resolvedId) {
|
|
314
|
+
const cleaned = cleanResolvedId(resolvedId);
|
|
315
|
+
if (!path.isAbsolute(cleaned)) return cleaned.replace(/^\/+/, "");
|
|
316
|
+
const rootCandidates = new Set([root]);
|
|
317
|
+
const realRoot = cachedRootRealpath(root);
|
|
318
|
+
if (realRoot) rootCandidates.add(realRoot);
|
|
319
|
+
const moduleCandidates = new Set([cleaned]);
|
|
320
|
+
const realCleaned = tryRealpathSync(cleaned);
|
|
321
|
+
if (realCleaned) moduleCandidates.add(realCleaned.replace(/\\/g, "/"));
|
|
322
|
+
for (const rootCandidate of rootCandidates) for (const moduleCandidate of moduleCandidates) {
|
|
323
|
+
const relative = relativeWithinRoot(rootCandidate, moduleCandidate);
|
|
324
|
+
if (relative) return relative;
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
async function resolveManifestModuleIds(specifiers, importer, root, resolveDynamicImport) {
|
|
329
|
+
const resolvedIds = [];
|
|
330
|
+
const seen = /* @__PURE__ */ new Set();
|
|
331
|
+
for (const specifier of specifiers) {
|
|
332
|
+
const resolved = await resolveDynamicImport(specifier, importer);
|
|
333
|
+
const moduleId = resolved ? toManifestModuleId(root, resolved) : null;
|
|
334
|
+
if (!moduleId || seen.has(moduleId)) continue;
|
|
335
|
+
seen.add(moduleId);
|
|
336
|
+
resolvedIds.push(moduleId);
|
|
337
|
+
}
|
|
338
|
+
return resolvedIds;
|
|
339
|
+
}
|
|
340
|
+
function shouldSkipCall(firstArg, secondArg) {
|
|
341
|
+
if (hasObjectProperty(firstArg, "loadableGenerated")) return true;
|
|
342
|
+
return hasObjectProperty(secondArg, "loadableGenerated");
|
|
343
|
+
}
|
|
344
|
+
function applyLoadableGenerated(output, code, callNode, moduleIds) {
|
|
345
|
+
const args = getArray(callNode, "arguments");
|
|
346
|
+
const firstArg = args[0];
|
|
347
|
+
const secondArg = args[1];
|
|
348
|
+
if (!isUnknownRecord(firstArg)) return false;
|
|
349
|
+
if (shouldSkipCall(firstArg, secondArg)) return false;
|
|
350
|
+
const property = `loadableGenerated: { modules: ${JSON.stringify(moduleIds)} }`;
|
|
351
|
+
if (getString(firstArg, "type") === "ObjectExpression") return appendObjectProperty(output, firstArg, property);
|
|
352
|
+
if (secondArg === void 0) return insertSecondOptionsArgument(output, code, callNode, firstArg, `{ ${property} }`);
|
|
353
|
+
if (isUnknownRecord(secondArg) && getString(secondArg, "type") === "ObjectExpression") return appendObjectProperty(output, secondArg, property);
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
async function transformNextDynamicPreloadMetadata(code, id, root, resolveDynamicImport) {
|
|
357
|
+
if (!code.includes("next/dynamic")) return null;
|
|
358
|
+
let ast;
|
|
359
|
+
try {
|
|
360
|
+
ast = parseAst(code);
|
|
361
|
+
} catch (error) {
|
|
362
|
+
if (typeof process !== "undefined" && process.env?.DEBUG?.includes("vinext")) console.debug(`[vinext] dynamic-preload-metadata: failed to parse ${id}:`, error);
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
const dynamicLocals = collectDynamicImportLocals(ast);
|
|
366
|
+
if (dynamicLocals.size === 0) return null;
|
|
367
|
+
const output = new MagicString(code);
|
|
368
|
+
let changed = false;
|
|
369
|
+
const pending = [];
|
|
370
|
+
visitDynamicCalls(ast, dynamicLocals, (node) => {
|
|
371
|
+
const args = getArray(node, "arguments");
|
|
372
|
+
if (args.length > 2) throw new Error(`next/dynamic only accepts 2 arguments (${id}${formatNodeLocation(code, node)})`);
|
|
373
|
+
const specifiers = collectImportSpecifiers(dynamicLoaderNode(args[0]));
|
|
374
|
+
if (specifiers.length === 0) return;
|
|
375
|
+
pending.push(resolveManifestModuleIds(specifiers, id, root, resolveDynamicImport).then((moduleIds) => {
|
|
376
|
+
if (moduleIds.length === 0) return;
|
|
377
|
+
if (applyLoadableGenerated(output, code, node, moduleIds)) changed = true;
|
|
378
|
+
}));
|
|
379
|
+
});
|
|
380
|
+
await Promise.all(pending);
|
|
381
|
+
if (!changed) return null;
|
|
382
|
+
return {
|
|
383
|
+
code: output.toString(),
|
|
384
|
+
map: output.generateMap({ hires: "boundary" })
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function createDynamicPreloadMetadataPlugin() {
|
|
388
|
+
let root = process.cwd();
|
|
389
|
+
return {
|
|
390
|
+
name: "vinext:dynamic-preload-metadata",
|
|
391
|
+
configResolved(config) {
|
|
392
|
+
root = config.root;
|
|
393
|
+
},
|
|
394
|
+
transform: {
|
|
395
|
+
filter: {
|
|
396
|
+
id: {
|
|
397
|
+
include: /\.(tsx?|jsx?|mjs)$/,
|
|
398
|
+
exclude: /node_modules/
|
|
399
|
+
},
|
|
400
|
+
code: "next/dynamic"
|
|
401
|
+
},
|
|
402
|
+
async handler(code, id) {
|
|
403
|
+
if (id.includes("node_modules") || id.startsWith("\0")) return null;
|
|
404
|
+
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return null;
|
|
405
|
+
const result = await transformNextDynamicPreloadMetadata(code, id, root, async (specifier, importer) => {
|
|
406
|
+
return (await this.resolve(specifier, importer, { skipSelf: true }))?.id ?? null;
|
|
407
|
+
});
|
|
408
|
+
if (!result) return null;
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
//#endregion
|
|
415
|
+
export { createDynamicPreloadMetadataPlugin, transformNextDynamicPreloadMetadata };
|
|
@@ -42,7 +42,7 @@ function createOgInlineFetchAssetsPlugin() {
|
|
|
42
42
|
return null;
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
if (code.includes("fetch(")) for (const match of code.matchAll(/fetch\(\s*new URL\(\s*(["'])(
|
|
45
|
+
if (code.includes("fetch(")) for (const match of code.matchAll(/fetch\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)(?:\.then\(\s*(?:function\s*\([^)]*\)|\([^)]*\)\s*=>)\s*\{?\s*return\s+[^.]+\.arrayBuffer\(\)\s*;?\s*\}?\s*,?\s*\)|\.then\(\s*\([^)]*\)\s*=>\s*[^.]+\.arrayBuffer\(\)\s*,?\s*\))/g)) {
|
|
46
46
|
const fullMatch = match[0];
|
|
47
47
|
const relPath = match[2];
|
|
48
48
|
const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
|
|
@@ -59,7 +59,7 @@ function createOgInlineFetchAssetsPlugin() {
|
|
|
59
59
|
newCode = newCode.replaceAll(fullMatch, inlined);
|
|
60
60
|
didReplace = true;
|
|
61
61
|
}
|
|
62
|
-
if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(
|
|
62
|
+
if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)\s*\)/g)) {
|
|
63
63
|
const fullMatch = match[0];
|
|
64
64
|
const relPath = match[2];
|
|
65
65
|
const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
|
|
@@ -21,11 +21,15 @@ declare const DEFAULT_OPTIMIZE_PACKAGES: string[];
|
|
|
21
21
|
* Handles: `export * as X from`, `export { A } from`, `import * as X; export { X }`,
|
|
22
22
|
* and `export * from "./sub"` (recursively resolves wildcard re-exports).
|
|
23
23
|
*
|
|
24
|
-
* Returns null if
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* Returns null if `entryPath` is empty, the file cannot be read, or the file
|
|
25
|
+
* has a parse error. Returns an empty map if the file is valid but exports
|
|
26
|
+
* nothing.
|
|
27
|
+
*
|
|
28
|
+
* @param entryPath - Pre-resolved absolute path to the barrel entry file (the
|
|
29
|
+
* caller owns entry resolution + its caching), or null when it could not be
|
|
30
|
+
* resolved.
|
|
27
31
|
*/
|
|
28
|
-
declare function buildBarrelExportMap(
|
|
32
|
+
declare function buildBarrelExportMap(entryPath: string | null, readFile: (filepath: string) => Promise<string | null>, cache?: Map<string, BarrelExportMap>): Promise<BarrelExportMap | null>;
|
|
29
33
|
/**
|
|
30
34
|
* Creates the vinext:optimize-imports Vite plugin.
|
|
31
35
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizePathSeparators } from "../utils/path.js";
|
|
1
2
|
import { getAstName } from "./ast-utils.js";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import path from "node:path";
|
|
@@ -185,12 +186,12 @@ async function resolvePackageEntry(packageName, projectRoot, preferReactServer)
|
|
|
185
186
|
const dotExport = pkgJson.exports["."];
|
|
186
187
|
if (dotExport) {
|
|
187
188
|
const entryPath = resolveExportsValue(dotExport, preferReactServer);
|
|
188
|
-
if (entryPath) return path.resolve(pkgDir, entryPath)
|
|
189
|
+
if (entryPath) return normalizePathSeparators(path.resolve(pkgDir, entryPath));
|
|
189
190
|
}
|
|
190
191
|
}
|
|
191
192
|
const entryField = pkgJson.module ?? pkgJson.main;
|
|
192
|
-
if (typeof entryField === "string") return path.resolve(pkgDir, entryField)
|
|
193
|
-
return createRequire(path.join(projectRoot, "package.json")).resolve(packageName)
|
|
193
|
+
if (typeof entryField === "string") return normalizePathSeparators(path.resolve(pkgDir, entryField));
|
|
194
|
+
return normalizePathSeparators(createRequire(path.join(projectRoot, "package.json")).resolve(packageName));
|
|
194
195
|
} catch {
|
|
195
196
|
return null;
|
|
196
197
|
}
|
|
@@ -228,14 +229,14 @@ async function buildExportMapFromFile(filePath, readFile, cache, visited, initia
|
|
|
228
229
|
const exportMap = /* @__PURE__ */ new Map();
|
|
229
230
|
const importBindings = /* @__PURE__ */ new Map();
|
|
230
231
|
const localDeclarations = /* @__PURE__ */ new Set();
|
|
231
|
-
const fileDir = path.dirname(filePath);
|
|
232
|
+
const fileDir = path.posix.dirname(filePath);
|
|
232
233
|
/**
|
|
233
234
|
* Normalize a source specifier: resolve relative paths to absolute so that
|
|
234
235
|
* entries in the export map always store absolute paths for file references.
|
|
235
236
|
* Bare package specifiers (e.g. "@radix-ui/react-slot") are returned unchanged.
|
|
236
237
|
*/
|
|
237
238
|
function normalizeSource(source) {
|
|
238
|
-
return source.startsWith(".") ? path.
|
|
239
|
+
return source.startsWith(".") ? path.posix.join(fileDir, source) : source;
|
|
239
240
|
}
|
|
240
241
|
function recordLocalDeclaration(node) {
|
|
241
242
|
if (!node) return;
|
|
@@ -297,7 +298,7 @@ async function buildExportMapFromFile(filePath, readFile, cache, visited, initia
|
|
|
297
298
|
isNamespace: true
|
|
298
299
|
});
|
|
299
300
|
} else if (rawSource.startsWith(".")) {
|
|
300
|
-
const subPath = path.
|
|
301
|
+
const subPath = path.posix.join(fileDir, rawSource);
|
|
301
302
|
const candidates = [
|
|
302
303
|
subPath,
|
|
303
304
|
`${subPath}.js`,
|
|
@@ -386,12 +387,15 @@ async function buildExportMapFromFile(filePath, readFile, cache, visited, initia
|
|
|
386
387
|
* Handles: `export * as X from`, `export { A } from`, `import * as X; export { X }`,
|
|
387
388
|
* and `export * from "./sub"` (recursively resolves wildcard re-exports).
|
|
388
389
|
*
|
|
389
|
-
* Returns null if
|
|
390
|
-
*
|
|
391
|
-
*
|
|
390
|
+
* Returns null if `entryPath` is empty, the file cannot be read, or the file
|
|
391
|
+
* has a parse error. Returns an empty map if the file is valid but exports
|
|
392
|
+
* nothing.
|
|
393
|
+
*
|
|
394
|
+
* @param entryPath - Pre-resolved absolute path to the barrel entry file (the
|
|
395
|
+
* caller owns entry resolution + its caching), or null when it could not be
|
|
396
|
+
* resolved.
|
|
392
397
|
*/
|
|
393
|
-
async function buildBarrelExportMap(
|
|
394
|
-
const entryPath = resolveEntry(packageName);
|
|
398
|
+
async function buildBarrelExportMap(entryPath, readFile, cache) {
|
|
395
399
|
if (!entryPath) return null;
|
|
396
400
|
const exportMapCache = cache ?? /* @__PURE__ */ new Map();
|
|
397
401
|
const cached = exportMapCache.get(entryPath);
|
|
@@ -466,7 +470,7 @@ function createOptimizeImportsPlugin(getNextConfig, getRoot) {
|
|
|
466
470
|
barrelEntry = await resolvePackageEntry(importSource, root, preferReactServer);
|
|
467
471
|
entryPathCache.set(cacheKey, barrelEntry ?? null);
|
|
468
472
|
}
|
|
469
|
-
const exportMap = await buildBarrelExportMap(
|
|
473
|
+
const exportMap = await buildBarrelExportMap(barrelEntry, readFileSafe, barrelCaches.exportMapCache);
|
|
470
474
|
if (!exportMap || !barrelEntry) continue;
|
|
471
475
|
const envKey = preferReactServer ? "rsc" : "ssr";
|
|
472
476
|
const registeredKey = `${envKey}:${barrelEntry}`;
|
package/dist/plugins/sass.d.ts
CHANGED
|
@@ -1,33 +1,62 @@
|
|
|
1
|
+
import { ResolvedConfig } from "vite";
|
|
2
|
+
|
|
1
3
|
//#region src/plugins/sass.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Map a Next.js `sassOptions` object onto Vite's
|
|
4
|
-
* `css.preprocessorOptions.scss` / `.sass` shape.
|
|
5
|
-
*
|
|
6
|
-
* Next.js (webpack + sass-loader) accepts:
|
|
7
|
-
* - `additionalData` (or legacy `prependData`) — prepended to every source
|
|
8
|
-
* - `includePaths` — directories searched by `@import`
|
|
9
|
-
* - `loadPaths` — modern Sass equivalent of `includePaths`
|
|
10
|
-
* - `implementation` — Sass implementation package name (e.g. `sass-embedded`)
|
|
11
|
-
* - other Sass options that get forwarded as-is
|
|
12
|
-
*
|
|
13
|
-
* Reference (Next.js source — destructures the same keys before forwarding
|
|
14
|
-
* the rest to sass-loader):
|
|
15
|
-
* .nextjs-ref/packages/next/src/build/webpack/config/blocks/css/index.ts#L150-L180
|
|
16
|
-
* https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/config/blocks/css/index.ts
|
|
17
|
-
*
|
|
18
|
-
* Vite expects:
|
|
19
|
-
* - `additionalData` (string or function) on the preprocessor options
|
|
20
|
-
* - modern Sass options (`loadPaths`, `importers`, `implementation`, …)
|
|
21
|
-
* flattened next to `additionalData`
|
|
22
|
-
*
|
|
23
|
-
* @see https://vite.dev/config/shared-options.html#css-preprocessoroptions
|
|
24
|
-
*/
|
|
25
4
|
type AdditionalData = string | ((source: string, filename: string) => string | Promise<string>);
|
|
26
5
|
type VitePreprocessorOptions = {
|
|
27
6
|
additionalData?: AdditionalData;
|
|
28
7
|
loadPaths?: string[];
|
|
29
8
|
[key: string]: any;
|
|
30
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Create a Sass `FileImporter` that resolves webpack-style tilde (`~`) imports.
|
|
12
|
+
*
|
|
13
|
+
* Next.js (via sass-loader's `webpackImporter`) supports two tilde forms:
|
|
14
|
+
*
|
|
15
|
+
* 1. `~pkg/path` — resolves `pkg/path` from `node_modules`. Used for
|
|
16
|
+
* third-party SCSS/CSS, e.g. `@import '~nprogress/nprogress.css'`.
|
|
17
|
+
*
|
|
18
|
+
* 2. `~/path` — resolves relative to the **project root** (the `~` acts as
|
|
19
|
+
* an alias for the root). Used with Turbopack's `resolveAlias: { '~*': '*' }`
|
|
20
|
+
* convention, e.g. `@use '~/styles/variables' as *`.
|
|
21
|
+
*
|
|
22
|
+
* Vite's built-in Sass resolver does not strip the `~` prefix, so any SCSS
|
|
23
|
+
* that uses tilde imports fails with "Can't find stylesheet to import" errors.
|
|
24
|
+
* This `FileImporter` runs before Vite's internal importer (added at the end
|
|
25
|
+
* of `importers[]` in the vite:css plugin) and canonicalises tilde URLs so
|
|
26
|
+
* Sass can load them from the filesystem.
|
|
27
|
+
*
|
|
28
|
+
* The returned object implements the modern Sass `FileImporter` interface:
|
|
29
|
+
* `findFileUrl` returns a `file://` URL and Sass automatically handles partial
|
|
30
|
+
* resolution (`_variables.scss` for `variables`), index files, and extensions.
|
|
31
|
+
*
|
|
32
|
+
* @param root - Absolute path to the Vite project root (used as the base for
|
|
33
|
+
* `~/path` resolution and for locating `node_modules`).
|
|
34
|
+
*/
|
|
35
|
+
declare function createSassTildeImporter(root: string): {
|
|
36
|
+
findFileUrl(url: string): URL | null;
|
|
37
|
+
};
|
|
31
38
|
declare function buildSassPreprocessorOptions(sassOptions: Record<string, unknown> | null | undefined): VitePreprocessorOptions | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Create a per-build binding of {@link SassAwareFileSystemLoader}.
|
|
41
|
+
*
|
|
42
|
+
* Returns:
|
|
43
|
+
* - `Loader` — a class to inject as postcss-modules' `css.modules.Loader`
|
|
44
|
+
* option. postcss-modules instantiates it with the fixed
|
|
45
|
+
* `(root, plugins, fileResolve)` signature, so the resolved Vite config is
|
|
46
|
+
* captured in this factory's closure rather than passed to the constructor.
|
|
47
|
+
* - `setResolvedConfig` — called from vinext's `configResolved` hook to bind
|
|
48
|
+
* that build's resolved config.
|
|
49
|
+
*
|
|
50
|
+
* One binding is created per vinext plugin instance, so concurrent or
|
|
51
|
+
* back-to-back builds in a single process never observe another build's
|
|
52
|
+
* config (root, sass options, `generateScopedName`, logger, …).
|
|
53
|
+
*/
|
|
54
|
+
declare function createSassAwareFileSystemLoader(): {
|
|
55
|
+
Loader: new (root: string, plugins: unknown[], fileResolve?: (newPath: string, relativeTo: string) => Promise<string>) => {
|
|
56
|
+
fetch(newPath: string, relativeTo: string, trace?: string): Promise<Record<string, string>>;
|
|
57
|
+
readonly finalSource: string;
|
|
58
|
+
};
|
|
59
|
+
setResolvedConfig: (config: ResolvedConfig) => void;
|
|
60
|
+
};
|
|
32
61
|
//#endregion
|
|
33
|
-
export { buildSassPreprocessorOptions };
|
|
62
|
+
export { buildSassPreprocessorOptions, createSassAwareFileSystemLoader, createSassTildeImporter };
|