mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-26 23:19:37 +00:00
fix(vite): bypass es-toolkit CJS shim for recharts deep imports
The Nodes page (and any other recharts-using route) crashed in dev and prod with TypeError: require_isUnsafeProperty is not a function. Root cause: es-toolkit's package.json exports './compat/*' only via a default condition pointing at the CJS shims under compat/<name>.js. Those shims use a require_X.Y access pattern that Vite's optimizer (Rolldown in Vite 8) and the production Rolldown build both mishandle, losing the named-export accessor and calling the namespace object as a function. recharts imports a dozen of these subpaths with default- import syntax, so every chart path tripped the bug. The matching ESM build at dist/compat/<category>/<name>.mjs is fine, but it only carries a named export. Recharts uses default imports. Plug a small Rollup-compatible plugin (enforce: 'pre') in front of the resolver: any 'es-toolkit/compat/<name>' request becomes a virtual module that imports the named symbol from the right .mjs file and re-exports it as both default and named. The plugin is registered as a top-level plugin (for the prod build) and via the new Vite 8 optimizeDeps.rolldownOptions.plugins (for the dev pre-bundler), so both pipelines pick it up consistently.
This commit is contained in:
@@ -77,6 +77,45 @@ function injectBasePathPlugin() {
|
||||
};
|
||||
}
|
||||
|
||||
// es-toolkit's `./compat/*` exports map only declares a CJS condition, so deep
|
||||
// imports like `es-toolkit/compat/get` resolve to a CJS shim. That shim uses a
|
||||
// `require_X.Y` pattern that Vite's optimizer and Rolldown both mishandle
|
||||
// (TypeError: require_isUnsafeProperty is not a function). The ESM build at
|
||||
// `dist/compat/<category>/<name>.mjs` is fine but only carries a named export,
|
||||
// while consumers like recharts use default imports — so emit a virtual module
|
||||
// that re-exports the named symbol as default.
|
||||
const ES_TOOLKIT_COMPAT_DIRS = ['array', 'function', 'math', 'object', 'predicate', 'string', 'util'];
|
||||
const ES_TOOLKIT_SHIM_PREFIX = '\0es-toolkit-compat:';
|
||||
|
||||
function findEsToolkitCompatMjs(name) {
|
||||
for (const sub of ES_TOOLKIT_COMPAT_DIRS) {
|
||||
const candidate = path.resolve(__dirname, 'node_modules/es-toolkit/dist/compat', sub, `${name}.mjs`);
|
||||
if (fs.existsSync(candidate)) return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function esToolkitCompatEsmResolver() {
|
||||
return {
|
||||
name: 'es-toolkit-compat-esm',
|
||||
enforce: 'pre',
|
||||
resolveId(id) {
|
||||
const m = id.match(/^es-toolkit\/compat\/(.+)$/);
|
||||
if (!m) return null;
|
||||
if (!findEsToolkitCompatMjs(m[1])) return null;
|
||||
return ES_TOOLKIT_SHIM_PREFIX + m[1];
|
||||
},
|
||||
load(id) {
|
||||
if (!id.startsWith(ES_TOOLKIT_SHIM_PREFIX)) return null;
|
||||
const name = id.slice(ES_TOOLKIT_SHIM_PREFIX.length);
|
||||
const target = findEsToolkitCompatMjs(name);
|
||||
if (!target) return null;
|
||||
const url = target.replace(/\\/g, '/');
|
||||
return `import { ${name} } from ${JSON.stringify(url)};\nexport { ${name} };\nexport default ${name};\n`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function bypassMigratedRoute(req) {
|
||||
if (req.method !== 'GET') return undefined;
|
||||
const url = req.url.split('?')[0];
|
||||
@@ -140,12 +179,17 @@ function makeBackendProxy(target) {
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react(), injectBasePathPlugin()],
|
||||
plugins: [esToolkitCompatEsmResolver(), react(), injectBasePathPlugin()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
rolldownOptions: {
|
||||
plugins: [esToolkitCompatEsmResolver()],
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
renderBuiltUrl(filename, { hostType }) {
|
||||
if (hostType === 'js') {
|
||||
|
||||
Reference in New Issue
Block a user