next-bun-compile 0.2.2 → 0.4.0
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 +12 -0
- package/dist/cli.js +34 -6
- package/dist/compile.js +3 -2
- package/dist/generate.js +29 -3
- package/dist/index.js +32 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,18 @@ bun run build # Builds Next.js + compiles to ./server
|
|
|
54
54
|
|
|
55
55
|
The binary is fully self-contained — static assets, public files, and the Next.js server are all embedded. Just copy it anywhere and run.
|
|
56
56
|
|
|
57
|
+
### Cross-Compilation
|
|
58
|
+
|
|
59
|
+
Any flags passed to `next-bun-compile` are forwarded to `bun build --compile`. Use `--target` to cross-compile for a different platform:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
next-bun-compile --target=bun-linux-x64
|
|
63
|
+
next-bun-compile --target=bun-linux-arm64
|
|
64
|
+
next-bun-compile --target=bun-windows-x64
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
See the [Bun cross-compilation docs](https://bun.sh/docs/bundler/executables#cross-compile) for all available targets.
|
|
68
|
+
|
|
57
69
|
### Environment Variables
|
|
58
70
|
|
|
59
71
|
| Variable | Default | Description |
|
package/dist/cli.js
CHANGED
|
@@ -67,9 +67,23 @@ function generateStubs(standaloneDir) {
|
|
|
67
67
|
console.log(`next-bun-compile: Created ${count} module stubs`);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
function patchRequireHook(standaloneDir) {
|
|
71
|
+
const hookPath = join(standaloneDir, "node_modules/next/dist/server/require-hook.js");
|
|
72
|
+
if (!existsSync(hookPath))
|
|
73
|
+
return;
|
|
74
|
+
let content = readFileSync(hookPath, "utf-8");
|
|
75
|
+
const target = "let resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;";
|
|
76
|
+
if (!content.includes(target))
|
|
77
|
+
return;
|
|
78
|
+
content = content.replace(target, `let _resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;
|
|
79
|
+
let resolve = (id) => { try { return _resolve(id); } catch { return ''; } };`);
|
|
80
|
+
writeFileSync(hookPath, content);
|
|
81
|
+
console.log("next-bun-compile: Patched require-hook.js for compiled binary compatibility");
|
|
82
|
+
}
|
|
70
83
|
function generateEntryPoint(options) {
|
|
71
84
|
const { standaloneDir, distDir, projectDir } = options;
|
|
72
85
|
generateStubs(standaloneDir);
|
|
86
|
+
patchRequireHook(standaloneDir);
|
|
73
87
|
const staticDir = join(distDir, "static");
|
|
74
88
|
const staticFiles = walkDir(staticDir).map((f) => ({
|
|
75
89
|
...f,
|
|
@@ -80,13 +94,18 @@ function generateEntryPoint(options) {
|
|
|
80
94
|
...f,
|
|
81
95
|
urlPath: `/${f.relativePath.replace(/\\/g, "/")}`
|
|
82
96
|
}));
|
|
97
|
+
const standaloneNextDir = join(standaloneDir, ".next");
|
|
98
|
+
const runtimeFiles = walkDir(standaloneNextDir).map((f) => ({
|
|
99
|
+
...f,
|
|
100
|
+
urlPath: `__runtime/.next/${f.relativePath.replace(/\\/g, "/")}`
|
|
101
|
+
}));
|
|
83
102
|
const ctx = JSON.parse(readFileSync(join(distDir, "bun-compile-ctx.json"), "utf-8"));
|
|
84
103
|
const { assetPrefix } = ctx;
|
|
85
|
-
const assetsToEmbed = assetPrefix ? publicFiles : [...staticFiles, ...publicFiles];
|
|
104
|
+
const assetsToEmbed = assetPrefix ? [...publicFiles, ...runtimeFiles] : [...staticFiles, ...publicFiles, ...runtimeFiles];
|
|
86
105
|
if (assetPrefix) {
|
|
87
106
|
console.log(`next-bun-compile: assetPrefix detected — skipping ${staticFiles.length} static assets (served from CDN)`);
|
|
88
107
|
}
|
|
89
|
-
console.log(`next-bun-compile: Embedding ${assetsToEmbed.length} assets (${
|
|
108
|
+
console.log(`next-bun-compile: Embedding ${assetsToEmbed.length} assets (${staticFiles.length} static + ${publicFiles.length} public + ${runtimeFiles.length} runtime)`);
|
|
90
109
|
const imports = [];
|
|
91
110
|
const mapEntries = [];
|
|
92
111
|
for (const asset of assetsToEmbed) {
|
|
@@ -108,7 +127,14 @@ ${mapEntries.join(`
|
|
|
108
127
|
throw new Error("next-bun-compile: Could not extract nextConfig from standalone server.js");
|
|
109
128
|
}
|
|
110
129
|
const assetExtractions = assetsToEmbed.map((a) => {
|
|
111
|
-
|
|
130
|
+
let diskPath;
|
|
131
|
+
if (a.urlPath.startsWith("__runtime/")) {
|
|
132
|
+
diskPath = a.urlPath.slice("__runtime/".length);
|
|
133
|
+
} else if (a.urlPath.startsWith("/_next/static/")) {
|
|
134
|
+
diskPath = ".next/static/" + a.relativePath;
|
|
135
|
+
} else {
|
|
136
|
+
diskPath = "public/" + a.relativePath;
|
|
137
|
+
}
|
|
112
138
|
return [a.urlPath, diskPath];
|
|
113
139
|
});
|
|
114
140
|
const serverEntry = `import { assetMap } from "./assets.generated.js";
|
|
@@ -158,7 +184,7 @@ extractAssets().then(() => {
|
|
|
158
184
|
import { execFileSync } from "node:child_process";
|
|
159
185
|
import { join as join2 } from "node:path";
|
|
160
186
|
function compile(options) {
|
|
161
|
-
const { standaloneDir, outfile } = options;
|
|
187
|
+
const { standaloneDir, outfile, extraArgs = [] } = options;
|
|
162
188
|
const entryPoint = join2(standaloneDir, "server-entry.js");
|
|
163
189
|
const args = [
|
|
164
190
|
"build",
|
|
@@ -175,7 +201,8 @@ function compile(options) {
|
|
|
175
201
|
"--define",
|
|
176
202
|
'process.env.NEXT_RUNTIME="nodejs"',
|
|
177
203
|
"--outfile",
|
|
178
|
-
outfile
|
|
204
|
+
outfile,
|
|
205
|
+
...extraArgs
|
|
179
206
|
];
|
|
180
207
|
console.log(`next-bun-compile: Compiling to ${outfile}...`);
|
|
181
208
|
execFileSync("bun", args, { stdio: "inherit" });
|
|
@@ -185,6 +212,7 @@ function compile(options) {
|
|
|
185
212
|
// src/cli.ts
|
|
186
213
|
import { existsSync as existsSync2 } from "node:fs";
|
|
187
214
|
import { join as join3, resolve } from "node:path";
|
|
215
|
+
var extraArgs = process.argv.slice(2);
|
|
188
216
|
var projectDir = resolve(".");
|
|
189
217
|
var distDir = join3(projectDir, ".next");
|
|
190
218
|
var standaloneDir = join3(distDir, "standalone");
|
|
@@ -197,4 +225,4 @@ if (existsSync2(ctxPath)) {
|
|
|
197
225
|
console.log("next-bun-compile: Using build context from adapter");
|
|
198
226
|
}
|
|
199
227
|
generateEntryPoint({ standaloneDir, distDir, projectDir });
|
|
200
|
-
compile({ standaloneDir, outfile: join3(projectDir, "server") });
|
|
228
|
+
compile({ standaloneDir, outfile: join3(projectDir, "server"), extraArgs });
|
package/dist/compile.js
CHANGED
|
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
function compile(options) {
|
|
8
|
-
const { standaloneDir, outfile } = options;
|
|
8
|
+
const { standaloneDir, outfile, extraArgs = [] } = options;
|
|
9
9
|
const entryPoint = join(standaloneDir, "server-entry.js");
|
|
10
10
|
const args = [
|
|
11
11
|
"build",
|
|
@@ -22,7 +22,8 @@ function compile(options) {
|
|
|
22
22
|
"--define",
|
|
23
23
|
'process.env.NEXT_RUNTIME="nodejs"',
|
|
24
24
|
"--outfile",
|
|
25
|
-
outfile
|
|
25
|
+
outfile,
|
|
26
|
+
...extraArgs
|
|
26
27
|
];
|
|
27
28
|
console.log(`next-bun-compile: Compiling to ${outfile}...`);
|
|
28
29
|
execFileSync("bun", args, { stdio: "inherit" });
|
package/dist/generate.js
CHANGED
|
@@ -66,9 +66,23 @@ function generateStubs(standaloneDir) {
|
|
|
66
66
|
console.log(`next-bun-compile: Created ${count} module stubs`);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
function patchRequireHook(standaloneDir) {
|
|
70
|
+
const hookPath = join(standaloneDir, "node_modules/next/dist/server/require-hook.js");
|
|
71
|
+
if (!existsSync(hookPath))
|
|
72
|
+
return;
|
|
73
|
+
let content = readFileSync(hookPath, "utf-8");
|
|
74
|
+
const target = "let resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;";
|
|
75
|
+
if (!content.includes(target))
|
|
76
|
+
return;
|
|
77
|
+
content = content.replace(target, `let _resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;
|
|
78
|
+
let resolve = (id) => { try { return _resolve(id); } catch { return ''; } };`);
|
|
79
|
+
writeFileSync(hookPath, content);
|
|
80
|
+
console.log("next-bun-compile: Patched require-hook.js for compiled binary compatibility");
|
|
81
|
+
}
|
|
69
82
|
function generateEntryPoint(options) {
|
|
70
83
|
const { standaloneDir, distDir, projectDir } = options;
|
|
71
84
|
generateStubs(standaloneDir);
|
|
85
|
+
patchRequireHook(standaloneDir);
|
|
72
86
|
const staticDir = join(distDir, "static");
|
|
73
87
|
const staticFiles = walkDir(staticDir).map((f) => ({
|
|
74
88
|
...f,
|
|
@@ -79,13 +93,18 @@ function generateEntryPoint(options) {
|
|
|
79
93
|
...f,
|
|
80
94
|
urlPath: `/${f.relativePath.replace(/\\/g, "/")}`
|
|
81
95
|
}));
|
|
96
|
+
const standaloneNextDir = join(standaloneDir, ".next");
|
|
97
|
+
const runtimeFiles = walkDir(standaloneNextDir).map((f) => ({
|
|
98
|
+
...f,
|
|
99
|
+
urlPath: `__runtime/.next/${f.relativePath.replace(/\\/g, "/")}`
|
|
100
|
+
}));
|
|
82
101
|
const ctx = JSON.parse(readFileSync(join(distDir, "bun-compile-ctx.json"), "utf-8"));
|
|
83
102
|
const { assetPrefix } = ctx;
|
|
84
|
-
const assetsToEmbed = assetPrefix ? publicFiles : [...staticFiles, ...publicFiles];
|
|
103
|
+
const assetsToEmbed = assetPrefix ? [...publicFiles, ...runtimeFiles] : [...staticFiles, ...publicFiles, ...runtimeFiles];
|
|
85
104
|
if (assetPrefix) {
|
|
86
105
|
console.log(`next-bun-compile: assetPrefix detected — skipping ${staticFiles.length} static assets (served from CDN)`);
|
|
87
106
|
}
|
|
88
|
-
console.log(`next-bun-compile: Embedding ${assetsToEmbed.length} assets (${
|
|
107
|
+
console.log(`next-bun-compile: Embedding ${assetsToEmbed.length} assets (${staticFiles.length} static + ${publicFiles.length} public + ${runtimeFiles.length} runtime)`);
|
|
89
108
|
const imports = [];
|
|
90
109
|
const mapEntries = [];
|
|
91
110
|
for (const asset of assetsToEmbed) {
|
|
@@ -107,7 +126,14 @@ ${mapEntries.join(`
|
|
|
107
126
|
throw new Error("next-bun-compile: Could not extract nextConfig from standalone server.js");
|
|
108
127
|
}
|
|
109
128
|
const assetExtractions = assetsToEmbed.map((a) => {
|
|
110
|
-
|
|
129
|
+
let diskPath;
|
|
130
|
+
if (a.urlPath.startsWith("__runtime/")) {
|
|
131
|
+
diskPath = a.urlPath.slice("__runtime/".length);
|
|
132
|
+
} else if (a.urlPath.startsWith("/_next/static/")) {
|
|
133
|
+
diskPath = ".next/static/" + a.relativePath;
|
|
134
|
+
} else {
|
|
135
|
+
diskPath = "public/" + a.relativePath;
|
|
136
|
+
}
|
|
111
137
|
return [a.urlPath, diskPath];
|
|
112
138
|
});
|
|
113
139
|
const serverEntry = `import { assetMap } from "./assets.generated.js";
|
package/dist/index.js
CHANGED
|
@@ -66,9 +66,23 @@ function generateStubs(standaloneDir) {
|
|
|
66
66
|
console.log(`next-bun-compile: Created ${count} module stubs`);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
function patchRequireHook(standaloneDir) {
|
|
70
|
+
const hookPath = join(standaloneDir, "node_modules/next/dist/server/require-hook.js");
|
|
71
|
+
if (!existsSync(hookPath))
|
|
72
|
+
return;
|
|
73
|
+
let content = readFileSync(hookPath, "utf-8");
|
|
74
|
+
const target = "let resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;";
|
|
75
|
+
if (!content.includes(target))
|
|
76
|
+
return;
|
|
77
|
+
content = content.replace(target, `let _resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;
|
|
78
|
+
let resolve = (id) => { try { return _resolve(id); } catch { return ''; } };`);
|
|
79
|
+
writeFileSync(hookPath, content);
|
|
80
|
+
console.log("next-bun-compile: Patched require-hook.js for compiled binary compatibility");
|
|
81
|
+
}
|
|
69
82
|
function generateEntryPoint(options) {
|
|
70
83
|
const { standaloneDir, distDir, projectDir } = options;
|
|
71
84
|
generateStubs(standaloneDir);
|
|
85
|
+
patchRequireHook(standaloneDir);
|
|
72
86
|
const staticDir = join(distDir, "static");
|
|
73
87
|
const staticFiles = walkDir(staticDir).map((f) => ({
|
|
74
88
|
...f,
|
|
@@ -79,13 +93,18 @@ function generateEntryPoint(options) {
|
|
|
79
93
|
...f,
|
|
80
94
|
urlPath: `/${f.relativePath.replace(/\\/g, "/")}`
|
|
81
95
|
}));
|
|
96
|
+
const standaloneNextDir = join(standaloneDir, ".next");
|
|
97
|
+
const runtimeFiles = walkDir(standaloneNextDir).map((f) => ({
|
|
98
|
+
...f,
|
|
99
|
+
urlPath: `__runtime/.next/${f.relativePath.replace(/\\/g, "/")}`
|
|
100
|
+
}));
|
|
82
101
|
const ctx = JSON.parse(readFileSync(join(distDir, "bun-compile-ctx.json"), "utf-8"));
|
|
83
102
|
const { assetPrefix } = ctx;
|
|
84
|
-
const assetsToEmbed = assetPrefix ? publicFiles : [...staticFiles, ...publicFiles];
|
|
103
|
+
const assetsToEmbed = assetPrefix ? [...publicFiles, ...runtimeFiles] : [...staticFiles, ...publicFiles, ...runtimeFiles];
|
|
85
104
|
if (assetPrefix) {
|
|
86
105
|
console.log(`next-bun-compile: assetPrefix detected — skipping ${staticFiles.length} static assets (served from CDN)`);
|
|
87
106
|
}
|
|
88
|
-
console.log(`next-bun-compile: Embedding ${assetsToEmbed.length} assets (${
|
|
107
|
+
console.log(`next-bun-compile: Embedding ${assetsToEmbed.length} assets (${staticFiles.length} static + ${publicFiles.length} public + ${runtimeFiles.length} runtime)`);
|
|
89
108
|
const imports = [];
|
|
90
109
|
const mapEntries = [];
|
|
91
110
|
for (const asset of assetsToEmbed) {
|
|
@@ -107,7 +126,14 @@ ${mapEntries.join(`
|
|
|
107
126
|
throw new Error("next-bun-compile: Could not extract nextConfig from standalone server.js");
|
|
108
127
|
}
|
|
109
128
|
const assetExtractions = assetsToEmbed.map((a) => {
|
|
110
|
-
|
|
129
|
+
let diskPath;
|
|
130
|
+
if (a.urlPath.startsWith("__runtime/")) {
|
|
131
|
+
diskPath = a.urlPath.slice("__runtime/".length);
|
|
132
|
+
} else if (a.urlPath.startsWith("/_next/static/")) {
|
|
133
|
+
diskPath = ".next/static/" + a.relativePath;
|
|
134
|
+
} else {
|
|
135
|
+
diskPath = "public/" + a.relativePath;
|
|
136
|
+
}
|
|
111
137
|
return [a.urlPath, diskPath];
|
|
112
138
|
});
|
|
113
139
|
const serverEntry = `import { assetMap } from "./assets.generated.js";
|
|
@@ -157,7 +183,7 @@ extractAssets().then(() => {
|
|
|
157
183
|
import { execFileSync } from "node:child_process";
|
|
158
184
|
import { join as join2 } from "node:path";
|
|
159
185
|
function compile(options) {
|
|
160
|
-
const { standaloneDir, outfile } = options;
|
|
186
|
+
const { standaloneDir, outfile, extraArgs = [] } = options;
|
|
161
187
|
const entryPoint = join2(standaloneDir, "server-entry.js");
|
|
162
188
|
const args = [
|
|
163
189
|
"build",
|
|
@@ -174,7 +200,8 @@ function compile(options) {
|
|
|
174
200
|
"--define",
|
|
175
201
|
'process.env.NEXT_RUNTIME="nodejs"',
|
|
176
202
|
"--outfile",
|
|
177
|
-
outfile
|
|
203
|
+
outfile,
|
|
204
|
+
...extraArgs
|
|
178
205
|
];
|
|
179
206
|
console.log(`next-bun-compile: Compiling to ${outfile}...`);
|
|
180
207
|
execFileSync("bun", args, { stdio: "inherit" });
|