next-bun-compile 0.6.13 → 0.7.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 +2 -0
- package/dist/cli.js +1 -1
- package/dist/{index-3xvctb1p.js → index-np1qb2b3.js} +167 -36
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ One command. One binary. No runtime dependencies.
|
|
|
8
8
|
next build # → ./server (single executable with embedded assets)
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
**📖 Docs: [ramonmalcolm10.github.io/next-bun-compile](https://ramonmalcolm10.github.io/next-bun-compile/)**
|
|
12
|
+
|
|
11
13
|
## Requirements
|
|
12
14
|
|
|
13
15
|
- [Bun](https://bun.sh) >= 1.3
|
package/dist/cli.js
CHANGED
|
@@ -46,24 +46,56 @@ function toVarName(filePath) {
|
|
|
46
46
|
const safe = filePath.replace(/[^a-zA-Z0-9]/g, "_").slice(0, 40);
|
|
47
47
|
return `asset_${safe}_${hash}`;
|
|
48
48
|
}
|
|
49
|
-
function findPackageDirs(
|
|
49
|
+
function findPackageDirs(standaloneDir, pkg) {
|
|
50
50
|
const dirs = [];
|
|
51
|
-
const direct = join(nodeModulesDir, pkg);
|
|
52
|
-
if (existsSync(direct))
|
|
53
|
-
dirs.push(direct);
|
|
54
51
|
const prefix = pkg.startsWith("@") ? pkg.split("/")[0] + "+" + pkg.split("/")[1] : pkg;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
const seen = new Set;
|
|
53
|
+
const checkNodeModules = (nodeModulesDir) => {
|
|
54
|
+
const direct = join(nodeModulesDir, pkg);
|
|
55
|
+
if (existsSync(direct) && !seen.has(direct)) {
|
|
56
|
+
seen.add(direct);
|
|
57
|
+
dirs.push(direct);
|
|
58
|
+
}
|
|
59
|
+
for (const store of [".bun", ".pnpm"]) {
|
|
60
|
+
const storeDir = join(nodeModulesDir, store);
|
|
61
|
+
if (!existsSync(storeDir))
|
|
62
|
+
continue;
|
|
63
|
+
let entries;
|
|
64
|
+
try {
|
|
65
|
+
entries = readdirSync(storeDir);
|
|
66
|
+
} catch {
|
|
61
67
|
continue;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
}
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
if (!entry.startsWith(prefix + "@"))
|
|
71
|
+
continue;
|
|
72
|
+
const hoisted = join(storeDir, entry, "node_modules", pkg);
|
|
73
|
+
if (existsSync(hoisted) && !seen.has(hoisted)) {
|
|
74
|
+
seen.add(hoisted);
|
|
75
|
+
dirs.push(hoisted);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
65
78
|
}
|
|
66
|
-
}
|
|
79
|
+
};
|
|
80
|
+
const walk = (dir) => {
|
|
81
|
+
let entries;
|
|
82
|
+
try {
|
|
83
|
+
entries = readdirSync(dir);
|
|
84
|
+
} catch {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
const full = join(dir, entry);
|
|
89
|
+
if (entry === "node_modules") {
|
|
90
|
+
checkNodeModules(full);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const stat = tryStat(full);
|
|
94
|
+
if (stat && stat.isDirectory())
|
|
95
|
+
walk(full);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
walk(standaloneDir);
|
|
67
99
|
return dirs;
|
|
68
100
|
}
|
|
69
101
|
function generateStubs(standaloneDir) {
|
|
@@ -92,7 +124,7 @@ function generateStubs(standaloneDir) {
|
|
|
92
124
|
const nodeModulesDir = join(standaloneDir, "node_modules");
|
|
93
125
|
let count = 0;
|
|
94
126
|
for (const stub of stubs) {
|
|
95
|
-
const pkgDirs = findPackageDirs(
|
|
127
|
+
const pkgDirs = findPackageDirs(standaloneDir, stub.pkg);
|
|
96
128
|
if (pkgDirs.length === 0)
|
|
97
129
|
pkgDirs.push(join(nodeModulesDir, stub.pkg));
|
|
98
130
|
for (const pkgDir of pkgDirs) {
|
|
@@ -230,6 +262,41 @@ function buildCanonicalResolutions(externalRoot, aliases) {
|
|
|
230
262
|
}
|
|
231
263
|
return out;
|
|
232
264
|
}
|
|
265
|
+
function validateAliasResolutions(aliases, resolutions) {
|
|
266
|
+
const verbose = process.env.NEXT_BUN_COMPILE_VERBOSE === "1";
|
|
267
|
+
const all = [];
|
|
268
|
+
for (const { alias, target, subpaths } of aliases) {
|
|
269
|
+
all.push({ ref: alias, canonical: target, file: resolutions.get(alias) ?? null });
|
|
270
|
+
for (const sub of subpaths) {
|
|
271
|
+
const ref = `${alias}/${sub}`;
|
|
272
|
+
all.push({
|
|
273
|
+
ref,
|
|
274
|
+
canonical: `${target}/${sub}`,
|
|
275
|
+
file: resolutions.get(ref) ?? null
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const unresolved = all.filter((e) => !e.file).map(({ ref, canonical }) => ({ ref, canonical }));
|
|
280
|
+
if (verbose && all.length > 0) {
|
|
281
|
+
console.log(`next-bun-compile: Validating ${all.length} turbopack alias reference(s):`);
|
|
282
|
+
for (const { ref, canonical, file } of all) {
|
|
283
|
+
if (file) {
|
|
284
|
+
const display = file.replace(/^\.next\/node_modules\//, "");
|
|
285
|
+
console.log(` ✓ ${ref} → ${canonical} (${display})`);
|
|
286
|
+
} else {
|
|
287
|
+
console.log(` ✗ ${ref} → ${canonical} (NOT FOUND)`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (unresolved.length > 0) {
|
|
292
|
+
console.warn(`next-bun-compile: ⚠ ${unresolved.length} of ${all.length} turbopack alias reference(s) won't resolve at runtime:`);
|
|
293
|
+
for (const { ref, canonical } of unresolved) {
|
|
294
|
+
console.warn(` ✗ ${ref} → ${canonical}`);
|
|
295
|
+
}
|
|
296
|
+
console.warn(`next-bun-compile: These chunks will throw at runtime when the reference is hit. ` + `Either the package is missing from dependencies, or it's hidden behind a path the ` + `standalone trace didn't include. Try adding to transpilePackages in next.config.`);
|
|
297
|
+
}
|
|
298
|
+
return unresolved;
|
|
299
|
+
}
|
|
233
300
|
function rewriteTurbopackAliases(standaloneNextDir, aliases, resolutions) {
|
|
234
301
|
if (aliases.length === 0 || resolutions.size === 0)
|
|
235
302
|
return;
|
|
@@ -294,8 +361,7 @@ function findServerDir(standaloneDir) {
|
|
|
294
361
|
return found;
|
|
295
362
|
}
|
|
296
363
|
function patchRequireHook(standaloneDir) {
|
|
297
|
-
const
|
|
298
|
-
const nextDirs = findPackageDirs(nodeModulesDir, "next");
|
|
364
|
+
const nextDirs = findPackageDirs(standaloneDir, "next");
|
|
299
365
|
const target = "let resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;";
|
|
300
366
|
const replacement = `let _resolve = process.env.NEXT_MINIMAL ? __non_webpack_require__.resolve : require.resolve;
|
|
301
367
|
let resolve = (id) => { try { return _resolve(id); } catch { return ''; } };`;
|
|
@@ -316,9 +382,6 @@ let resolve = (id) => { try { return _resolve(id); } catch { return ''; } };`;
|
|
|
316
382
|
}
|
|
317
383
|
}
|
|
318
384
|
function collectExternalModules(standaloneDir) {
|
|
319
|
-
const nodeModulesDir = join(standaloneDir, "node_modules");
|
|
320
|
-
if (!existsSync(nodeModulesDir))
|
|
321
|
-
return [];
|
|
322
385
|
const pkgRoots = new Map;
|
|
323
386
|
function addPkg(name, path) {
|
|
324
387
|
if (!pkgRoots.has(name))
|
|
@@ -346,17 +409,37 @@ function collectExternalModules(standaloneDir) {
|
|
|
346
409
|
}
|
|
347
410
|
}
|
|
348
411
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
412
|
+
function walkForNodeModules(dir) {
|
|
413
|
+
let entries;
|
|
414
|
+
try {
|
|
415
|
+
entries = readdirSync(dir);
|
|
416
|
+
} catch {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
for (const entry of entries) {
|
|
420
|
+
const full = join(dir, entry);
|
|
421
|
+
if (entry === "node_modules") {
|
|
422
|
+
scanDir(full);
|
|
423
|
+
for (const store of [".bun", ".pnpm"]) {
|
|
424
|
+
const storeDir = join(full, store);
|
|
425
|
+
if (!existsSync(storeDir))
|
|
426
|
+
continue;
|
|
427
|
+
for (const storeEntry of readdirSync(storeDir)) {
|
|
428
|
+
const nested = join(storeDir, storeEntry, "node_modules");
|
|
429
|
+
if (existsSync(nested))
|
|
430
|
+
scanDir(nested);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const stat = tryStat(full);
|
|
436
|
+
if (stat && stat.isDirectory())
|
|
437
|
+
walkForNodeModules(full);
|
|
358
438
|
}
|
|
359
439
|
}
|
|
440
|
+
walkForNodeModules(standaloneDir);
|
|
441
|
+
if (pkgRoots.size === 0)
|
|
442
|
+
return [];
|
|
360
443
|
const results = [];
|
|
361
444
|
for (const [name, pkgPath] of pkgRoots) {
|
|
362
445
|
for (const f of walkDir(pkgPath)) {
|
|
@@ -369,8 +452,7 @@ function collectExternalModules(standaloneDir) {
|
|
|
369
452
|
return results;
|
|
370
453
|
}
|
|
371
454
|
function fixModuleResolution(standaloneDir) {
|
|
372
|
-
const
|
|
373
|
-
for (const pkgDir of findPackageDirs(nodeModulesDir, "next")) {
|
|
455
|
+
for (const pkgDir of findPackageDirs(standaloneDir, "next")) {
|
|
374
456
|
const compiledDir = join(pkgDir, "dist/compiled");
|
|
375
457
|
if (!existsSync(compiledDir))
|
|
376
458
|
continue;
|
|
@@ -389,7 +471,7 @@ function fixModuleResolution(standaloneDir) {
|
|
|
389
471
|
}
|
|
390
472
|
}
|
|
391
473
|
}
|
|
392
|
-
for (const helpersDir of findPackageDirs(
|
|
474
|
+
for (const helpersDir of findPackageDirs(standaloneDir, "@swc/helpers")) {
|
|
393
475
|
const cjsDir = join(helpersDir, "cjs");
|
|
394
476
|
if (!existsSync(cjsDir))
|
|
395
477
|
continue;
|
|
@@ -450,6 +532,7 @@ function generateEntryPoint(options) {
|
|
|
450
532
|
console.log(`next-bun-compile: Embedding ${externalModules.length} external modules for SSR`);
|
|
451
533
|
}
|
|
452
534
|
const canonicalResolutions = buildCanonicalResolutions(externalDir, turbopackAliases);
|
|
535
|
+
validateAliasResolutions(turbopackAliases, canonicalResolutions);
|
|
453
536
|
rewriteTurbopackAliases(standaloneNextDir, turbopackAliases, canonicalResolutions);
|
|
454
537
|
const ctx = JSON.parse(readFileSync(join(distDir, "bun-compile-ctx.json"), "utf-8"));
|
|
455
538
|
const { assetPrefix } = ctx;
|
|
@@ -511,6 +594,20 @@ process.env.NODE_ENV = "production";
|
|
|
511
594
|
// honor exports maps. Generic: every externalized package's internal deps
|
|
512
595
|
// get resolved without per-package patching.
|
|
513
596
|
const __nbcAliases = ${JSON.stringify(Object.fromEntries(turbopackAliases.map((a) => [a.alias, a.target])))};
|
|
597
|
+
// Debug mode: set NEXT_BUN_COMPILE_DEBUG=1 to log every resolver-hook
|
|
598
|
+
// decision (alias redirects, fallback walks, fallback failures). Off by
|
|
599
|
+
// default so production logs stay clean; turn it on when reproducing a
|
|
600
|
+
// resolution bug — that one log line is usually enough to know which
|
|
601
|
+
// package was missing and where the walk gave up.
|
|
602
|
+
const __nbcDebug = process.env.NEXT_BUN_COMPILE_DEBUG === "1";
|
|
603
|
+
function __nbcLog(msg) { console.log("next-bun-compile [debug]:", msg); }
|
|
604
|
+
if (__nbcDebug) {
|
|
605
|
+
const n = Object.keys(__nbcAliases).length;
|
|
606
|
+
__nbcLog(\`resolver hook installed; \${n} alias mapping(s):\`);
|
|
607
|
+
for (const [k, v] of Object.entries(__nbcAliases)) {
|
|
608
|
+
__nbcLog(\` \${k} → \${v}\`);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
514
611
|
const __nbcOrigResolveFilename = Module._resolveFilename;
|
|
515
612
|
function __nbcStatFile(p) {
|
|
516
613
|
try { return fs.statSync(p).isFile() ? p : null; } catch { return null; }
|
|
@@ -540,12 +637,34 @@ function __nbcResolveSubpath(pkgDir, pkgJson, sub) {
|
|
|
540
637
|
}
|
|
541
638
|
}
|
|
542
639
|
}
|
|
543
|
-
|
|
640
|
+
// Direct file forms
|
|
641
|
+
const direct = __nbcStatFile(path.join(pkgDir, sub))
|
|
544
642
|
|| __nbcStatFile(path.join(pkgDir, sub + ".js"))
|
|
545
643
|
|| __nbcStatFile(path.join(pkgDir, sub + ".cjs"))
|
|
546
644
|
|| __nbcStatFile(path.join(pkgDir, sub + ".mjs"))
|
|
547
|
-
|| __nbcStatFile(path.join(pkgDir, sub + ".json"))
|
|
548
|
-
|
|
645
|
+
|| __nbcStatFile(path.join(pkgDir, sub + ".json"));
|
|
646
|
+
if (direct) return direct;
|
|
647
|
+
// Subpath is a directory: read its own package.json + main (e.g.
|
|
648
|
+
// next/dist/compiled/source-map has main: "source-map.js"). Falls
|
|
649
|
+
// back to index.js / index.cjs lookup if no package.json.
|
|
650
|
+
const subDir = path.join(pkgDir, sub);
|
|
651
|
+
try {
|
|
652
|
+
if (fs.statSync(subDir).isDirectory()) {
|
|
653
|
+
const subPkgPath = path.join(subDir, "package.json");
|
|
654
|
+
if (fs.existsSync(subPkgPath)) {
|
|
655
|
+
try {
|
|
656
|
+
const subPkg = JSON.parse(fs.readFileSync(subPkgPath, "utf-8"));
|
|
657
|
+
const main = typeof subPkg.main === "string" ? subPkg.main : null;
|
|
658
|
+
if (main) {
|
|
659
|
+
const f = __nbcStatFile(path.join(subDir, main))
|
|
660
|
+
|| __nbcStatFile(path.join(subDir, main + ".js"));
|
|
661
|
+
if (f) return f;
|
|
662
|
+
}
|
|
663
|
+
} catch {}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
} catch {}
|
|
667
|
+
return __nbcStatFile(path.join(pkgDir, sub, "index.js"))
|
|
549
668
|
|| __nbcStatFile(path.join(pkgDir, sub, "index.cjs"));
|
|
550
669
|
}
|
|
551
670
|
function __nbcResolvePackage(request, fromDir) {
|
|
@@ -596,6 +715,10 @@ function __nbcRedirectAlias(request) {
|
|
|
596
715
|
}
|
|
597
716
|
Module._resolveFilename = function(request, parent, isMain, options) {
|
|
598
717
|
const redirected = __nbcRedirectAlias(request);
|
|
718
|
+
if (__nbcDebug && redirected !== request) {
|
|
719
|
+
const from = parent && parent.filename ? parent.filename : "<unknown>";
|
|
720
|
+
__nbcLog(\`redirected "\${request}" → "\${redirected}" (from \${from})\`);
|
|
721
|
+
}
|
|
599
722
|
try {
|
|
600
723
|
return __nbcOrigResolveFilename.call(this, redirected, parent, isMain, options);
|
|
601
724
|
} catch (err) {
|
|
@@ -605,7 +728,15 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
|
|
605
728
|
}
|
|
606
729
|
const fromDir = parent && parent.filename ? path.dirname(parent.filename) : process.cwd();
|
|
607
730
|
const resolved = __nbcResolvePackage(redirected, fromDir);
|
|
608
|
-
if (resolved)
|
|
731
|
+
if (resolved) {
|
|
732
|
+
if (__nbcDebug) {
|
|
733
|
+
__nbcLog(\`fallback resolved "\${redirected}" → \${resolved} (from \${fromDir})\`);
|
|
734
|
+
}
|
|
735
|
+
return resolved;
|
|
736
|
+
}
|
|
737
|
+
if (__nbcDebug) {
|
|
738
|
+
__nbcLog(\`fallback FAILED for "\${redirected}" (from \${fromDir}); throwing original ResolveMessage\`);
|
|
739
|
+
}
|
|
609
740
|
throw err;
|
|
610
741
|
}
|
|
611
742
|
};
|
package/dist/index.js
CHANGED