vite-plugin-vercel 11.0.0-beta.2 → 11.0.0-beta.21
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 +466 -104
- 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,34 @@ 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 xOriginalPath = request.headers.get("x-original-path");
|
|
550
|
+
let newUrl = null;
|
|
551
|
+
let newRequest = request;
|
|
552
|
+
if (typeof xOriginalPath === "string") newUrl = new URL(xOriginalPath, request.url).toString();
|
|
553
|
+
if (newUrl && request.url !== newUrl) newRequest = new Request(newUrl, {
|
|
554
|
+
method: request.method,
|
|
555
|
+
headers: request.headers,
|
|
556
|
+
body: request.body,
|
|
557
|
+
mode: request.mode,
|
|
558
|
+
credentials: request.credentials,
|
|
559
|
+
cache: request.cache,
|
|
560
|
+
redirect: request.redirect,
|
|
561
|
+
referrer: request.referrer,
|
|
562
|
+
integrity: request.integrity
|
|
563
|
+
});
|
|
564
|
+
return newRequest;
|
|
565
|
+
}
|
|
566
|
+
|
|
254
567
|
//#endregion
|
|
255
568
|
//#region src/plugins/loader.ts
|
|
256
|
-
const re_DUMMY =
|
|
569
|
+
const re_DUMMY = new RegExp(`__DUMMY__$`);
|
|
570
|
+
const re_edge = /[?&]vercel_edge\b/;
|
|
571
|
+
const re_node = /[?&]vercel_node\b/;
|
|
257
572
|
function loaderPlugin(pluginConfig) {
|
|
573
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
258
574
|
let root;
|
|
259
575
|
return [
|
|
260
576
|
{
|
|
@@ -277,19 +593,57 @@ function loaderPlugin(pluginConfig) {
|
|
|
277
593
|
name: "vite-plugin-vercel:load-edge",
|
|
278
594
|
apply: "build",
|
|
279
595
|
resolveId: {
|
|
280
|
-
filter: { id:
|
|
596
|
+
filter: { id: re_edge },
|
|
281
597
|
async handler(id, importer, opts) {
|
|
282
|
-
const resolved = await this.resolve(id.replace(
|
|
598
|
+
const resolved = await this.resolve(id.replace(re_edge, ""), importer, opts);
|
|
283
599
|
if (!resolved) return null;
|
|
284
|
-
return `${resolved.id}?
|
|
600
|
+
return `${resolved.id}?vercel_edge`;
|
|
285
601
|
}
|
|
286
602
|
},
|
|
287
603
|
load: {
|
|
288
|
-
filter: { id:
|
|
604
|
+
filter: { id: re_edge },
|
|
289
605
|
async handler(id) {
|
|
290
|
-
const mod = id.replace(
|
|
606
|
+
const mod = id.replace(re_edge, "");
|
|
291
607
|
return `import mod from ${JSON.stringify(mod)};
|
|
292
|
-
|
|
608
|
+
|
|
609
|
+
${getOriginalRequest.toString()}
|
|
610
|
+
|
|
611
|
+
const fn = (r) => {
|
|
612
|
+
return mod.fetch(getOriginalRequest(r));
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
export default fn`;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
name: "vite-plugin-vercel:load-node",
|
|
621
|
+
apply: "build",
|
|
622
|
+
resolveId: {
|
|
623
|
+
filter: { id: re_node },
|
|
624
|
+
async handler(id, importer, opts) {
|
|
625
|
+
const resolved = await this.resolve(id.replace(re_node, ""), importer, opts);
|
|
626
|
+
if (!resolved) return null;
|
|
627
|
+
return `${resolved.id}?vercel_node`;
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
load: {
|
|
631
|
+
filter: { id: re_node },
|
|
632
|
+
async handler(id) {
|
|
633
|
+
const mod = id.replace(re_node, "");
|
|
634
|
+
return `import mod from ${JSON.stringify(mod)};
|
|
635
|
+
|
|
636
|
+
${getOriginalRequest.toString()}
|
|
637
|
+
|
|
638
|
+
if (mod?.fetch) {
|
|
639
|
+
const ori = mod.fetch;
|
|
640
|
+
mod.fetch = (r) => {
|
|
641
|
+
return ori(getOriginalRequest(r));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
const def = mod?.server?.nodeHandler ?? mod;
|
|
646
|
+
|
|
293
647
|
export default def;`;
|
|
294
648
|
}
|
|
295
649
|
}
|
|
@@ -298,7 +652,7 @@ export default def;`;
|
|
|
298
652
|
name: "vite-plugin-vercel:build-functions",
|
|
299
653
|
apply: "build",
|
|
300
654
|
applyToEnvironment(env) {
|
|
301
|
-
return env.name ===
|
|
655
|
+
return env.name === envNames.node || env.name === envNames.edge;
|
|
302
656
|
},
|
|
303
657
|
config: {
|
|
304
658
|
order: "post",
|
|
@@ -309,28 +663,30 @@ export default def;`;
|
|
|
309
663
|
configEnvironment: {
|
|
310
664
|
order: "post",
|
|
311
665
|
handler(name) {
|
|
312
|
-
const isEdge = name ===
|
|
313
|
-
if (name ===
|
|
666
|
+
const isEdge = name === envNames.edge;
|
|
667
|
+
if (name === envNames.node || isEdge) {
|
|
314
668
|
const entries = dedupeRoutes().filter((e) => (e.vercel?.edge ?? false) === isEdge);
|
|
315
669
|
return { build: { rollupOptions: {
|
|
316
|
-
input: Object.fromEntries(entries.map((e) => [entryDestination(root ?? process.cwd(), e, ".func/index"), isEdge ? `${e.id}?
|
|
317
|
-
output: {
|
|
670
|
+
input: Object.fromEntries(entries.map((e) => [entryDestination(root ?? process.cwd(), e, ".func/index"), isEdge ? `${e.id}?vercel_edge` : `${e.id}?vercel_node`])),
|
|
671
|
+
output: {
|
|
672
|
+
hoistTransitiveImports: false,
|
|
673
|
+
entryFileNames: "[name].js"
|
|
674
|
+
}
|
|
318
675
|
} } };
|
|
319
676
|
}
|
|
320
677
|
}
|
|
321
678
|
},
|
|
322
679
|
async buildStart() {
|
|
323
|
-
const isEdge = this.environment.name ===
|
|
680
|
+
const isEdge = this.environment.name === envNames.edge;
|
|
324
681
|
const nodeVersion = await getNodeVersion(process.cwd());
|
|
325
682
|
const entries = dedupeRoutes();
|
|
326
683
|
for (const entry of entries.filter((e) => (e.vercel?.edge ?? false) === isEdge)) {
|
|
327
|
-
const isEdge$1 = this.environment.name === "vercel_edge";
|
|
328
684
|
this.emitFile({
|
|
329
685
|
type: "asset",
|
|
330
686
|
fileName: entryDestination(root ?? process.cwd(), entry, ".func/.vc-config.json"),
|
|
331
|
-
source: JSON.stringify(getVcConfig(pluginConfig, isEdge
|
|
687
|
+
source: JSON.stringify(getVcConfig(pluginConfig, isEdge ? "index.js" : "index.mjs", {
|
|
332
688
|
nodeVersion,
|
|
333
|
-
edge: isEdge
|
|
689
|
+
edge: isEdge,
|
|
334
690
|
streaming: entry.vercel?.streaming
|
|
335
691
|
}), void 0, 2)
|
|
336
692
|
});
|
|
@@ -340,8 +696,8 @@ export default def;`;
|
|
|
340
696
|
source: JSON.stringify(vercelOutputPrerenderConfigSchema.parse(entry.vercel.isr), void 0, 2)
|
|
341
697
|
});
|
|
342
698
|
pluginConfig.rewrites ??= [];
|
|
343
|
-
for (const
|
|
344
|
-
const source = toPathToRegexpV6(
|
|
699
|
+
for (const ir of sortRoutes([entry.route].flat().map((p) => fromRou3(p)))) {
|
|
700
|
+
const source = toPathToRegexpV6(ir);
|
|
345
701
|
pluginConfig.rewrites.push({
|
|
346
702
|
enforce: entry.vercel?.enforce,
|
|
347
703
|
source,
|
|
@@ -367,11 +723,12 @@ export default def;`;
|
|
|
367
723
|
|
|
368
724
|
//#endregion
|
|
369
725
|
//#region src/plugins/react-edge.ts
|
|
370
|
-
function reactEdgePlugin() {
|
|
726
|
+
function reactEdgePlugin(pluginConfig) {
|
|
727
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
371
728
|
return {
|
|
372
729
|
name: "vite-plugin-vercel:react-edge",
|
|
373
730
|
applyToEnvironment(env) {
|
|
374
|
-
return env.name ===
|
|
731
|
+
return env.name === envNames.edge;
|
|
375
732
|
},
|
|
376
733
|
resolveId: {
|
|
377
734
|
order: "pre",
|
|
@@ -397,9 +754,18 @@ function getConfig(pluginConfig) {
|
|
|
397
754
|
const { routes, error } = getTransformedRoutes({
|
|
398
755
|
cleanUrls: pluginConfig.cleanUrls ?? true,
|
|
399
756
|
trailingSlash: pluginConfig.trailingSlash,
|
|
400
|
-
rewrites: reorderEnforce(_rewrites)
|
|
757
|
+
rewrites: reorderEnforce(_rewrites.map((r) => {
|
|
758
|
+
if (r.source === "/:_1*") r.source = "(.*)";
|
|
759
|
+
return r;
|
|
760
|
+
})),
|
|
401
761
|
redirects: pluginConfig.redirects ? reorderEnforce(pluginConfig.redirects) : void 0,
|
|
402
|
-
headers:
|
|
762
|
+
headers: [{
|
|
763
|
+
source: "/(.*)",
|
|
764
|
+
headers: [{
|
|
765
|
+
key: "x-original-path",
|
|
766
|
+
value: "/$1"
|
|
767
|
+
}]
|
|
768
|
+
}, ...pluginConfig.headers ?? []]
|
|
403
769
|
});
|
|
404
770
|
if (error) throw error;
|
|
405
771
|
if (pluginConfig.config?.routes && pluginConfig.config.routes.length > 0 && !pluginConfig.config.routes.every((r) => "continue" in r && r.continue)) console.warn("Did you forget to add `\"continue\": true` to your routes? See https://vercel.com/docs/build-output-api/v3/configuration#source-route\nIf not, it is discouraged to use `routes` config to override routes. Prefer using `rewrites` and `redirects`.");
|
|
@@ -435,69 +801,64 @@ function getConfig(pluginConfig) {
|
|
|
435
801
|
//#region src/utils/const.ts
|
|
436
802
|
const virtualEntry = "virtual:vite-plugin-vercel:entry";
|
|
437
803
|
|
|
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
804
|
//#endregion
|
|
450
805
|
//#region src/plugins/setupEnvs.ts
|
|
451
806
|
const outDir = path.posix.join(process.cwd(), ".vercel/output");
|
|
452
807
|
const DUMMY = "__DUMMY__";
|
|
453
808
|
let injected = false;
|
|
454
809
|
function setupEnvs(pluginConfig) {
|
|
810
|
+
const envNames = getBuildEnvNames(pluginConfig);
|
|
455
811
|
return [
|
|
456
812
|
{
|
|
457
813
|
name: "vite-plugin-vercel:setup-envs",
|
|
458
814
|
buildApp: {
|
|
459
815
|
order: "post",
|
|
460
816
|
async handler(builder) {
|
|
461
|
-
try {
|
|
462
|
-
await builder.build(builder.environments.
|
|
817
|
+
if (!builder.environments[envNames.client].isBuilt) try {
|
|
818
|
+
await builder.build(builder.environments[envNames.client]);
|
|
463
819
|
} catch (e) {
|
|
464
820
|
if (e instanceof Error && e.message.includes(`Could not resolve entry module "index.html"`)) {} else throw e;
|
|
465
821
|
}
|
|
466
|
-
await builder.build(builder.environments.
|
|
467
|
-
await builder.build(builder.environments.
|
|
822
|
+
if (envNames.edge !== false && !builder.environments[envNames.edge].isBuilt) await builder.build(builder.environments[envNames.edge]);
|
|
823
|
+
if (!builder.environments[envNames.node].isBuilt) await builder.build(builder.environments[envNames.node]);
|
|
468
824
|
}
|
|
469
825
|
},
|
|
470
|
-
config
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (
|
|
826
|
+
config: {
|
|
827
|
+
order: "post",
|
|
828
|
+
handler() {
|
|
829
|
+
if (!injected) {
|
|
830
|
+
injected = true;
|
|
831
|
+
if (pluginConfig.entries) pluginConfig.entries.forEach((entry) => {
|
|
832
|
+
addEntry(entry);
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
const outDirOverride = pluginConfig.outDir ? { build: { outDir: pluginConfig.outDir } } : {};
|
|
836
|
+
const environments = {};
|
|
837
|
+
if (envNames.client) environments[envNames.client] = {
|
|
838
|
+
build: {
|
|
839
|
+
outDir: path.join(pluginConfig.outDir ?? outDir, "static"),
|
|
840
|
+
copyPublicDir: true,
|
|
841
|
+
rollupOptions: { input: getDummyInput() }
|
|
842
|
+
},
|
|
843
|
+
consumer: "client"
|
|
844
|
+
};
|
|
845
|
+
if (envNames.edge) environments[envNames.edge] = createVercelEnvironmentOptions(outDirOverride);
|
|
846
|
+
if (envNames.node) environments[envNames.node] = createVercelEnvironmentOptions(outDirOverride);
|
|
847
|
+
return {
|
|
848
|
+
environments,
|
|
849
|
+
builder: {}
|
|
850
|
+
};
|
|
474
851
|
}
|
|
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
852
|
},
|
|
492
853
|
sharedDuringBuild: true
|
|
493
854
|
},
|
|
494
855
|
{
|
|
495
856
|
name: "vite-plugin-vercel:setup-envs:vercel_edge",
|
|
496
857
|
applyToEnvironment(env) {
|
|
497
|
-
return env.name ===
|
|
858
|
+
return env.name === envNames.edge;
|
|
498
859
|
},
|
|
499
860
|
configEnvironment(name, config, env) {
|
|
500
|
-
if (name !==
|
|
861
|
+
if (name !== envNames.edge) return;
|
|
501
862
|
return {
|
|
502
863
|
resolve: {
|
|
503
864
|
external: edgeExternal,
|
|
@@ -524,8 +885,8 @@ function setupEnvs(pluginConfig) {
|
|
|
524
885
|
},
|
|
525
886
|
generateBundle: {
|
|
526
887
|
order: "post",
|
|
527
|
-
async handler(_opts, bundle
|
|
528
|
-
cleanupDummy(bundle
|
|
888
|
+
async handler(_opts, bundle) {
|
|
889
|
+
cleanupDummy(bundle);
|
|
529
890
|
}
|
|
530
891
|
},
|
|
531
892
|
sharedDuringBuild: true
|
|
@@ -533,16 +894,16 @@ function setupEnvs(pluginConfig) {
|
|
|
533
894
|
{
|
|
534
895
|
name: "vite-plugin-vercel:setup-envs:vercel_node",
|
|
535
896
|
applyToEnvironment(env) {
|
|
536
|
-
return env.name ===
|
|
897
|
+
return env.name === envNames.node;
|
|
537
898
|
},
|
|
538
899
|
configEnvironment(name, config) {
|
|
539
|
-
if (name !==
|
|
900
|
+
if (name !== envNames.node) return;
|
|
540
901
|
return { optimizeDeps: { ...config.optimizeDeps } };
|
|
541
902
|
},
|
|
542
903
|
generateBundle: {
|
|
543
904
|
order: "post",
|
|
544
|
-
async handler(_opts, bundle
|
|
545
|
-
cleanupDummy(bundle
|
|
905
|
+
async handler(_opts, bundle) {
|
|
906
|
+
cleanupDummy(bundle);
|
|
546
907
|
this.emitFile({
|
|
547
908
|
type: "asset",
|
|
548
909
|
fileName: "config.json",
|
|
@@ -555,10 +916,10 @@ function setupEnvs(pluginConfig) {
|
|
|
555
916
|
{
|
|
556
917
|
name: "vite-plugin-vercel:setup-envs:vercel_client",
|
|
557
918
|
applyToEnvironment(env) {
|
|
558
|
-
return env.name ===
|
|
919
|
+
return env.name === envNames.client;
|
|
559
920
|
},
|
|
560
|
-
generateBundle: { async handler(_opts, bundle
|
|
561
|
-
cleanupDummy(bundle
|
|
921
|
+
generateBundle: { async handler(_opts, bundle) {
|
|
922
|
+
cleanupDummy(bundle);
|
|
562
923
|
const topLevelConfig = this.environment.getTopLevelConfig();
|
|
563
924
|
const clientEnv = topLevelConfig.environments.client;
|
|
564
925
|
if (clientEnv) try {
|
|
@@ -589,7 +950,9 @@ function createVercelEnvironmentOptions(overrides) {
|
|
|
589
950
|
rollupOptions: {
|
|
590
951
|
input: getDummyInput(),
|
|
591
952
|
output: {
|
|
592
|
-
sanitizeFileName:
|
|
953
|
+
sanitizeFileName: (filename) => {
|
|
954
|
+
return filename.replace("\0", "_");
|
|
955
|
+
},
|
|
593
956
|
sourcemap: false
|
|
594
957
|
}
|
|
595
958
|
},
|
|
@@ -604,26 +967,25 @@ function createVercelEnvironmentOptions(overrides) {
|
|
|
604
967
|
function getDummyInput() {
|
|
605
968
|
return { [DUMMY]: `${virtualEntry}:${DUMMY}` };
|
|
606
969
|
}
|
|
607
|
-
function cleanupDummy(bundle
|
|
608
|
-
const dummy = Object.keys(bundle
|
|
609
|
-
if (dummy) delete bundle
|
|
970
|
+
function cleanupDummy(bundle) {
|
|
971
|
+
const dummy = Object.keys(bundle).find((key) => key.includes("_DUMMY_"));
|
|
972
|
+
if (dummy) delete bundle[dummy];
|
|
610
973
|
}
|
|
611
974
|
|
|
612
975
|
//#endregion
|
|
613
976
|
//#region src/plugins/index.ts
|
|
614
977
|
function vercel(pluginConfig = {}) {
|
|
615
978
|
return [
|
|
616
|
-
reactEdgePlugin(),
|
|
617
|
-
vercelCleanupPlugin(),
|
|
979
|
+
reactEdgePlugin(pluginConfig),
|
|
980
|
+
vercelCleanupPlugin(pluginConfig),
|
|
618
981
|
apiPlugin(pluginConfig),
|
|
619
982
|
...setupEnvs(pluginConfig),
|
|
620
983
|
...loaderPlugin(pluginConfig),
|
|
621
|
-
...
|
|
984
|
+
...pluginConfig?.bundleStrategy === "nf3" ? nf3BundlePlugin(pluginConfig) : basicBundlePlugin(pluginConfig),
|
|
622
985
|
catchAll(),
|
|
623
986
|
devServer()
|
|
624
987
|
];
|
|
625
988
|
}
|
|
626
|
-
var plugins_default = vercel;
|
|
627
989
|
|
|
628
990
|
//#endregion
|
|
629
|
-
export {
|
|
991
|
+
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.21",
|
|
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
|