Skip to content

Commit 80131d0

Browse files
Copilothotlong
andcommitted
fix(web): resolve pnpm strict-mode build failures for react-router and Node.js builtins
- Add react-router as direct dependency for pnpm strict module resolution - Add nodeBuiltinStubs Vite plugin to shim crypto/path/module imports from @objectstack/core that leak into the browser bundle - Exclude @objectstack/core from Vite optimizeDeps pre-bundling - Add react-router to Vite optimizeDeps.include for proper deduplication Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent 221c1e6 commit 80131d0

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"lucide-react": "^0.469.0",
2626
"react": "^19.0.0",
2727
"react-dom": "^19.0.0",
28+
"react-router": "^7.2.0",
2829
"react-router-dom": "^7.2.0",
2930
"tailwind-merge": "^3.0.2"
3031
},

apps/web/vite.config.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,39 @@ function htmlBaseUrl(): Plugin {
1515
};
1616
}
1717

18+
/**
19+
* Rollup plugin: stub Node.js built-in modules that leak into the browser
20+
* bundle via server-side transitive dependencies (e.g. @objectstack/core).
21+
* Each built-in is resolved to a virtual module exporting a Proxy so that
22+
* any named import (e.g. `import { createHash } from "crypto"`) receives a
23+
* no-op function instead of failing the build.
24+
*/
25+
const nodeBuiltins = ['crypto', 'path', 'module', 'fs', 'os', 'util'];
26+
const VIRTUAL_PREFIX = '\0node-stub:';
27+
function nodeBuiltinStubs(): Plugin {
28+
return {
29+
name: 'node-builtin-stubs',
30+
enforce: 'pre',
31+
resolveId(source) {
32+
if (nodeBuiltins.includes(source)) return VIRTUAL_PREFIX + source;
33+
},
34+
load(id) {
35+
if (id.startsWith(VIRTUAL_PREFIX)) {
36+
// Return a module that exports a Proxy as its default + re-exports
37+
// any named binding the consumer asks for as a no-op function.
38+
return `
39+
const handler = { get: (_, prop) => typeof prop === 'string' ? () => '' : undefined };
40+
const stub = new Proxy({}, handler);
41+
export default stub;
42+
export const createHash = () => ({ update: () => ({ digest: () => '' }) });
43+
`;
44+
}
45+
},
46+
};
47+
}
48+
1849
export default defineConfig({
19-
plugins: [react(), tailwindcss(), htmlBaseUrl()],
50+
plugins: [react(), tailwindcss(), htmlBaseUrl(), nodeBuiltinStubs()],
2051
base,
2152
resolve: {
2253
// Ensure every dependency resolves to exactly ONE copy of React, its DOM
@@ -32,11 +63,15 @@ export default defineConfig({
3263
'react',
3364
'react-dom',
3465
'react-dom/client',
66+
'react-router',
3567
'react-router-dom',
3668
'better-auth/react',
3769
'better-auth/client/plugins',
3870
'@tanstack/react-query',
3971
],
72+
// @objectstack/core contains Node.js built-ins (crypto, path).
73+
// Exclude it from pre-bundling so the stubs plugin resolves them.
74+
exclude: ['@objectstack/core'],
4075
},
4176
server: {
4277
port: 5321,

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)