vite-plugin-vercel 11.0.0-beta.2 → 11.0.0-beta.20
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 +4 -7
- package/dist/api.js +63 -1
- package/dist/assert-vtiLgQIb.js +8 -0
- package/dist/index.d.ts +20 -7
- package/dist/index.js +3 -3
- package/dist/types.d.ts +14 -0
- package/dist/vite.js +467 -103
- package/package.json +9 -8
- package/dist/api-DR2y7JVQ.js +0 -70
- /package/dist/{path-B4ThGm96.js → path-DoLvGKnz.js} +0 -0
package/README.md
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
# vite-plugin-vercel
|
|
2
2
|
|
|
3
3
|
> [!NOTE]
|
|
4
|
-
> You are on the [Vite Environment API](https://vite.dev/guide/api-environment.html#environment-configuration) beta branch (
|
|
4
|
+
> You are on the [Vite Environment API](https://vite.dev/guide/api-environment.html#environment-configuration) beta branch (v11). Check out [v9 branch](https://github.com/magne4000/vite-plugin-vercel/tree/v9) for current stable version.
|
|
5
5
|
|
|
6
6
|
Vercel adapter for [Vite](https://vitejs.dev/).
|
|
7
7
|
|
|
8
8
|
Bundle your Vite application as supported by [Vercel Output API (v3)](https://vercel.com/docs/build-output-api/v3).
|
|
9
9
|
|
|
10
|
-
> [!NOTE]
|
|
11
|
-
> This plugin is mostly a re-export of [`@photonjs/vercel`](https://github.com/photon-js/photon/tree/main/packages/adapter-vercel)
|
|
12
|
-
|
|
13
10
|
## Install
|
|
14
11
|
|
|
15
12
|
```bash
|
|
@@ -68,7 +65,7 @@ export default defineConfig({
|
|
|
68
65
|
```
|
|
69
66
|
|
|
70
67
|
> [!NOTE]
|
|
71
|
-
> `@vercel/build`
|
|
68
|
+
> `@vercel/build` forces the building of files in the _/api_ folder, with no way to disable this behavior.
|
|
72
69
|
> It's recommended to place your files in a different folder.
|
|
73
70
|
|
|
74
71
|
### Configure endpoints
|
|
@@ -165,7 +162,7 @@ export default defineConfig({
|
|
|
165
162
|
trailingSlash: true,
|
|
166
163
|
/**
|
|
167
164
|
* Use `getVercelEntries` for mapping your filesystem routes to entries.
|
|
168
|
-
* If you are interfacing this plugin with a framework, entries can also be added through the
|
|
165
|
+
* If you are interfacing this plugin with a framework, entries can also be added through the {@link https://github.com/photon-js/universal-deploy | universal-deploy} API
|
|
169
166
|
*/
|
|
170
167
|
entries: {
|
|
171
168
|
root: {
|
|
@@ -209,7 +206,7 @@ Related documentation: https://vercel.com/docs/edge-network/headers/request-head
|
|
|
209
206
|
|
|
210
207
|
## Migrations
|
|
211
208
|
|
|
212
|
-
- [Migration from v9 to
|
|
209
|
+
- [Migration from v9 to v11](https://github.com/magne4000/vite-plugin-vercel/blob/main/MIGRATION.md)
|
|
213
210
|
|
|
214
211
|
## Demo
|
|
215
212
|
|
package/dist/api.js
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as assert } from "./assert-vtiLgQIb.js";
|
|
2
2
|
|
|
3
|
+
//#region src/api.ts
|
|
4
|
+
function createAPI(outfiles, pluginConfig) {
|
|
5
|
+
return {
|
|
6
|
+
getOutFiles() {
|
|
7
|
+
return outfiles;
|
|
8
|
+
},
|
|
9
|
+
get config() {
|
|
10
|
+
pluginConfig.config ??= {};
|
|
11
|
+
return pluginConfig.config;
|
|
12
|
+
},
|
|
13
|
+
get defaultMaxDuration() {
|
|
14
|
+
return pluginConfig.defaultMaxDuration;
|
|
15
|
+
},
|
|
16
|
+
set defaultMaxDuration(value) {
|
|
17
|
+
pluginConfig.defaultMaxDuration = value;
|
|
18
|
+
},
|
|
19
|
+
get expiration() {
|
|
20
|
+
return pluginConfig.expiration;
|
|
21
|
+
},
|
|
22
|
+
set expiration(value) {
|
|
23
|
+
pluginConfig.expiration = value;
|
|
24
|
+
},
|
|
25
|
+
get rewrites() {
|
|
26
|
+
pluginConfig.rewrites ??= [];
|
|
27
|
+
return pluginConfig.rewrites;
|
|
28
|
+
},
|
|
29
|
+
get headers() {
|
|
30
|
+
pluginConfig.headers ??= [];
|
|
31
|
+
return pluginConfig.headers;
|
|
32
|
+
},
|
|
33
|
+
get redirects() {
|
|
34
|
+
pluginConfig.redirects ??= [];
|
|
35
|
+
return pluginConfig.redirects;
|
|
36
|
+
},
|
|
37
|
+
get cleanUrls() {
|
|
38
|
+
return pluginConfig.cleanUrls;
|
|
39
|
+
},
|
|
40
|
+
set cleanUrls(value) {
|
|
41
|
+
pluginConfig.cleanUrls = value;
|
|
42
|
+
},
|
|
43
|
+
get trailingSlash() {
|
|
44
|
+
return pluginConfig.trailingSlash;
|
|
45
|
+
},
|
|
46
|
+
set trailingSlash(value) {
|
|
47
|
+
pluginConfig.trailingSlash = value;
|
|
48
|
+
},
|
|
49
|
+
get defaultSupportsResponseStreaming() {
|
|
50
|
+
return pluginConfig.defaultSupportsResponseStreaming;
|
|
51
|
+
},
|
|
52
|
+
set defaultSupportsResponseStreaming(value) {
|
|
53
|
+
pluginConfig.defaultSupportsResponseStreaming = value;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function getVercelAPI(pluginContextOrServer) {
|
|
58
|
+
const vpv = ("environment" in pluginContextOrServer ? pluginContextOrServer.environment.config : pluginContextOrServer.config).plugins.find((p) => p.name === "vite-plugin-vercel:api");
|
|
59
|
+
assert(vpv, "Could not find vite-plugin-vercel:api plugin");
|
|
60
|
+
assert(vpv.api, "Missing `api`. Make sure vite-plugin-vercel is up-to-date");
|
|
61
|
+
return vpv.api("environment" in pluginContextOrServer ? pluginContextOrServer : void 0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
3
65
|
export { createAPI, getVercelAPI };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
import { EntryMeta } from "@universal-deploy/store";
|
|
2
2
|
|
|
3
3
|
//#region src/index.d.ts
|
|
4
|
-
|
|
4
|
+
interface GetVercelEntriesOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Map entries to URL patterns
|
|
7
|
+
* @example
|
|
8
|
+
* // When dir: "endpoints/myapi" and destination: "api"
|
|
9
|
+
* // endpoints/myapi/page.ts -> /api/page
|
|
10
|
+
* // endpoints/myapi/name/[name].ts -> /api/name/*
|
|
11
|
+
*/
|
|
12
|
+
destination?: string;
|
|
13
|
+
/**
|
|
14
|
+
* If true, parse entries exports for per-file settings.
|
|
15
|
+
* Entries can export `edge`, `isr`, `headers` and `streaming`. See README for more details
|
|
16
|
+
*
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
tryParseExports?: boolean;
|
|
20
|
+
}
|
|
5
21
|
/**
|
|
6
22
|
* Scans the filesystem for entry points.
|
|
7
|
-
* @
|
|
23
|
+
* @beta
|
|
8
24
|
*/
|
|
9
25
|
declare function getVercelEntries(dir: string, {
|
|
10
26
|
destination,
|
|
11
27
|
tryParseExports
|
|
12
|
-
}:
|
|
13
|
-
destination?: string | undefined;
|
|
14
|
-
tryParseExports?: boolean | undefined;
|
|
15
|
-
}): Promise<EntryMeta[]>;
|
|
28
|
+
}: GetVercelEntriesOptions): Promise<EntryMeta[]>;
|
|
16
29
|
declare function extractExports(filepath: string): Promise<{
|
|
17
30
|
edge?: boolean | undefined;
|
|
18
31
|
headers?: Record<string, string> | undefined;
|
|
@@ -22,4 +35,4 @@ declare function extractExports(filepath: string): Promise<{
|
|
|
22
35
|
} | undefined;
|
|
23
36
|
} | null>;
|
|
24
37
|
//#endregion
|
|
25
|
-
export { extractExports, getVercelEntries };
|
|
38
|
+
export { GetVercelEntriesOptions, extractExports, getVercelEntries };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as pathRelativeTo } from "./path-
|
|
1
|
+
import { t as pathRelativeTo } from "./path-DoLvGKnz.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { vercelEndpointExports } from "@vite-plugin-vercel/schemas";
|
|
4
4
|
import { fromNextFs } from "convert-route/next-fs";
|
|
@@ -10,7 +10,7 @@ import { normalizePath } from "vite";
|
|
|
10
10
|
//#region src/index.ts
|
|
11
11
|
/**
|
|
12
12
|
* Scans the filesystem for entry points.
|
|
13
|
-
* @
|
|
13
|
+
* @beta
|
|
14
14
|
*/
|
|
15
15
|
async function getVercelEntries(dir, { destination = dir, tryParseExports = true }) {
|
|
16
16
|
const normalizedDir = normalizePath(dir);
|
|
@@ -31,7 +31,7 @@ async function getVercelEntries(dir, { destination = dir, tryParseExports = true
|
|
|
31
31
|
if (xports?.isr) entry.vercel.isr = xports.isr;
|
|
32
32
|
if (xports?.headers) entry.vercel.headers = xports.headers;
|
|
33
33
|
if (xports?.streaming) entry.vercel.streaming = xports.streaming;
|
|
34
|
-
entry.
|
|
34
|
+
entry.route = entryToRou3(key);
|
|
35
35
|
if (key.includes("[...")) entry.vercel.enforce = "post";
|
|
36
36
|
entryPoints.push(entry);
|
|
37
37
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -12,6 +12,20 @@ type ViteVercelRedirect = Redirect & {
|
|
|
12
12
|
};
|
|
13
13
|
type PluginContext = ThisParameterType<Extract<Plugin["resolveId"], (...args: never) => any>>;
|
|
14
14
|
interface ViteVercelConfig {
|
|
15
|
+
/**
|
|
16
|
+
* @experimental
|
|
17
|
+
* @default basic
|
|
18
|
+
*/
|
|
19
|
+
bundleStrategy?: "basic" | "nf3";
|
|
20
|
+
/**
|
|
21
|
+
* Override vite build environments
|
|
22
|
+
* @experimental
|
|
23
|
+
*/
|
|
24
|
+
viteEnvNames?: {
|
|
25
|
+
client?: string;
|
|
26
|
+
edge?: string | false;
|
|
27
|
+
node?: string;
|
|
28
|
+
};
|
|
15
29
|
/**
|
|
16
30
|
* How long Functions should be allowed to run for every request, in seconds.
|
|
17
31
|
* If left empty, default value for your plan will be used.
|
package/dist/vite.js
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
|
-
import { t as pathRelativeTo$1 } from "./path-
|
|
2
|
-
import {
|
|
1
|
+
import { t as pathRelativeTo$1 } from "./path-DoLvGKnz.js";
|
|
2
|
+
import { t as assert } from "./assert-vtiLgQIb.js";
|
|
3
|
+
import { createAPI, getVercelAPI } from "./api.js";
|
|
4
|
+
import { builtinModules } from "node:module";
|
|
3
5
|
import path from "node:path";
|
|
4
6
|
import { vercelOutputConfigSchema, vercelOutputPrerenderConfigSchema, vercelOutputVcConfigSchema } from "@vite-plugin-vercel/schemas";
|
|
5
7
|
import { fromRou3 } from "convert-route/rou3";
|
|
6
8
|
import { BuildEnvironment, createRunnableDevEnvironment, mergeConfig, normalizePath } from "vite";
|
|
7
9
|
import { catchAll, devServer } from "@universal-deploy/store/vite";
|
|
8
|
-
import {
|
|
9
|
-
import fs from "node:fs";
|
|
10
|
+
import { addEntry, getAllEntries } from "@universal-deploy/store";
|
|
11
|
+
import fs, { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { copyFile, cp, rmdir, unlink } from "node:fs/promises";
|
|
13
|
+
import { findRoot } from "@manypkg/find-root";
|
|
14
|
+
import { nodeFileTrace, resolve } from "@vercel/nft";
|
|
15
|
+
import { transform } from "oxc-transform";
|
|
16
|
+
import { build } from "rolldown";
|
|
10
17
|
import { cpus } from "node:os";
|
|
11
|
-
import { resolve } from "@vercel/nft";
|
|
12
18
|
import { externals } from "nf3/plugin";
|
|
13
19
|
import pLimit from "p-limit";
|
|
14
|
-
import { build } from "rolldown";
|
|
15
20
|
import { getNodeVersion } from "@vercel/build-utils";
|
|
16
21
|
import { toPathToRegexpV6 } from "convert-route/path-to-regexp-v6";
|
|
17
|
-
import { cp } from "node:fs/promises";
|
|
18
22
|
import { getTransformedRoutes, mergeRoutes, normalizeRoutes } from "@vercel/routing-utils";
|
|
19
23
|
|
|
24
|
+
//#region src/utils/buildEnvs.ts
|
|
25
|
+
function getBuildEnvNames(pluginConfig) {
|
|
26
|
+
return {
|
|
27
|
+
client: pluginConfig.viteEnvNames?.client ?? "vercel_client",
|
|
28
|
+
edge: pluginConfig.viteEnvNames?.edge ?? "vercel_edge",
|
|
29
|
+
node: pluginConfig.viteEnvNames?.node ?? "vercel_node"
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
20
34
|
//#region src/utils/dedupeRoutes.ts
|
|
21
35
|
/**
|
|
22
36
|
* When multiple entries point to the same module, we can deploy them as a single function.
|
|
@@ -24,20 +38,65 @@ import { getTransformedRoutes, mergeRoutes, normalizeRoutes } from "@vercel/rout
|
|
|
24
38
|
*/
|
|
25
39
|
function dedupeRoutes() {
|
|
26
40
|
const entriesToKeep = [];
|
|
27
|
-
const entriesGroupedByModuleId = groupBy(
|
|
41
|
+
const entriesGroupedByModuleId = groupBy(getAllEntries(), (e) => e.id);
|
|
28
42
|
for (const entries of entriesGroupedByModuleId.values()) {
|
|
29
43
|
let groupedEntry;
|
|
30
44
|
for (const entry of entries) if (entry.vercel && Object.keys(entry.vercel).length > 0) {
|
|
31
|
-
if (!Array.isArray(entry.
|
|
45
|
+
if (!Array.isArray(entry.route)) entry.route = [entry.route];
|
|
32
46
|
entriesToKeep.push(entry);
|
|
33
47
|
} else if (!groupedEntry) {
|
|
34
48
|
groupedEntry = structuredClone(entry);
|
|
35
|
-
if (!Array.isArray(groupedEntry.
|
|
49
|
+
if (!Array.isArray(groupedEntry.route)) groupedEntry.route = [groupedEntry.route];
|
|
36
50
|
entriesToKeep.push(groupedEntry);
|
|
37
|
-
} else groupedEntry.
|
|
51
|
+
} else groupedEntry.route.push(...[entry.route].flat());
|
|
38
52
|
}
|
|
39
53
|
return entriesToKeep;
|
|
40
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Sorts routes by specificity.
|
|
57
|
+
*
|
|
58
|
+
* Specificity rules:
|
|
59
|
+
* 1. Segment type priority at each position: Static > Dynamic/Param > Catch-all.
|
|
60
|
+
* 2. Total route length: Longer routes are generally more specific.
|
|
61
|
+
* 3. Prefix match exception: A shorter static route is more specific than a longer route
|
|
62
|
+
* that only adds a catch-all segment to the same prefix.
|
|
63
|
+
* 4. Alphabetical order: Final tie-breaker for static segments at the same position.
|
|
64
|
+
*
|
|
65
|
+
* @param routes - Array of routes to sort.
|
|
66
|
+
* @returns A new array of routes sorted from most specific to least specific.
|
|
67
|
+
*/
|
|
68
|
+
function sortRoutes(routes) {
|
|
69
|
+
return [...routes].sort((a, b) => {
|
|
70
|
+
const lenA = a.pathname.length;
|
|
71
|
+
const lenB = b.pathname.length;
|
|
72
|
+
const commonLen = Math.min(lenA, lenB);
|
|
73
|
+
for (let i = 0; i < commonLen; i++) {
|
|
74
|
+
const segA = a.pathname[i];
|
|
75
|
+
const segB = b.pathname[i];
|
|
76
|
+
if (segA.value && !segB.value) return -1;
|
|
77
|
+
if (!segA.value && segB.value) return 1;
|
|
78
|
+
if (segA.value && segB.value) {
|
|
79
|
+
if (segA.value !== segB.value) {
|
|
80
|
+
if (lenA !== lenB) return lenB - lenA;
|
|
81
|
+
return segA.value.localeCompare(segB.value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (!segA.optional && segB.optional) return -1;
|
|
85
|
+
if (segA.optional && !segB.optional) return 1;
|
|
86
|
+
if (segA.catchAll && segB.catchAll) {
|
|
87
|
+
if (!segA.catchAll.greedy && segB.catchAll.greedy) return -1;
|
|
88
|
+
if (segA.catchAll.greedy && !segB.catchAll.greedy) return 1;
|
|
89
|
+
}
|
|
90
|
+
if (segA.catchAll && !segB.catchAll) return 1;
|
|
91
|
+
if (!segA.catchAll && segB.catchAll) return -1;
|
|
92
|
+
}
|
|
93
|
+
if (lenA !== lenB) {
|
|
94
|
+
if (lenA > lenB) return a.pathname[lenB].catchAll ? 1 : -1;
|
|
95
|
+
return b.pathname[lenA].catchAll ? -1 : 1;
|
|
96
|
+
}
|
|
97
|
+
return 0;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
41
100
|
function groupBy(list, fn, selector) {
|
|
42
101
|
return Array.from(list).reduce((acc, curr) => {
|
|
43
102
|
const key = fn(curr);
|
|
@@ -56,8 +115,36 @@ function removeExtension$1(subject) {
|
|
|
56
115
|
|
|
57
116
|
//#endregion
|
|
58
117
|
//#region src/utils/destination.ts
|
|
118
|
+
function parseViteId(id) {
|
|
119
|
+
const [path, query] = id.split("?");
|
|
120
|
+
return {
|
|
121
|
+
path: decodeURIComponent(path),
|
|
122
|
+
query
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function extractBestPath({ path, query }) {
|
|
126
|
+
if (!query) return path;
|
|
127
|
+
return query.split("&").map(decodeURIComponent).find((p) => p.includes("/")) || path;
|
|
128
|
+
}
|
|
129
|
+
function shortenPath(path, maxSegments = 2) {
|
|
130
|
+
return removeExtension$1(path.split(/[\\/]/).filter(Boolean).slice(-maxSegments).join("_"));
|
|
131
|
+
}
|
|
132
|
+
function mapPath(path, maxSegments = 2) {
|
|
133
|
+
const nodeModuleMatch = path.match(/node_modules[\\/](.+?)([\\/].*)?$/);
|
|
134
|
+
if (nodeModuleMatch) return `${nodeModuleMatch[1].split(/[\\/]/)[0]}_${removeExtension$1(nodeModuleMatch[2]?.split(/[\\/]/).pop() || "index")}`;
|
|
135
|
+
return shortenPath(path, maxSegments);
|
|
136
|
+
}
|
|
137
|
+
function hashString(str, length = 6) {
|
|
138
|
+
let hash = 5381;
|
|
139
|
+
for (let i = 0; i < str.length; i++) hash = hash * 33 ^ str.charCodeAt(i);
|
|
140
|
+
hash = hash >>> 0;
|
|
141
|
+
return hash.toString(36).slice(0, length);
|
|
142
|
+
}
|
|
143
|
+
function uniqueViteName(id, entry, maxSegments = 2) {
|
|
144
|
+
return removeExtension$1(`${mapPath(extractBestPath(parseViteId(id)), maxSegments)}_${hashString(JSON.stringify(entry))}`.replace(/[^a-zA-Z0-9\-_[\]/]/g, "-"));
|
|
145
|
+
}
|
|
59
146
|
function entryDestinationDefault(root, entry) {
|
|
60
|
-
return
|
|
147
|
+
return uniqueViteName(pathRelativeTo$1(entry.id, root), entry);
|
|
61
148
|
}
|
|
62
149
|
function entryDestination(root, entry, postfix) {
|
|
63
150
|
return `${path.posix.join("functions/", entryDestinationDefault(root, entry))}${postfix}`;
|
|
@@ -66,6 +153,7 @@ function entryDestination(root, entry, postfix) {
|
|
|
66
153
|
//#endregion
|
|
67
154
|
//#region src/plugins/api.ts
|
|
68
155
|
function apiPlugin(pluginConfig) {
|
|
156
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
69
157
|
const outfiles = [];
|
|
70
158
|
return {
|
|
71
159
|
name: "vite-plugin-vercel:api",
|
|
@@ -73,12 +161,12 @@ function apiPlugin(pluginConfig) {
|
|
|
73
161
|
return createAPI(outfiles, pluginConfig);
|
|
74
162
|
},
|
|
75
163
|
applyToEnvironment({ name }) {
|
|
76
|
-
return name ===
|
|
164
|
+
return name === envNames.edge || name === envNames.node;
|
|
77
165
|
},
|
|
78
|
-
writeBundle(_opts, bundle
|
|
166
|
+
writeBundle(_opts, bundle) {
|
|
79
167
|
const root = this.environment.config.root ?? process.cwd();
|
|
80
168
|
const entryMapByDestination = new Map(dedupeRoutes().map((e) => [entryDestination(root, e, ".func/index"), e]));
|
|
81
|
-
for (const [key, value] of Object.entries(bundle
|
|
169
|
+
for (const [key, value] of Object.entries(bundle)) if (value.type === "chunk" && entryMapByDestination.has(removeExtension$1(key))) outfiles.push({
|
|
82
170
|
type: "chunk",
|
|
83
171
|
root: this.environment.config.root,
|
|
84
172
|
outdir: this.environment.config.build.outDir,
|
|
@@ -96,6 +184,17 @@ function apiPlugin(pluginConfig) {
|
|
|
96
184
|
};
|
|
97
185
|
}
|
|
98
186
|
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/utils/edge.ts
|
|
189
|
+
const edgeConditions = [
|
|
190
|
+
"edge-light",
|
|
191
|
+
"worker",
|
|
192
|
+
"browser",
|
|
193
|
+
"module",
|
|
194
|
+
"import",
|
|
195
|
+
"default"
|
|
196
|
+
];
|
|
197
|
+
|
|
99
198
|
//#endregion
|
|
100
199
|
//#region src/utils/external.ts
|
|
101
200
|
const _external = [
|
|
@@ -108,8 +207,193 @@ const _external = [
|
|
|
108
207
|
const edgeExternal = [..._external, ..._external.map((e) => `node:${e}`)];
|
|
109
208
|
|
|
110
209
|
//#endregion
|
|
111
|
-
//#region src/plugins/bundle.ts
|
|
112
|
-
|
|
210
|
+
//#region src/plugins/bundle/basic.ts
|
|
211
|
+
const builtIns = new Set(builtinModules.flatMap((m) => [m, `node:${m}`]));
|
|
212
|
+
const edgeWasmPlugin = {
|
|
213
|
+
name: "edge-wasm-vercel",
|
|
214
|
+
resolveId: {
|
|
215
|
+
filter: { id: [/\.wasm\?module$/] },
|
|
216
|
+
handler(id) {
|
|
217
|
+
return {
|
|
218
|
+
id: id.replace(/\.wasm\?module$/, ".wasm"),
|
|
219
|
+
external: true
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const dynamicNativeImportPlugin = {
|
|
225
|
+
name: "edge-dynamic-import-native",
|
|
226
|
+
resolveDynamicImport(specifier) {
|
|
227
|
+
if (typeof specifier === "string" && builtIns.has(specifier)) return {
|
|
228
|
+
id: specifier,
|
|
229
|
+
external: true
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const reactEdgePlugin$1 = {
|
|
234
|
+
name: "react-edge-plugin",
|
|
235
|
+
resolveId: {
|
|
236
|
+
filter: { id: [/react-dom\/server/] },
|
|
237
|
+
async handler(_id, importer, options) {
|
|
238
|
+
return this.resolve("react-dom/server.edge", importer, options);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
function basicBundlePlugin(pluginConfig) {
|
|
243
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
244
|
+
const bundledAssets = /* @__PURE__ */ new Map();
|
|
245
|
+
const bundledChunks = [];
|
|
246
|
+
return [{
|
|
247
|
+
name: "vite-plugin-vercel:bundle",
|
|
248
|
+
enforce: "post",
|
|
249
|
+
apply: "build",
|
|
250
|
+
generateBundle(_opts, bundle) {
|
|
251
|
+
for (const b of Object.values(bundle)) {
|
|
252
|
+
const outFile = joinAbsolute(this.environment, this.environment.config.build.outDir, b.fileName);
|
|
253
|
+
if (b.type === "asset") {
|
|
254
|
+
const originalFileNames = b.originalFileNames.map((relativePath) => path.resolve(this.environment.config.root, relativePath));
|
|
255
|
+
const asset = {
|
|
256
|
+
env: this.environment.name,
|
|
257
|
+
root: this.environment.config.root,
|
|
258
|
+
outDir: this.environment.config.build.outDir,
|
|
259
|
+
outFile,
|
|
260
|
+
fileName: b.fileName
|
|
261
|
+
};
|
|
262
|
+
for (const originalFileName of originalFileNames) bundledAssets.set(originalFileName, asset);
|
|
263
|
+
} else if (this.environment.name === envNames.edge || this.environment.name === envNames.node) bundledChunks.push(outFile);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
closeBundle: {
|
|
267
|
+
order: "post",
|
|
268
|
+
async handler() {
|
|
269
|
+
if (!isVercelLastBuildStep(this.environment, pluginConfig)) return;
|
|
270
|
+
this.environment.logger.info("Creating Vercel bundles...");
|
|
271
|
+
const outfiles = getVercelAPI(this).getOutFiles();
|
|
272
|
+
const filesToKeepP = [];
|
|
273
|
+
for (const outfile of outfiles) if (outfile.type === "chunk") filesToKeepP.push(bundle$1(this, bundledAssets, outfile));
|
|
274
|
+
await cleanup$1((await Promise.all(filesToKeepP)).flat(), bundledChunks);
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
sharedDuringBuild: true
|
|
278
|
+
}];
|
|
279
|
+
}
|
|
280
|
+
function getAbsoluteOutFile(outfile) {
|
|
281
|
+
const source = joinAbsolutePosix(outfile.root, outfile.outdir, outfile.filepath);
|
|
282
|
+
return {
|
|
283
|
+
source,
|
|
284
|
+
destination: source.replace(outfile.outdir, outfile.outdir)
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
async function bundle$1(pluginContext, bundledAssets, outfile) {
|
|
288
|
+
const output = [];
|
|
289
|
+
const { source, destination } = getAbsoluteOutFile(outfile);
|
|
290
|
+
const isEdge = Boolean(outfile.relatedEntry.vercel?.edge);
|
|
291
|
+
const { environment } = pluginContext;
|
|
292
|
+
const buildOptions = {};
|
|
293
|
+
buildOptions.output = {
|
|
294
|
+
format: "esm",
|
|
295
|
+
legalComments: "none",
|
|
296
|
+
codeSplitting: false
|
|
297
|
+
};
|
|
298
|
+
buildOptions.checks = { pluginTimings: false };
|
|
299
|
+
buildOptions.input = [source];
|
|
300
|
+
buildOptions.treeshake = true;
|
|
301
|
+
buildOptions.resolve ??= {};
|
|
302
|
+
if (isEdge) {
|
|
303
|
+
buildOptions.platform = "browser";
|
|
304
|
+
buildOptions.external = edgeExternal;
|
|
305
|
+
buildOptions.resolve.conditionNames = edgeConditions;
|
|
306
|
+
buildOptions.transform = { define: { "process.env.NODE_ENV": JSON.stringify("production") } };
|
|
307
|
+
buildOptions.output.file = destination.replace(/\.mjs$/, ".js");
|
|
308
|
+
buildOptions.plugins = [
|
|
309
|
+
edgeWasmPlugin,
|
|
310
|
+
dynamicNativeImportPlugin,
|
|
311
|
+
reactEdgePlugin$1
|
|
312
|
+
];
|
|
313
|
+
} else {
|
|
314
|
+
buildOptions.platform = "node";
|
|
315
|
+
buildOptions.output.file = destination.replace(/\.js$/, ".mjs");
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
await build(buildOptions);
|
|
319
|
+
output.push(buildOptions.output.file);
|
|
320
|
+
} catch (e) {
|
|
321
|
+
throw new Error(`Error while bundling ${destination}`, { cause: e });
|
|
322
|
+
}
|
|
323
|
+
let base = environment.config.root;
|
|
324
|
+
try {
|
|
325
|
+
base = (await findRoot(environment.config.root)).rootDir;
|
|
326
|
+
} catch (_e) {}
|
|
327
|
+
const resolvedEntryP = pluginContext.resolve(outfile.relatedEntry.id);
|
|
328
|
+
const entryFilePath = existsSync(outfile.relatedEntry.id) ? outfile.relatedEntry.id : (await resolvedEntryP)?.id && existsSync((await resolvedEntryP).id) ? (await resolvedEntryP).id : null;
|
|
329
|
+
if (entryFilePath === null) return [];
|
|
330
|
+
const { fileList, reasons } = await nodeFileTrace([entryFilePath], {
|
|
331
|
+
base,
|
|
332
|
+
processCwd: environment.config.root,
|
|
333
|
+
mixedModules: true,
|
|
334
|
+
ignore: [
|
|
335
|
+
"**/node_modules/react{,-dom,-dom-server-turbopack}/**/*.development.js",
|
|
336
|
+
"**/*.d.ts",
|
|
337
|
+
"**/*.map",
|
|
338
|
+
"**/node_modules/webpack5/**/*"
|
|
339
|
+
],
|
|
340
|
+
async readFile(filepath) {
|
|
341
|
+
const code = readFileSync(filepath, "utf-8");
|
|
342
|
+
if (filepath.endsWith(".ts") || filepath.endsWith(".tsx")) return (await transform(filepath, code, { target: "es2022" })).code;
|
|
343
|
+
return code;
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
for (const file of fileList) if (reasons.has(file) && reasons.get(file)?.type.includes("asset") && !file.endsWith(".js") && !file.endsWith(".cjs") && !file.endsWith(".mjs") && !file.endsWith("package.json")) {
|
|
347
|
+
const absolutePath = path.join(base, file);
|
|
348
|
+
const assetRenamedByVite = bundledAssets.get(absolutePath);
|
|
349
|
+
const basename = path.basename(assetRenamedByVite ? assetRenamedByVite.fileName : absolutePath);
|
|
350
|
+
if (assetRenamedByVite) writeFileSync(destination, readFileSync(destination, "utf-8").replaceAll(`/${assetRenamedByVite.fileName}`, `./${path.basename(assetRenamedByVite.fileName)}`));
|
|
351
|
+
const to = path.join(path.dirname(destination), basename);
|
|
352
|
+
output.push(to);
|
|
353
|
+
await copyFile(absolutePath, to);
|
|
354
|
+
}
|
|
355
|
+
return output;
|
|
356
|
+
}
|
|
357
|
+
function joinAbsolute(env_or_p0, p1, ...p) {
|
|
358
|
+
if (path.isAbsolute(p1)) return path.join(p1, ...p);
|
|
359
|
+
return path.join(typeof env_or_p0 === "string" ? env_or_p0 : env_or_p0.config.root, p1, ...p);
|
|
360
|
+
}
|
|
361
|
+
function joinAbsolutePosix(env_or_p0, p1, ...p) {
|
|
362
|
+
if (path.isAbsolute(p1)) return path.posix.join(p1, ...p);
|
|
363
|
+
return path.posix.join(typeof env_or_p0 === "string" ? env_or_p0 : env_or_p0.config.root, p1, ...p);
|
|
364
|
+
}
|
|
365
|
+
function isVercelLastBuildStep(env, pluginConfig) {
|
|
366
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
367
|
+
return (typeof env !== "string" ? env.name : env) === envNames.node;
|
|
368
|
+
}
|
|
369
|
+
async function cleanup$1(filesToKeep, bundledChunks) {
|
|
370
|
+
const toKeep = new Set(filesToKeep);
|
|
371
|
+
const removedFiles = [];
|
|
372
|
+
await Promise.all(bundledChunks.map(async (file) => {
|
|
373
|
+
if (!toKeep.has(file)) try {
|
|
374
|
+
await unlink(file);
|
|
375
|
+
removedFiles.push(file);
|
|
376
|
+
} catch {}
|
|
377
|
+
}));
|
|
378
|
+
const dirsToRemove = /* @__PURE__ */ new Set();
|
|
379
|
+
for (const file of removedFiles) {
|
|
380
|
+
let dir = path.dirname(file);
|
|
381
|
+
while (dir && dir !== "." && dir !== "/" && !toKeep.has(dir)) {
|
|
382
|
+
dirsToRemove.add(dir);
|
|
383
|
+
dir = path.dirname(dir);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
const sortedDirs = Array.from(dirsToRemove).sort((a, b) => b.length - a.length);
|
|
387
|
+
for (const dir of sortedDirs) try {
|
|
388
|
+
await rmdir(dir);
|
|
389
|
+
} catch {}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
//#endregion
|
|
393
|
+
//#region src/plugins/bundle/nf3.ts
|
|
394
|
+
function nf3BundlePlugin(pluginConfig) {
|
|
395
|
+
console.warn("[vite-plugin-vercel] bundleStrategy 'nf3' is highly experimental. Use at your own risk; support is not provided for related issues.");
|
|
396
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
113
397
|
const externalsPlugin = externals({});
|
|
114
398
|
delete externalsPlugin.buildEnd;
|
|
115
399
|
let buildOutput;
|
|
@@ -125,24 +409,31 @@ function bundlePlugin() {
|
|
|
125
409
|
return env.config.consumer !== "client";
|
|
126
410
|
},
|
|
127
411
|
async writeBundle(_, output) {
|
|
128
|
-
const isEdge = this.environment.name ===
|
|
412
|
+
const isEdge = this.environment.name === envNames.edge;
|
|
129
413
|
const config = this.environment.config;
|
|
130
|
-
const outDir
|
|
414
|
+
const outDir = normalizePath(path.isAbsolute(config.build.outDir) ? config.build.outDir : path.join(config.root, config.build.outDir));
|
|
131
415
|
const entries = Object.entries(output).filter((e) => "isEntry" in e[1] && e[1].isEntry).map((e) => ({
|
|
132
416
|
name: e[1].name,
|
|
133
417
|
fileName: e[1].fileName,
|
|
134
|
-
outPath: path.join(outDir
|
|
418
|
+
outPath: path.join(outDir, e[1].fileName)
|
|
135
419
|
}));
|
|
136
|
-
|
|
420
|
+
if (entries.length === 0) return;
|
|
137
421
|
const outPaths = entries.map((entry) => entry.outPath);
|
|
138
|
-
const input = Object.fromEntries(outPaths.map((e) => [removeExtension(pathRelativeTo(e, outDir
|
|
422
|
+
const input = Object.fromEntries(outPaths.map((e) => [removeExtension(pathRelativeTo(e, outDir)), e]));
|
|
139
423
|
const limit = pLimit(Math.max(1, Math.ceil(cpus().length / 2)));
|
|
424
|
+
const nonVitePlugins = this.environment.config.plugins.filter((p) => {
|
|
425
|
+
return !p.name.startsWith("vite:") && p.name !== "alias" && p.name !== "commonjs" && p.name !== "nitro:externals";
|
|
426
|
+
}).map((x) => {
|
|
427
|
+
const { buildStart, buildEnd, writeBundle, generateBundle, ...rest } = x;
|
|
428
|
+
return rest;
|
|
429
|
+
});
|
|
140
430
|
const localOutput = (await Promise.all(Object.values(input).map((entryPath) => limit(async () => {
|
|
141
|
-
const outDir
|
|
431
|
+
const outDir = path.dirname(entryPath);
|
|
142
432
|
return { output: (await bundle({
|
|
433
|
+
plugins: nonVitePlugins,
|
|
143
434
|
isEdge,
|
|
144
435
|
input: { index: entryPath },
|
|
145
|
-
outDir
|
|
436
|
+
outDir,
|
|
146
437
|
externals: {
|
|
147
438
|
conditions: this.environment.config.resolve.conditions,
|
|
148
439
|
rootDir: this.environment.config.root,
|
|
@@ -155,7 +446,7 @@ function bundlePlugin() {
|
|
|
155
446
|
}
|
|
156
447
|
})).output.map((o) => ({
|
|
157
448
|
...o,
|
|
158
|
-
fileName: path.join(outDir
|
|
449
|
+
fileName: path.join(outDir, o.fileName)
|
|
159
450
|
})) };
|
|
160
451
|
})))).flatMap((r) => r.output);
|
|
161
452
|
buildOutput = buildOutput ? [...buildOutput, ...localOutput] : localOutput;
|
|
@@ -169,7 +460,7 @@ function bundle(options) {
|
|
|
169
460
|
platform: options.isEdge ? "browser" : "node",
|
|
170
461
|
external: options.isEdge ? edgeExternal : [],
|
|
171
462
|
write: true,
|
|
172
|
-
plugins: [externals(options.externals)],
|
|
463
|
+
plugins: [...options.plugins, externals(options.externals)],
|
|
173
464
|
input: options.input,
|
|
174
465
|
resolve: { conditionNames: options.externals.conditions },
|
|
175
466
|
output: {
|
|
@@ -208,12 +499,13 @@ function removeExtension(subject) {
|
|
|
208
499
|
//#region src/plugins/clean-outdir.ts
|
|
209
500
|
function vercelCleanupPlugin(pluginConfig) {
|
|
210
501
|
let alreadyRun = false;
|
|
502
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
211
503
|
return {
|
|
212
504
|
apply: "build",
|
|
213
505
|
name: "vite-plugin-vercel:cleanup",
|
|
214
506
|
enforce: "pre",
|
|
215
507
|
applyToEnvironment(env) {
|
|
216
|
-
return env.name ===
|
|
508
|
+
return env.name === envNames.client;
|
|
217
509
|
},
|
|
218
510
|
buildStart: {
|
|
219
511
|
order: "pre",
|
|
@@ -251,10 +543,37 @@ function getVcConfig(pluginConfig, filename, options) {
|
|
|
251
543
|
});
|
|
252
544
|
}
|
|
253
545
|
|
|
546
|
+
//#endregion
|
|
547
|
+
//#region src/utils/request.ts
|
|
548
|
+
function getOriginalRequest(request) {
|
|
549
|
+
const xNowRouteMatchesHeader = request.headers.get("x-now-route-matches");
|
|
550
|
+
let newUrl = null;
|
|
551
|
+
let newRequest = request;
|
|
552
|
+
if (typeof xNowRouteMatchesHeader === "string") {
|
|
553
|
+
const originalPathBis = new URLSearchParams(xNowRouteMatchesHeader).get("1");
|
|
554
|
+
if (originalPathBis) newUrl = new URL(originalPathBis, request.url).toString();
|
|
555
|
+
}
|
|
556
|
+
if (newUrl) newRequest = new Request(newUrl, {
|
|
557
|
+
method: request.method,
|
|
558
|
+
headers: request.headers,
|
|
559
|
+
body: request.body,
|
|
560
|
+
mode: request.mode,
|
|
561
|
+
credentials: request.credentials,
|
|
562
|
+
cache: request.cache,
|
|
563
|
+
redirect: request.redirect,
|
|
564
|
+
referrer: request.referrer,
|
|
565
|
+
integrity: request.integrity
|
|
566
|
+
});
|
|
567
|
+
return newRequest;
|
|
568
|
+
}
|
|
569
|
+
|
|
254
570
|
//#endregion
|
|
255
571
|
//#region src/plugins/loader.ts
|
|
256
|
-
const re_DUMMY =
|
|
572
|
+
const re_DUMMY = new RegExp(`__DUMMY__$`);
|
|
573
|
+
const re_edge = /[?&]vercel_edge\b/;
|
|
574
|
+
const re_node = /[?&]vercel_node\b/;
|
|
257
575
|
function loaderPlugin(pluginConfig) {
|
|
576
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
258
577
|
let root;
|
|
259
578
|
return [
|
|
260
579
|
{
|
|
@@ -277,19 +596,57 @@ function loaderPlugin(pluginConfig) {
|
|
|
277
596
|
name: "vite-plugin-vercel:load-edge",
|
|
278
597
|
apply: "build",
|
|
279
598
|
resolveId: {
|
|
280
|
-
filter: { id:
|
|
599
|
+
filter: { id: re_edge },
|
|
600
|
+
async handler(id, importer, opts) {
|
|
601
|
+
const resolved = await this.resolve(id.replace(re_edge, ""), importer, opts);
|
|
602
|
+
if (!resolved) return null;
|
|
603
|
+
return `${resolved.id}?vercel_edge`;
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
load: {
|
|
607
|
+
filter: { id: re_edge },
|
|
608
|
+
async handler(id) {
|
|
609
|
+
const mod = id.replace(re_edge, "");
|
|
610
|
+
return `import mod from ${JSON.stringify(mod)};
|
|
611
|
+
|
|
612
|
+
${getOriginalRequest.toString()}
|
|
613
|
+
|
|
614
|
+
const fn = (r) => {
|
|
615
|
+
return mod.fetch(getOriginalRequest(r));
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
export default fn`;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
name: "vite-plugin-vercel:load-node",
|
|
624
|
+
apply: "build",
|
|
625
|
+
resolveId: {
|
|
626
|
+
filter: { id: re_node },
|
|
281
627
|
async handler(id, importer, opts) {
|
|
282
|
-
const resolved = await this.resolve(id.replace(
|
|
628
|
+
const resolved = await this.resolve(id.replace(re_node, ""), importer, opts);
|
|
283
629
|
if (!resolved) return null;
|
|
284
|
-
return `${resolved.id}?
|
|
630
|
+
return `${resolved.id}?vercel_node`;
|
|
285
631
|
}
|
|
286
632
|
},
|
|
287
633
|
load: {
|
|
288
|
-
filter: { id:
|
|
634
|
+
filter: { id: re_node },
|
|
289
635
|
async handler(id) {
|
|
290
|
-
const mod = id.replace(
|
|
636
|
+
const mod = id.replace(re_node, "");
|
|
291
637
|
return `import mod from ${JSON.stringify(mod)};
|
|
292
|
-
|
|
638
|
+
|
|
639
|
+
${getOriginalRequest.toString()}
|
|
640
|
+
|
|
641
|
+
if (mod?.fetch) {
|
|
642
|
+
const ori = mod.fetch;
|
|
643
|
+
mod.fetch = (r) => {
|
|
644
|
+
return ori(getOriginalRequest(r));
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const def = mod?.server?.nodeHandler ?? mod;
|
|
649
|
+
|
|
293
650
|
export default def;`;
|
|
294
651
|
}
|
|
295
652
|
}
|
|
@@ -298,7 +655,7 @@ export default def;`;
|
|
|
298
655
|
name: "vite-plugin-vercel:build-functions",
|
|
299
656
|
apply: "build",
|
|
300
657
|
applyToEnvironment(env) {
|
|
301
|
-
return env.name ===
|
|
658
|
+
return env.name === envNames.node || env.name === envNames.edge;
|
|
302
659
|
},
|
|
303
660
|
config: {
|
|
304
661
|
order: "post",
|
|
@@ -309,28 +666,30 @@ export default def;`;
|
|
|
309
666
|
configEnvironment: {
|
|
310
667
|
order: "post",
|
|
311
668
|
handler(name) {
|
|
312
|
-
const isEdge = name ===
|
|
313
|
-
if (name ===
|
|
669
|
+
const isEdge = name === envNames.edge;
|
|
670
|
+
if (name === envNames.node || isEdge) {
|
|
314
671
|
const entries = dedupeRoutes().filter((e) => (e.vercel?.edge ?? false) === isEdge);
|
|
315
672
|
return { build: { rollupOptions: {
|
|
316
|
-
input: Object.fromEntries(entries.map((e) => [entryDestination(root ?? process.cwd(), e, ".func/index"), isEdge ? `${e.id}?
|
|
317
|
-
output: {
|
|
673
|
+
input: Object.fromEntries(entries.map((e) => [entryDestination(root ?? process.cwd(), e, ".func/index"), isEdge ? `${e.id}?vercel_edge` : `${e.id}?vercel_node`])),
|
|
674
|
+
output: {
|
|
675
|
+
hoistTransitiveImports: false,
|
|
676
|
+
entryFileNames: "[name].js"
|
|
677
|
+
}
|
|
318
678
|
} } };
|
|
319
679
|
}
|
|
320
680
|
}
|
|
321
681
|
},
|
|
322
682
|
async buildStart() {
|
|
323
|
-
const isEdge = this.environment.name ===
|
|
683
|
+
const isEdge = this.environment.name === envNames.edge;
|
|
324
684
|
const nodeVersion = await getNodeVersion(process.cwd());
|
|
325
685
|
const entries = dedupeRoutes();
|
|
326
686
|
for (const entry of entries.filter((e) => (e.vercel?.edge ?? false) === isEdge)) {
|
|
327
|
-
const isEdge$1 = this.environment.name === "vercel_edge";
|
|
328
687
|
this.emitFile({
|
|
329
688
|
type: "asset",
|
|
330
689
|
fileName: entryDestination(root ?? process.cwd(), entry, ".func/.vc-config.json"),
|
|
331
|
-
source: JSON.stringify(getVcConfig(pluginConfig, isEdge
|
|
690
|
+
source: JSON.stringify(getVcConfig(pluginConfig, isEdge ? "index.js" : "index.mjs", {
|
|
332
691
|
nodeVersion,
|
|
333
|
-
edge: isEdge
|
|
692
|
+
edge: isEdge,
|
|
334
693
|
streaming: entry.vercel?.streaming
|
|
335
694
|
}), void 0, 2)
|
|
336
695
|
});
|
|
@@ -340,8 +699,8 @@ export default def;`;
|
|
|
340
699
|
source: JSON.stringify(vercelOutputPrerenderConfigSchema.parse(entry.vercel.isr), void 0, 2)
|
|
341
700
|
});
|
|
342
701
|
pluginConfig.rewrites ??= [];
|
|
343
|
-
for (const
|
|
344
|
-
const source = toPathToRegexpV6(
|
|
702
|
+
for (const ir of sortRoutes([entry.route].flat().map((p) => fromRou3(p)))) {
|
|
703
|
+
const source = toPathToRegexpV6(ir);
|
|
345
704
|
pluginConfig.rewrites.push({
|
|
346
705
|
enforce: entry.vercel?.enforce,
|
|
347
706
|
source,
|
|
@@ -367,11 +726,12 @@ export default def;`;
|
|
|
367
726
|
|
|
368
727
|
//#endregion
|
|
369
728
|
//#region src/plugins/react-edge.ts
|
|
370
|
-
function reactEdgePlugin() {
|
|
729
|
+
function reactEdgePlugin(pluginConfig) {
|
|
730
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
371
731
|
return {
|
|
372
732
|
name: "vite-plugin-vercel:react-edge",
|
|
373
733
|
applyToEnvironment(env) {
|
|
374
|
-
return env.name ===
|
|
734
|
+
return env.name === envNames.edge;
|
|
375
735
|
},
|
|
376
736
|
resolveId: {
|
|
377
737
|
order: "pre",
|
|
@@ -397,7 +757,10 @@ function getConfig(pluginConfig) {
|
|
|
397
757
|
const { routes, error } = getTransformedRoutes({
|
|
398
758
|
cleanUrls: pluginConfig.cleanUrls ?? true,
|
|
399
759
|
trailingSlash: pluginConfig.trailingSlash,
|
|
400
|
-
rewrites: reorderEnforce(_rewrites)
|
|
760
|
+
rewrites: reorderEnforce(_rewrites.map((r) => {
|
|
761
|
+
if (r.source === "/:_1*") r.source = "(.*)";
|
|
762
|
+
return r;
|
|
763
|
+
})),
|
|
401
764
|
redirects: pluginConfig.redirects ? reorderEnforce(pluginConfig.redirects) : void 0,
|
|
402
765
|
headers: pluginConfig.headers
|
|
403
766
|
});
|
|
@@ -423,6 +786,7 @@ function getConfig(pluginConfig) {
|
|
|
423
786
|
routes: buildRoutes
|
|
424
787
|
}]
|
|
425
788
|
});
|
|
789
|
+
for (const route of cleanRoutes) wrapRouteInParentheses(route);
|
|
426
790
|
return vercelOutputConfigSchema.parse({
|
|
427
791
|
version: 3,
|
|
428
792
|
...pluginConfig.config,
|
|
@@ -430,74 +794,73 @@ function getConfig(pluginConfig) {
|
|
|
430
794
|
overrides: { ...pluginConfig.config?.overrides }
|
|
431
795
|
});
|
|
432
796
|
}
|
|
797
|
+
function wrapRouteInParentheses(route) {
|
|
798
|
+
if (!route.src || !route.dest || route.src.match(/^\(.*\)$/) || route.src.match(/^\^\(.*\)\$$/)) return;
|
|
799
|
+
route.src = `(${route.src})`;
|
|
800
|
+
}
|
|
433
801
|
|
|
434
802
|
//#endregion
|
|
435
803
|
//#region src/utils/const.ts
|
|
436
804
|
const virtualEntry = "virtual:vite-plugin-vercel:entry";
|
|
437
805
|
|
|
438
|
-
//#endregion
|
|
439
|
-
//#region src/utils/edge.ts
|
|
440
|
-
const edgeConditions = [
|
|
441
|
-
"edge-light",
|
|
442
|
-
"worker",
|
|
443
|
-
"browser",
|
|
444
|
-
"module",
|
|
445
|
-
"import",
|
|
446
|
-
"default"
|
|
447
|
-
];
|
|
448
|
-
|
|
449
806
|
//#endregion
|
|
450
807
|
//#region src/plugins/setupEnvs.ts
|
|
451
808
|
const outDir = path.posix.join(process.cwd(), ".vercel/output");
|
|
452
809
|
const DUMMY = "__DUMMY__";
|
|
453
810
|
let injected = false;
|
|
454
811
|
function setupEnvs(pluginConfig) {
|
|
812
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
455
813
|
return [
|
|
456
814
|
{
|
|
457
815
|
name: "vite-plugin-vercel:setup-envs",
|
|
458
816
|
buildApp: {
|
|
459
817
|
order: "post",
|
|
460
818
|
async handler(builder) {
|
|
461
|
-
try {
|
|
462
|
-
await builder.build(builder.environments.
|
|
819
|
+
if (!builder.environments[envNames.client].isBuilt) try {
|
|
820
|
+
await builder.build(builder.environments[envNames.client]);
|
|
463
821
|
} catch (e) {
|
|
464
822
|
if (e instanceof Error && e.message.includes(`Could not resolve entry module "index.html"`)) {} else throw e;
|
|
465
823
|
}
|
|
466
|
-
await builder.build(builder.environments.
|
|
467
|
-
await builder.build(builder.environments.
|
|
824
|
+
if (envNames.edge !== false && !builder.environments[envNames.edge].isBuilt) await builder.build(builder.environments[envNames.edge]);
|
|
825
|
+
if (!builder.environments[envNames.node].isBuilt) await builder.build(builder.environments[envNames.node]);
|
|
468
826
|
}
|
|
469
827
|
},
|
|
470
|
-
config
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (
|
|
828
|
+
config: {
|
|
829
|
+
order: "post",
|
|
830
|
+
handler() {
|
|
831
|
+
if (!injected) {
|
|
832
|
+
injected = true;
|
|
833
|
+
if (pluginConfig.entries) pluginConfig.entries.forEach((entry) => {
|
|
834
|
+
addEntry(entry);
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
const outDirOverride = pluginConfig.outDir ? { build: { outDir: pluginConfig.outDir } } : {};
|
|
838
|
+
const environments = {};
|
|
839
|
+
if (envNames.client) environments[envNames.client] = {
|
|
840
|
+
build: {
|
|
841
|
+
outDir: path.join(pluginConfig.outDir ?? outDir, "static"),
|
|
842
|
+
copyPublicDir: true,
|
|
843
|
+
rollupOptions: { input: getDummyInput() }
|
|
844
|
+
},
|
|
845
|
+
consumer: "client"
|
|
846
|
+
};
|
|
847
|
+
if (envNames.edge) environments[envNames.edge] = createVercelEnvironmentOptions(outDirOverride);
|
|
848
|
+
if (envNames.node) environments[envNames.node] = createVercelEnvironmentOptions(outDirOverride);
|
|
849
|
+
return {
|
|
850
|
+
environments,
|
|
851
|
+
builder: {}
|
|
852
|
+
};
|
|
474
853
|
}
|
|
475
|
-
const outDirOverride = pluginConfig.outDir ? { build: { outDir: pluginConfig.outDir } } : {};
|
|
476
|
-
return {
|
|
477
|
-
environments: {
|
|
478
|
-
vercel_edge: createVercelEnvironmentOptions(outDirOverride),
|
|
479
|
-
vercel_node: createVercelEnvironmentOptions(outDirOverride),
|
|
480
|
-
vercel_client: {
|
|
481
|
-
build: {
|
|
482
|
-
outDir: path.join(pluginConfig.outDir ?? outDir, "static"),
|
|
483
|
-
copyPublicDir: true,
|
|
484
|
-
rollupOptions: { input: getDummyInput() }
|
|
485
|
-
},
|
|
486
|
-
consumer: "client"
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
|
-
builder: {}
|
|
490
|
-
};
|
|
491
854
|
},
|
|
492
855
|
sharedDuringBuild: true
|
|
493
856
|
},
|
|
494
857
|
{
|
|
495
858
|
name: "vite-plugin-vercel:setup-envs:vercel_edge",
|
|
496
859
|
applyToEnvironment(env) {
|
|
497
|
-
return env.name ===
|
|
860
|
+
return env.name === envNames.edge;
|
|
498
861
|
},
|
|
499
862
|
configEnvironment(name, config, env) {
|
|
500
|
-
if (name !==
|
|
863
|
+
if (name !== envNames.edge) return;
|
|
501
864
|
return {
|
|
502
865
|
resolve: {
|
|
503
866
|
external: edgeExternal,
|
|
@@ -524,8 +887,8 @@ function setupEnvs(pluginConfig) {
|
|
|
524
887
|
},
|
|
525
888
|
generateBundle: {
|
|
526
889
|
order: "post",
|
|
527
|
-
async handler(_opts, bundle
|
|
528
|
-
cleanupDummy(bundle
|
|
890
|
+
async handler(_opts, bundle) {
|
|
891
|
+
cleanupDummy(bundle);
|
|
529
892
|
}
|
|
530
893
|
},
|
|
531
894
|
sharedDuringBuild: true
|
|
@@ -533,16 +896,16 @@ function setupEnvs(pluginConfig) {
|
|
|
533
896
|
{
|
|
534
897
|
name: "vite-plugin-vercel:setup-envs:vercel_node",
|
|
535
898
|
applyToEnvironment(env) {
|
|
536
|
-
return env.name ===
|
|
899
|
+
return env.name === envNames.node;
|
|
537
900
|
},
|
|
538
901
|
configEnvironment(name, config) {
|
|
539
|
-
if (name !==
|
|
902
|
+
if (name !== envNames.node) return;
|
|
540
903
|
return { optimizeDeps: { ...config.optimizeDeps } };
|
|
541
904
|
},
|
|
542
905
|
generateBundle: {
|
|
543
906
|
order: "post",
|
|
544
|
-
async handler(_opts, bundle
|
|
545
|
-
cleanupDummy(bundle
|
|
907
|
+
async handler(_opts, bundle) {
|
|
908
|
+
cleanupDummy(bundle);
|
|
546
909
|
this.emitFile({
|
|
547
910
|
type: "asset",
|
|
548
911
|
fileName: "config.json",
|
|
@@ -555,10 +918,10 @@ function setupEnvs(pluginConfig) {
|
|
|
555
918
|
{
|
|
556
919
|
name: "vite-plugin-vercel:setup-envs:vercel_client",
|
|
557
920
|
applyToEnvironment(env) {
|
|
558
|
-
return env.name ===
|
|
921
|
+
return env.name === envNames.client;
|
|
559
922
|
},
|
|
560
|
-
generateBundle: { async handler(_opts, bundle
|
|
561
|
-
cleanupDummy(bundle
|
|
923
|
+
generateBundle: { async handler(_opts, bundle) {
|
|
924
|
+
cleanupDummy(bundle);
|
|
562
925
|
const topLevelConfig = this.environment.getTopLevelConfig();
|
|
563
926
|
const clientEnv = topLevelConfig.environments.client;
|
|
564
927
|
if (clientEnv) try {
|
|
@@ -589,7 +952,9 @@ function createVercelEnvironmentOptions(overrides) {
|
|
|
589
952
|
rollupOptions: {
|
|
590
953
|
input: getDummyInput(),
|
|
591
954
|
output: {
|
|
592
|
-
sanitizeFileName:
|
|
955
|
+
sanitizeFileName: (filename) => {
|
|
956
|
+
return filename.replace("\0", "_");
|
|
957
|
+
},
|
|
593
958
|
sourcemap: false
|
|
594
959
|
}
|
|
595
960
|
},
|
|
@@ -604,26 +969,25 @@ function createVercelEnvironmentOptions(overrides) {
|
|
|
604
969
|
function getDummyInput() {
|
|
605
970
|
return { [DUMMY]: `${virtualEntry}:${DUMMY}` };
|
|
606
971
|
}
|
|
607
|
-
function cleanupDummy(bundle
|
|
608
|
-
const dummy = Object.keys(bundle
|
|
609
|
-
if (dummy) delete bundle
|
|
972
|
+
function cleanupDummy(bundle) {
|
|
973
|
+
const dummy = Object.keys(bundle).find((key) => key.includes("_DUMMY_"));
|
|
974
|
+
if (dummy) delete bundle[dummy];
|
|
610
975
|
}
|
|
611
976
|
|
|
612
977
|
//#endregion
|
|
613
978
|
//#region src/plugins/index.ts
|
|
614
979
|
function vercel(pluginConfig = {}) {
|
|
615
980
|
return [
|
|
616
|
-
reactEdgePlugin(),
|
|
617
|
-
vercelCleanupPlugin(),
|
|
981
|
+
reactEdgePlugin(pluginConfig),
|
|
982
|
+
vercelCleanupPlugin(pluginConfig),
|
|
618
983
|
apiPlugin(pluginConfig),
|
|
619
984
|
...setupEnvs(pluginConfig),
|
|
620
985
|
...loaderPlugin(pluginConfig),
|
|
621
|
-
...
|
|
986
|
+
...pluginConfig?.bundleStrategy === "nf3" ? nf3BundlePlugin(pluginConfig) : basicBundlePlugin(pluginConfig),
|
|
622
987
|
catchAll(),
|
|
623
988
|
devServer()
|
|
624
989
|
];
|
|
625
990
|
}
|
|
626
|
-
var plugins_default = vercel;
|
|
627
991
|
|
|
628
992
|
//#endregion
|
|
629
|
-
export {
|
|
993
|
+
export { vercel as default, vercel };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-vercel",
|
|
3
|
-
"version": "11.0.0-beta.
|
|
3
|
+
"version": "11.0.0-beta.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -26,29 +26,30 @@
|
|
|
26
26
|
"@types/node": "^22.19.3",
|
|
27
27
|
"@universal-middleware/express": "^0.4.22",
|
|
28
28
|
"@vercel/node": "^5.5.15",
|
|
29
|
-
"tsdown": "^0.
|
|
29
|
+
"tsdown": "^0.20.3",
|
|
30
30
|
"typescript": "^5.9.3",
|
|
31
31
|
"vite": "^7.2.4",
|
|
32
32
|
"vitest": "^4.0.16"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@manypkg/find-root": "^3.1.0",
|
|
36
|
-
"@universal-deploy/store": "^0.
|
|
36
|
+
"@universal-deploy/store": "^0.1.3",
|
|
37
37
|
"@universal-middleware/core": "^0.4.13",
|
|
38
38
|
"@universal-middleware/vercel": "^0.4.29",
|
|
39
39
|
"@vercel/build-utils": "^13.2.3",
|
|
40
|
-
"@vercel/nft": "^1.
|
|
40
|
+
"@vercel/nft": "^1.2.0",
|
|
41
41
|
"@vercel/routing-utils": "^5.3.1",
|
|
42
|
-
"@vite-plugin-vercel/schemas": "latest",
|
|
43
42
|
"convert-route": "^1.0.0",
|
|
44
43
|
"fast-glob": "^3.3.3",
|
|
45
44
|
"magicast": "^0.5.1",
|
|
46
|
-
"nf3": "^0.3.
|
|
45
|
+
"nf3": "^0.3.4",
|
|
46
|
+
"oxc-transform": "^0.108.0",
|
|
47
47
|
"p-limit": "^7.2.0",
|
|
48
48
|
"path-to-regexp": "^8.3.0",
|
|
49
|
-
"rolldown": "^1.0.0-
|
|
49
|
+
"rolldown": "^1.0.0-rc.4",
|
|
50
50
|
"strip-ansi": "^7.1.2",
|
|
51
|
-
"vite-plugin-wasm": "^3.5.0"
|
|
51
|
+
"vite-plugin-wasm": "^3.5.0",
|
|
52
|
+
"@vite-plugin-vercel/schemas": "^1.0.0"
|
|
52
53
|
},
|
|
53
54
|
"scripts": {
|
|
54
55
|
"dev": "tsdown --watch",
|
package/dist/api-DR2y7JVQ.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
//#region src/utils/assert.ts
|
|
2
|
-
function assert(condition, errorMessage) {
|
|
3
|
-
if (condition) return;
|
|
4
|
-
throw new Error(`[vite-plugin-vercel] ${errorMessage}`);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region src/api.ts
|
|
9
|
-
function createAPI(outfiles, pluginConfig) {
|
|
10
|
-
return {
|
|
11
|
-
getOutFiles() {
|
|
12
|
-
return outfiles;
|
|
13
|
-
},
|
|
14
|
-
get config() {
|
|
15
|
-
pluginConfig.config ??= {};
|
|
16
|
-
return pluginConfig.config;
|
|
17
|
-
},
|
|
18
|
-
get defaultMaxDuration() {
|
|
19
|
-
return pluginConfig.defaultMaxDuration;
|
|
20
|
-
},
|
|
21
|
-
set defaultMaxDuration(value) {
|
|
22
|
-
pluginConfig.defaultMaxDuration = value;
|
|
23
|
-
},
|
|
24
|
-
get expiration() {
|
|
25
|
-
return pluginConfig.expiration;
|
|
26
|
-
},
|
|
27
|
-
set expiration(value) {
|
|
28
|
-
pluginConfig.expiration = value;
|
|
29
|
-
},
|
|
30
|
-
get rewrites() {
|
|
31
|
-
pluginConfig.rewrites ??= [];
|
|
32
|
-
return pluginConfig.rewrites;
|
|
33
|
-
},
|
|
34
|
-
get headers() {
|
|
35
|
-
pluginConfig.headers ??= [];
|
|
36
|
-
return pluginConfig.headers;
|
|
37
|
-
},
|
|
38
|
-
get redirects() {
|
|
39
|
-
pluginConfig.redirects ??= [];
|
|
40
|
-
return pluginConfig.redirects;
|
|
41
|
-
},
|
|
42
|
-
get cleanUrls() {
|
|
43
|
-
return pluginConfig.cleanUrls;
|
|
44
|
-
},
|
|
45
|
-
set cleanUrls(value) {
|
|
46
|
-
pluginConfig.cleanUrls = value;
|
|
47
|
-
},
|
|
48
|
-
get trailingSlash() {
|
|
49
|
-
return pluginConfig.trailingSlash;
|
|
50
|
-
},
|
|
51
|
-
set trailingSlash(value) {
|
|
52
|
-
pluginConfig.trailingSlash = value;
|
|
53
|
-
},
|
|
54
|
-
get defaultSupportsResponseStreaming() {
|
|
55
|
-
return pluginConfig.defaultSupportsResponseStreaming;
|
|
56
|
-
},
|
|
57
|
-
set defaultSupportsResponseStreaming(value) {
|
|
58
|
-
pluginConfig.defaultSupportsResponseStreaming = value;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function getVercelAPI(pluginContextOrServer) {
|
|
63
|
-
const vpv = ("environment" in pluginContextOrServer ? pluginContextOrServer.environment.config : pluginContextOrServer.config).plugins.find((p) => p.name === "vite-plugin-vercel:api");
|
|
64
|
-
assert(vpv, "Could not find vite-plugin-vercel:api plugin");
|
|
65
|
-
assert(vpv.api, "Missing `api`. Make sure vite-plugin-vercel is up-to-date");
|
|
66
|
-
return vpv.api("environment" in pluginContextOrServer ? pluginContextOrServer : void 0);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
//#endregion
|
|
70
|
-
export { getVercelAPI as n, assert as r, createAPI as t };
|
|
File without changes
|