recycle recycle
This commit is contained in:
parent
7aa76ec55c
commit
1407e6620e
@ -229,19 +229,53 @@ Before applying this technique to any library, verify:
|
||||
condition in the exports map — confirmed in the
|
||||
[official exports map](https://github.com/TanStack/router/blob/main/packages/router-core/package.json)).
|
||||
|
||||
4. **Exclude from `optimizeDeps`**
|
||||
4. **Exclude from `optimizeDeps` — but skip packages with CJS transitive deps**
|
||||
|
||||
Without this, Vite's dev pre-bundler re-bundles the source into a single
|
||||
opaque chunk and defeats the purpose in dev mode.
|
||||
Without `exclude`, Vite's dev pre-bundler re-bundles the source into a
|
||||
single opaque chunk and defeats the purpose in dev mode.
|
||||
([Vite docs — `optimizeDeps.exclude`](https://vitejs.dev/config/dep-optimization-options.html#optimizedeps-exclude):
|
||||
_"Dependencies to exclude from pre-bundling."_)
|
||||
|
||||
The Vite docs warn:
|
||||
> _"CommonJS dependencies should not be excluded from optimization. If an
|
||||
> ESM dependency is excluded from optimization, but has a nested CommonJS
|
||||
> dependency, the CommonJS dependency should be added to
|
||||
> `optimizeDeps.include`."_
|
||||
|
||||
**`@tanstack/react-store` is the exception here.** Its source file
|
||||
`src/useStore.ts` imports `use-sync-external-store/shim/with-selector`
|
||||
which is a CJS-only file (`module.exports = ...`). If that package is
|
||||
excluded from optimizeDeps, Vite serves the raw CJS as ESM and the named
|
||||
import breaks at runtime in dev:
|
||||
|
||||
```
|
||||
Uncaught SyntaxError: The requested module
|
||||
'.../use-sync-external-store/shim/with-selector.js'
|
||||
does not provide an export named 'useSyncExternalStoreWithSelector'
|
||||
```
|
||||
|
||||
The fix requires including the **exact import subpath**, not the package
|
||||
root. `@tanstack/react-store/dist/esm/useStore.js` imports
|
||||
`use-sync-external-store/shim/with-selector` — that is the string Vite
|
||||
must match to serve the pre-bundled ESM wrapper:
|
||||
|
||||
```ts
|
||||
optimizeDeps: {
|
||||
exclude: ["@tanstack/router-core", "@tanstack/react-router", /* … */],
|
||||
exclude: ["@tanstack/router-core", "@tanstack/react-router",
|
||||
"@tanstack/history", "@tanstack/store"],
|
||||
include: ["use-sync-external-store/shim/with-selector"],
|
||||
}
|
||||
```
|
||||
|
||||
Including `"use-sync-external-store"` (the root) does **not** fix it —
|
||||
Vite pre-bundles at subpath granularity and the pre-bundled root is never
|
||||
served for the subpath import.
|
||||
|
||||
**General rule:** before source-aliasing a package, scan its `src/` for
|
||||
non-relative imports and check whether any of those are CJS-only (no
|
||||
`"type": "module"`, no ESM `exports` map, uses `module.exports`). If so,
|
||||
add the exact import path to `optimizeDeps.include`.
|
||||
|
||||
5. **Do not set `treeshake.moduleSideEffects: false` globally**
|
||||
|
||||
Setting it globally tells Rollup every module is pure and eliminates any
|
||||
@ -272,22 +306,83 @@ Before applying this technique to any library, verify:
|
||||
|
||||
---
|
||||
|
||||
## rolldown-vite
|
||||
|
||||
[Rolldown](https://rolldown.rs) is a Rust-powered bundler designed as a drop-in
|
||||
replacement for Rollup. Vite is migrating to it officially; in the meantime it
|
||||
is available as the separate package `rolldown-vite`.
|
||||
|
||||
### Installing
|
||||
|
||||
Use the `npm:` package alias so `vite` resolves to `rolldown-vite` everywhere —
|
||||
plugins and scripts continue to `import from 'vite'` unchanged:
|
||||
|
||||
```json
|
||||
"devDependencies": {
|
||||
"vite": "npm:rolldown-vite@7.3.1"
|
||||
}
|
||||
```
|
||||
|
||||
> **Pin the version.** `rolldown-vite` is experimental and may introduce
|
||||
> breaking changes in patch releases.
|
||||
> Do not use `@latest` in committed config.
|
||||
|
||||
Do **not** use `"overrides"` alongside a direct `vite` devDependency — npm
|
||||
rejects the conflict.
|
||||
|
||||
### What changes
|
||||
|
||||
| Area | Before (Rollup/esbuild) | After (Rolldown) |
|
||||
|---|---|---|
|
||||
| Production bundler | Rollup | Rolldown (Rust) |
|
||||
| Dep pre-bundler | esbuild | Rolldown |
|
||||
| CJS interop | `@rollup/plugin-commonjs` | Rolldown native |
|
||||
| JS minifier | esbuild | Oxc |
|
||||
| CSS minifier | esbuild | Lightning CSS |
|
||||
|
||||
### Config notes
|
||||
|
||||
`rollupOptions.output.format` is a Rollup-only option not recognised by
|
||||
Rolldown — remove it. Rolldown outputs ES modules by default, so no
|
||||
replacement is needed.
|
||||
|
||||
### Benchmark
|
||||
|
||||
| | Build time | Main JS gzip |
|
||||
|---|---|---|
|
||||
| Vite 5 + Rollup | ~1100 ms | 46.4 kB |
|
||||
| rolldown-vite 7 | **331 ms** | **45.8 kB** |
|
||||
|
||||
**3× faster build**, marginally smaller output. Dev server cold-start also
|
||||
drops from ~730 ms to ~557 ms.
|
||||
|
||||
### Known limitations
|
||||
|
||||
- Some Rollup output options produce validation warnings (unknown keys).
|
||||
Remove options that Rolldown handles by default (`format: "es"`, etc.).
|
||||
- `manualChunks` is deprecated in favour of Rolldown's `advancedChunks`.
|
||||
- The `transformWithEsbuild` Vite helper now requires `esbuild` installed
|
||||
separately (Rolldown uses Oxc internally).
|
||||
|
||||
See the [official rolldown-vite docs](https://vite.dev/guide/rolldown) for the
|
||||
full compatibility matrix.
|
||||
|
||||
---
|
||||
|
||||
## Build targets and module format
|
||||
|
||||
```ts
|
||||
build: {
|
||||
target: "esnext", // no transpilation downgrade, modern browsers only
|
||||
modulePreload: { polyfill: false }, // drop the ~1.6 kB modulepreload polyfill
|
||||
rollupOptions: {
|
||||
output: { format: "es" }, // native ESM output
|
||||
},
|
||||
// format defaults to "es" in rolldown-vite — no rollupOptions needed
|
||||
}
|
||||
```
|
||||
|
||||
`target: "esnext"` + `format: "es"` means no CommonJS wrapper, no legacy
|
||||
syntax transforms, and native dynamic `import()` for code splitting.
|
||||
`modulePreload: { polyfill: false }` removes the small polyfill that is
|
||||
irrelevant for modern browsers.
|
||||
`target: "esnext"` means no legacy syntax transforms and native dynamic
|
||||
`import()` for code splitting.
|
||||
`modulePreload: { polyfill: false }` removes the small polyfill irrelevant for
|
||||
modern browsers.
|
||||
|
||||
---
|
||||
|
||||
|
||||
842
packages/ui-next/package-lock.json
generated
842
packages/ui-next/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,6 @@
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^5.4.11"
|
||||
"vite": "npm:rolldown-vite@7.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,20 +36,29 @@ export default defineConfig({
|
||||
{ find: "@tanstack/react-router", replacement: nm("@tanstack/react-router/src/index.tsx") },
|
||||
{ find: "@tanstack/history", replacement: nm("@tanstack/history/src/index.ts") },
|
||||
{ find: "@tanstack/store", replacement: nm("@tanstack/store/src/index.ts") },
|
||||
{ find: "@tanstack/react-store", replacement: nm("@tanstack/react-store/src/index.ts") },
|
||||
// @tanstack/react-store is NOT source-aliased: its src/useStore.ts imports
|
||||
// use-sync-external-store/shim/with-selector (CJS-only). The pre-built
|
||||
// dist/esm already has that CJS dep inlined as ESM — no interop needed.
|
||||
|
||||
{ find: "@", replacement: path.resolve(__dirname, "src") },
|
||||
],
|
||||
},
|
||||
// Don't pre-bundle the tanstack packages — let Rollup see their raw source
|
||||
// Don't pre-bundle the four source-aliased tanstack packages — let Rollup
|
||||
// see their raw TypeScript. @tanstack/react-store is intentionally omitted:
|
||||
// its source pulls in a CJS dep (use-sync-external-store/shim/with-selector)
|
||||
// that Vite can't serve as ESM without pre-bundling, so we leave it on the
|
||||
// pre-built dist/esm path where the CJS is already inlined.
|
||||
optimizeDeps: {
|
||||
exclude: [
|
||||
"@tanstack/router-core",
|
||||
"@tanstack/react-router",
|
||||
"@tanstack/history",
|
||||
"@tanstack/store",
|
||||
"@tanstack/react-store",
|
||||
],
|
||||
// use-sync-external-store ships CJS only. Vite cannot serve it as ESM
|
||||
// without pre-bundling — include the exact subpath that @tanstack/react-store
|
||||
// imports so the pre-bundler wraps it and named imports work in dev.
|
||||
include: ["use-sync-external-store/shim/with-selector"],
|
||||
},
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
@ -65,8 +74,7 @@ export default defineConfig({
|
||||
build: {
|
||||
target: "esnext",
|
||||
modulePreload: { polyfill: false },
|
||||
rollupOptions: {
|
||||
output: { format: "es" },
|
||||
},
|
||||
// rollupOptions.output.format is a Rollup-only option not supported by Rolldown;
|
||||
// Rolldown outputs ES modules by default so it's not needed.
|
||||
},
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user