@bleedingdev/modern-js-create 3.2.0-ultramodern.97 ā 3.2.0-ultramodern.98
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/bin/run.js +0 -0
- package/package.json +3 -3
- package/template/.agents/skills-lock.json +0 -34
- package/template/.browserslistrc +0 -4
- package/template/.codex/hooks.json +0 -16
- package/template/.github/renovate.json +0 -53
- package/template/.github/workflows/ultramodern-gates.yml.handlebars +0 -54
- package/template/.gitignore.handlebars +0 -30
- package/template/.mise.toml.handlebars +0 -2
- package/template/.nvmrc +0 -2
- package/template-workspace/.agents/agent-reference-repos.json +0 -24
- package/template-workspace/.agents/rstackjs-agent-skills-LICENSE +0 -21
- package/template-workspace/.agents/skills/rsbuild-best-practices/SKILL.md +0 -57
- package/template-workspace/.agents/skills/rsdoctor-analysis/SKILL.md +0 -96
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/command-map.md +0 -113
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/common-analysis-patterns.md +0 -190
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor-common.md +0 -88
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor-rspack.md +0 -138
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor-webpack.md +0 -71
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/install-rsdoctor.md +0 -39
- package/template-workspace/.agents/skills/rsdoctor-analysis/references/rsdoctor-data-types.md +0 -103
- package/template-workspace/.agents/skills/rslib-best-practices/SKILL.md +0 -58
- package/template-workspace/.agents/skills/rslib-modern-package/SKILL.md +0 -173
- package/template-workspace/.agents/skills/rspack-best-practices/SKILL.md +0 -70
- package/template-workspace/.agents/skills/rspack-tracing/SKILL.md +0 -75
- package/template-workspace/.agents/skills/rspack-tracing/references/bottlenecks.md +0 -47
- package/template-workspace/.agents/skills/rspack-tracing/references/tracing-guide.md +0 -38
- package/template-workspace/.agents/skills/rspack-tracing/scripts/analyze_trace.js +0 -184
- package/template-workspace/.agents/skills/rstest-best-practices/SKILL.md +0 -133
- package/template-workspace/.agents/skills-lock.json +0 -114
- package/template-workspace/.codex/hooks.json +0 -16
- package/template-workspace/.github/renovate.json +0 -29
- package/template-workspace/.github/workflows/ultramodern-workspace-gates.yml.handlebars +0 -54
- package/template-workspace/.gitignore.handlebars +0 -5
- package/template-workspace/.mise.toml.handlebars +0 -2
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rslib-best-practices
|
|
3
|
-
description: Rslib best practices for config, CLI workflow, output, declaration files, dependency handling, build optimization and toolchain integration. Use when writing, reviewing, or troubleshooting Rslib projects.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rslib Best Practices
|
|
7
|
-
|
|
8
|
-
Apply these rules when writing or reviewing Rslib library projects.
|
|
9
|
-
|
|
10
|
-
## Configuration
|
|
11
|
-
|
|
12
|
-
- Use `rslib.config.ts` and `defineConfig`
|
|
13
|
-
- Check Rslib-specific configurations first (e.g., `lib.*`), and also leverage Rsbuild configurations (e.g., `source.*`, `output.*`, `tools.*`) as needed
|
|
14
|
-
- For deep-level or advanced configuration needs, use `tools.rspack` or `tools.bundlerChain` to access Rspack's native configurations
|
|
15
|
-
- In TypeScript projects, prefer `tsconfig.json` path aliases
|
|
16
|
-
|
|
17
|
-
## CLI
|
|
18
|
-
|
|
19
|
-
- Use `rslib` to build
|
|
20
|
-
- Use `rslib --watch` to build in watch mode for local development
|
|
21
|
-
- Use `rslib inspect` to inspect final Rslib/Rsbuild/Rspack configs
|
|
22
|
-
|
|
23
|
-
## Output
|
|
24
|
-
|
|
25
|
-
- Prefer to build pure-ESM package with `"type": "module"` in `package.json`
|
|
26
|
-
- Prefer to use bundleless mode with `output.target` set to `'web'` when building component libraries
|
|
27
|
-
- Prefer to use bundle mode when building Node.js utility libraries
|
|
28
|
-
- Ensure `exports` field in `package.json` is correctly configured and matches the actual JavaScript output and declaration files output of different formats (ESM, CJS, etc.)
|
|
29
|
-
|
|
30
|
-
## Declaration files
|
|
31
|
-
|
|
32
|
-
- Prefer to enable declaration file generation with `lib.dts: true` or detailed configurations
|
|
33
|
-
- For faster type generation, enable `lib.dts.tsgo` experimental feature with `@typescript/native-preview` installed
|
|
34
|
-
|
|
35
|
-
## Dependencies
|
|
36
|
-
|
|
37
|
-
- Prefer to place dependencies to be bundled in `devDependencies` in bundle mode and dependencies in `dependencies` and `peerDependencies` will be automatically externalized (not bundled) by default
|
|
38
|
-
- Verify the build output and dependency specifiers in `package.json` carefully to ensure no missing dependency errors occur when consumers install and use this package
|
|
39
|
-
|
|
40
|
-
## Build optimization
|
|
41
|
-
|
|
42
|
-
- Keep syntax target in `lib.syntax` aligned with real compatibility requirements to enable better optimizations
|
|
43
|
-
- Avoid format-specific APIs in source code for better compatibility with different output formats
|
|
44
|
-
- Prefer lightweight dependencies to reduce bundle size
|
|
45
|
-
|
|
46
|
-
## Toolchain integration
|
|
47
|
-
|
|
48
|
-
- Prefer to use Rstest with `@rstest/adapter-rslib` for writing tests
|
|
49
|
-
- Prefer to use Rspress for writing library documentation, with `@rspress/plugin-preview` and `@rspress/plugin-api-docgen` for component previews and API docs
|
|
50
|
-
|
|
51
|
-
## Debugging
|
|
52
|
-
|
|
53
|
-
- Run with `DEBUG=rsbuild` when diagnosing config resolution or plugin behavior
|
|
54
|
-
- Read generated files in `dist/.rsbuild` to confirm final Rsbuild/Rspack config, not assumed config
|
|
55
|
-
|
|
56
|
-
## Documentation
|
|
57
|
-
|
|
58
|
-
- For the latest Rslib docs, read https://rslib.rs/llms.txt
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rslib-modern-package
|
|
3
|
-
description: Opinionated Rslib recommendations for modern JS/TS npm package design covering pure ESM, strict TypeScript, explicit exports, small stable APIs, pragmatic dependencies, accurate sideEffects, correct declarations, package validation, provenance, README.md, and AGENTS.md. Use when the user wants to make a JS/TS package more modern, check whether the current package setup is healthy, review package.json/exports/types/dependencies/docs/release readiness, or apply a modern library baseline.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rslib Modern Package
|
|
7
|
-
|
|
8
|
-
Use this skill when creating a new Rslib library, modernizing an existing JS/TS package, or reviewing a package against an opinionated modern library standard.
|
|
9
|
-
|
|
10
|
-
This skill is opinionated: it describes a recommended modern package contract and may suggest breaking changes when they make the package simpler, safer, and easier for modern consumers.
|
|
11
|
-
|
|
12
|
-
## Standard
|
|
13
|
-
|
|
14
|
-
Default recommendation for new JS/TS libraries:
|
|
15
|
-
|
|
16
|
-
- ESM-first, preferably pure ESM.
|
|
17
|
-
- Strict TypeScript and correct declaration files.
|
|
18
|
-
- Explicit public API through `package.json#exports`.
|
|
19
|
-
- Small named-export API surface.
|
|
20
|
-
- Few runtime dependencies, without treating zero dependencies as a religion.
|
|
21
|
-
- Small, tree-shakeable output with accurate `sideEffects`.
|
|
22
|
-
- Clear dependency placement: runtime dependencies, peer dependencies, optional dependencies, and dev dependencies are not interchangeable.
|
|
23
|
-
- Published package is tested as an artifact, not just as source files.
|
|
24
|
-
- Release flow is automated, traceable, and SemVer-aware.
|
|
25
|
-
- README.md explains usage for humans; AGENTS.md preserves package invariants for future agents.
|
|
26
|
-
|
|
27
|
-
## Workflow
|
|
28
|
-
|
|
29
|
-
1. **Inspect the package contract first**
|
|
30
|
-
- Read `package.json`, lockfile/package manager, `rslib.config.*`, `tsconfig*`, CI/release config, README.md, AGENTS.md, and existing `dist` output.
|
|
31
|
-
- Identify package kind: Node utility, browser library, isomorphic utility, CLI, UI/component library, framework plugin, SDK, or adapter.
|
|
32
|
-
- List supported runtimes, current entry points, deep imports, runtime dependencies, peer dependencies, optional integrations, files with side effects, and published files.
|
|
33
|
-
- Run `npm pack --dry-run` early when changing package shape so the real tarball contents guide the review.
|
|
34
|
-
|
|
35
|
-
2. **Define target environments explicitly**
|
|
36
|
-
- Do not say "supports modern environments" without defining them.
|
|
37
|
-
- Verify the current Node.js release schedule before choosing `engines`.
|
|
38
|
-
- As of May 9, 2026, Node.js 22 and 24 are LTS, and Node.js 20 is EOL. For new Node-facing packages, recommend `engines.node >=22` unless real consumers need an older runtime.
|
|
39
|
-
- Browser packages should state whether they require native ESM, a bundler, Workers support, SSR compatibility, DOM APIs, CSS processing, or specific browser baselines.
|
|
40
|
-
- Compatibility drops are breaking changes: old Node/browser versions, undocumented deep imports, default/named export shape, bundled vs external dependency behavior, and import side effects.
|
|
41
|
-
|
|
42
|
-
3. **Prefer pure ESM, but explain compatibility cost**
|
|
43
|
-
- New packages should use `"type": "module"` and ESM source/output.
|
|
44
|
-
- Rslib's default format is ESM; keep that default unless there is a clear reason to add another format.
|
|
45
|
-
- Evaluate compatibility from real consumers and supported runtimes instead of assuming every historical module format is required.
|
|
46
|
-
- Modern Node.js can load synchronous ESM from CommonJS via `require(esm)`; do not assume CJS consumers always require a separate CJS build.
|
|
47
|
-
- If you rely on `require(esm)` compatibility, document and test its constraints: supported Node versions, no top-level `await` in the loaded graph, namespace-object return shape, default export behavior, and CJS/ESM cycle limits.
|
|
48
|
-
- Prefer Node built-in specifiers such as `node:fs/promises`.
|
|
49
|
-
|
|
50
|
-
4. **Make `exports` the public API**
|
|
51
|
-
- Treat `package.json#exports` as the product contract.
|
|
52
|
-
- Export only paths users are meant to import.
|
|
53
|
-
- Do not allow imports like `pkg/dist/foo.js` by exporting `./dist/*`. That makes the generated output layout part of the public API and turns internal file moves into breaking changes.
|
|
54
|
-
- Instead, expose only intentional public paths such as `pkg` and `pkg/foo.js`, mapped to the actual files in `dist`.
|
|
55
|
-
- Keep subpath style consistent: either all with extensions such as `./foo.js`, or all without extensions. Prefer paths with extensions when browser import maps matter.
|
|
56
|
-
- Keep `"types"` first inside conditional exports.
|
|
57
|
-
- Adding `exports` to an older package can be breaking because undeclared deep imports stop working.
|
|
58
|
-
- Add `./package.json` only when consumers legitimately need package metadata.
|
|
59
|
-
|
|
60
|
-
5. **Design a small API surface**
|
|
61
|
-
- Prefer named exports for multi-API packages.
|
|
62
|
-
- Avoid default-export objects that gather every function into one object.
|
|
63
|
-
- Public functions should be few, stable, well-named, and semver-maintained.
|
|
64
|
-
- Keep internal types, caches, helper functions, adapter details, and error internals private unless they are part of the contract.
|
|
65
|
-
- Avoid top-level work during import: file scans, network calls, timers, process mutation, global registration, DOM access, prototype mutation, or environment detection with side effects.
|
|
66
|
-
- Async APIs that may be canceled should accept `AbortSignal`.
|
|
67
|
-
- Prefer stable error classes, error codes, or typed error shapes over string matching.
|
|
68
|
-
|
|
69
|
-
6. **Use Rslib as the implementation path, not the whole standard**
|
|
70
|
-
- For detailed Rslib configuration guidance, use the `rslib-best-practices` skill.
|
|
71
|
-
- In this skill, only check whether Rslib output, declarations, `package.json#exports`, `files`, dependencies, and docs agree with the modern package contract.
|
|
72
|
-
- Keep Rslib configuration small and intentional; avoid adding build complexity that does not improve the package contract.
|
|
73
|
-
|
|
74
|
-
7. **Keep dependencies small and intentional**
|
|
75
|
-
- Start from platform APIs, not from dependency search.
|
|
76
|
-
- Prefer built-ins when the runtime supports them: `URL`, `URLSearchParams`, `Intl`, `fetch`, `AbortController`, `structuredClone`, `crypto.randomUUID`, Web Streams, `TextEncoder`, `TextDecoder`, `node:fs/promises`, and `node:crypto`.
|
|
77
|
-
- Small runtime dependencies are fine when they reduce maintenance risk or implementation complexity.
|
|
78
|
-
- Avoid large utility packages for one or two helpers.
|
|
79
|
-
- Evaluate dependencies for ESM support, `exports`, types, transitive dependency count, package size, license, maintenance activity, security history, install scripts, side effects, native install fragility, and granular imports.
|
|
80
|
-
- Put required runtime packages in `dependencies`.
|
|
81
|
-
- Put host-owned frameworks and toolchains in `peerDependencies`, such as React, Vue, Svelte, Rspack, Rsbuild, webpack, TypeScript, and framework runtimes.
|
|
82
|
-
- Keep peer ranges reasonably broad; do not pin peers to a patch version unless required.
|
|
83
|
-
- Put build tools, test tools, type tools, docs tools, and Rsbuild/Rspack plugins in `devDependencies`.
|
|
84
|
-
- Use `optionalDependencies` or optional peers via `peerDependenciesMeta` for optional integrations.
|
|
85
|
-
|
|
86
|
-
8. **Make TypeScript strict and package-oriented**
|
|
87
|
-
- Prefer TypeScript source for TS libraries; otherwise use high-quality JSDoc plus generated declarations.
|
|
88
|
-
- With TypeScript 6 or tsgo-era defaults, strict checking may already be enabled; preserve that default and do not turn it off. For older TypeScript versions or inherited configs, set `strict: true` explicitly.
|
|
89
|
-
- In Rslib projects, consider enabling `lib.dts.tsgo` to speed up declaration generation when the project can use tsgo.
|
|
90
|
-
- Keep `module` and `moduleResolution` aligned with how declarations are emitted and how consumers resolve the package; NodeNext and bundler-style resolution are both valid in the right toolchain.
|
|
91
|
-
- Use `verbatimModuleSyntax` so type-only imports/exports are explicit.
|
|
92
|
-
- Use `isolatedDeclarations` when practical so exported APIs are explicit enough for declaration-oriented tooling.
|
|
93
|
-
- Emit declarations; use declaration maps when editor navigation matters.
|
|
94
|
-
- Use `import type` and `export type` for type-only dependencies.
|
|
95
|
-
- Do not rely on consumers setting `skipLibCheck` to hide broken package types.
|
|
96
|
-
- Test declarations as consumers see them, especially when using subpath exports.
|
|
97
|
-
|
|
98
|
-
9. **Keep `sideEffects` accurate**
|
|
99
|
-
- Use `sideEffects: false` only when importing package files has no top-level side effects.
|
|
100
|
-
- If CSS, polyfills, registrations, global listeners, prototype changes, or other import-time mutations exist, list the files with side effects instead.
|
|
101
|
-
- Do not set `sideEffects: false` just to improve bundle size; incorrect values can remove required CSS or setup code.
|
|
102
|
-
- Do not change globals just because a file is imported. If setup is required, expose an explicit `setup()` or `install()` function and let users call it themselves.
|
|
103
|
-
|
|
104
|
-
10. **Make `package.json` authoritative**
|
|
105
|
-
- Required modern shape: `"type": "module"`, explicit `exports`, correct declarations, `files` allowlist, accurate `sideEffects`, sensible `engines`, and release scripts.
|
|
106
|
-
- Include README.md, AGENTS.md, and LICENSE in `files` when they exist.
|
|
107
|
-
- `files` should prevent tests, fixtures, private docs, build caches, local configs, and large generated artifacts from leaking into the tarball.
|
|
108
|
-
- Avoid stale `main`/`module` fields unless compatibility evidence requires them; if kept, they must agree with `exports`.
|
|
109
|
-
- Keep runtime dependency fields accurate. A package that works locally only because a runtime dependency is in `devDependencies` is broken.
|
|
110
|
-
|
|
111
|
-
11. **Validate the published artifact**
|
|
112
|
-
- Run normal lint, typecheck, tests, and `rslib build`.
|
|
113
|
-
- Smoke test built ESM output.
|
|
114
|
-
- Run type-level tests when the public API is type-heavy.
|
|
115
|
-
- Run `npm pack --dry-run` and inspect included files.
|
|
116
|
-
- In Rslib, prefer `rsbuild-plugin-publint` to run publint after build; use `npx publint` as a CLI fallback.
|
|
117
|
-
- In Rslib, prefer `rsbuild-plugin-arethetypeswrong` to run Are The Types Wrong after build when declarations are shipped; use `npx --yes @arethetypeswrong/cli --pack .` as a CLI fallback.
|
|
118
|
-
- Install the packed tarball into clean consumer fixtures for important packages.
|
|
119
|
-
- Test ESM import, bundler import for browser/component libraries, CLI execution for `bin` packages, and every public subpath export.
|
|
120
|
-
|
|
121
|
-
12. **Prepare README.md and AGENTS.md before publishing**
|
|
122
|
-
- Always check whether both files exist before publishing or modernizing a package.
|
|
123
|
-
- If either file is missing, recommend adding it; for implementation tasks, create a concise version unless the user asks not to.
|
|
124
|
-
- README.md should include: package name, one-sentence purpose, install/usage, key features or API links, supported environments, docs/related links, changelog or contribution link, and license.
|
|
125
|
-
- AGENTS.md should include: stack, package contract, common commands, source layout, code style, validation commands, and release checklist.
|
|
126
|
-
- Keep both files synchronized with `package.json#exports`, supported runtimes, and actual Rslib output.
|
|
127
|
-
|
|
128
|
-
13. **Publish with supply-chain hygiene**
|
|
129
|
-
- Follow SemVer and document breaking changes.
|
|
130
|
-
- Maintain a changelog for user-visible changes.
|
|
131
|
-
- Use prerelease versions and dist-tags for beta/next channels.
|
|
132
|
-
- Prefer CI publishing with npm provenance or trusted publishing.
|
|
133
|
-
- Avoid long-lived publish tokens where trusted publishing is available.
|
|
134
|
-
- Remember that a published package name/version pair cannot be reused safely.
|
|
135
|
-
|
|
136
|
-
## Review Red Flags
|
|
137
|
-
|
|
138
|
-
- `exports` is missing, points to files not emitted by Rslib, or allows public imports such as `pkg/dist/foo.js`.
|
|
139
|
-
- `module`/`main` fields disagree with `exports`.
|
|
140
|
-
- Type declarations do not match runtime entry points.
|
|
141
|
-
- Runtime dependency is accidentally listed only in `devDependencies`.
|
|
142
|
-
- React/Vue/Svelte/Rspack/Rsbuild/webpack/TypeScript is bundled or placed in `dependencies` when it should be a peer.
|
|
143
|
-
- `sideEffects: false` is set while importing CSS, polyfills, global registrations, global listeners, or prototype changes.
|
|
144
|
-
- Package has install scripts without a strong reason.
|
|
145
|
-
- Top-level import reads user files, starts timers, touches the network, mutates globals, or assumes `window`/`process`.
|
|
146
|
-
- Published tarball contains private source maps, tests/fixtures that are not useful to consumers, large generated docs, local config secrets, or build caches.
|
|
147
|
-
|
|
148
|
-
## Checklist
|
|
149
|
-
|
|
150
|
-
- [ ] Supported environments are explicit.
|
|
151
|
-
- [ ] Package is ESM-first, preferably pure ESM.
|
|
152
|
-
- [ ] `package.json` has `"type": "module"`.
|
|
153
|
-
- [ ] Public entry points are declared in `exports`.
|
|
154
|
-
- [ ] No accidental reliance on undeclared deep imports.
|
|
155
|
-
- [ ] Rslib output, declarations, `exports`, and `files` agree.
|
|
156
|
-
- [ ] TypeScript strict mode is enabled.
|
|
157
|
-
- [ ] Declarations are emitted and validated.
|
|
158
|
-
- [ ] Runtime dependencies are justified and small.
|
|
159
|
-
- [ ] Host frameworks/toolchains are peers.
|
|
160
|
-
- [ ] Build/test/type/docs tools are dev dependencies.
|
|
161
|
-
- [ ] `sideEffects` is accurate.
|
|
162
|
-
- [ ] `npm pack --dry-run` has been inspected.
|
|
163
|
-
- [ ] `publint` passes.
|
|
164
|
-
- [ ] Are The Types Wrong check passes when declarations are shipped.
|
|
165
|
-
- [ ] Built ESM smoke test passes.
|
|
166
|
-
- [ ] README.md exists.
|
|
167
|
-
- [ ] AGENTS.md exists.
|
|
168
|
-
- [ ] Release flow uses SemVer, changelog, and provenance/trusted publishing when available.
|
|
169
|
-
|
|
170
|
-
## Documentation
|
|
171
|
-
|
|
172
|
-
- For the latest Rslib docs, read https://rslib.rs/llms.txt
|
|
173
|
-
- Shipping ESM for CommonJS consumers: https://nodejs.github.io/package-examples/04-cjs-esm-interop/shipping-esm-for-cjs/
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rspack-best-practices
|
|
3
|
-
description: Rspack best practices for config, CLI workflow, type checking, CSS, bundle optimization, assets and profiling. Use when writing, reviewing, or troubleshooting Rspack projects.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rspack Best Practices
|
|
7
|
-
|
|
8
|
-
Apply these rules when writing or reviewing Rspack projects.
|
|
9
|
-
|
|
10
|
-
## Configuration
|
|
11
|
-
|
|
12
|
-
- Use `rspack.config.ts` and `defineConfig`
|
|
13
|
-
- Define explicit `entry` values for multi-page applications
|
|
14
|
-
- Keep one main config and branch by `process.env.NODE_ENV` only when needed
|
|
15
|
-
- Keep rule conditions narrow and explicit (`test`, `include`, `exclude`, `resourceQuery`)
|
|
16
|
-
- Prefer built-in Rspack plugins/loaders over community JS alternatives when equivalent features exist
|
|
17
|
-
|
|
18
|
-
## CLI
|
|
19
|
-
|
|
20
|
-
If `@rspack/cli` is installed:
|
|
21
|
-
|
|
22
|
-
- Use `rspack dev` for local development
|
|
23
|
-
- Use `rspack build` for production build
|
|
24
|
-
- Use `rspack preview` only for local production preview
|
|
25
|
-
|
|
26
|
-
## Type checking
|
|
27
|
-
|
|
28
|
-
- Use `ts-checker-rspack-plugin` for integrated dev/build type checks
|
|
29
|
-
- Or run `tsc --noEmit`/`vue-tsc --noEmit` as an explicit script step
|
|
30
|
-
|
|
31
|
-
## CSS
|
|
32
|
-
|
|
33
|
-
Choose one strategy:
|
|
34
|
-
|
|
35
|
-
- Built-in CSS (`type: 'css' | 'css/auto' | 'css/module'`) for modern setups
|
|
36
|
-
- `css-loader` + `CssExtractRspackPlugin` for webpack migration compatibility
|
|
37
|
-
- `style-loader` for pure style-in-JS runtime injection scenarios
|
|
38
|
-
|
|
39
|
-
Optional:
|
|
40
|
-
|
|
41
|
-
- Use `builtin:lightningcss-loader` when goals are syntax downgrade + vendor prefixing
|
|
42
|
-
- Use `sass-loader`/`less-loader` for preprocessing Sass/Less files
|
|
43
|
-
- Use `@tailwindcss/webpack` for Tailwind CSS integration
|
|
44
|
-
|
|
45
|
-
## Bundle size optimization
|
|
46
|
-
|
|
47
|
-
- Prefer dynamic `import()` for non-critical code paths
|
|
48
|
-
- Prefer lightweight libraries where possible
|
|
49
|
-
- Keep `target` aligned with real compatibility requirements
|
|
50
|
-
|
|
51
|
-
## Asset management
|
|
52
|
-
|
|
53
|
-
- Import source-managed assets from project source directories, not from `public`
|
|
54
|
-
- Reference `public` files by absolute URL path
|
|
55
|
-
- Prefer asset modules (`asset`, `asset/resource`, `asset/inline`, `asset/source`) over legacy `file-loader`/`url-loader`/`raw-loader`
|
|
56
|
-
|
|
57
|
-
## Profiling
|
|
58
|
-
|
|
59
|
-
- Use Node CPU profiling (`--cpu-prof`) when JavaScript-side overhead is suspected
|
|
60
|
-
- Use `RSPACK_PROFILE=OVERVIEW` and analyze trace output for compiler-phase bottlenecks
|
|
61
|
-
- Replace known slow stacks first (`babel-loader`, PostCSS, terser) with Rspack built-ins when feasible
|
|
62
|
-
|
|
63
|
-
## Security
|
|
64
|
-
|
|
65
|
-
- Do not publish `.map` files to public servers/CDNs when production source maps are enabled
|
|
66
|
-
|
|
67
|
-
## Documentation
|
|
68
|
-
|
|
69
|
-
- For the latest (v2) docs, read http://rspack.rs/llms.txt
|
|
70
|
-
- For Rspack v1 docs, read http://v1.rspack.rs/llms.txt
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rspack-tracing
|
|
3
|
-
description: Comprehensive guide and toolkit for diagnosing Rspack build issues. Quickly identify where crashes/errors occur, or perform detailed performance profiling to resolve bottlenecks. Use when the user encounters build failures, slow builds, or wants to optimize Rspack performance.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rspack Tracing & Performance Profiling
|
|
7
|
-
|
|
8
|
-
## When to Use This Skill
|
|
9
|
-
|
|
10
|
-
Use this skill when you need to:
|
|
11
|
-
|
|
12
|
-
1. Diagnose why an Rspack build is slow.
|
|
13
|
-
2. Understand which plugins or loaders are taking the most time.
|
|
14
|
-
3. Analyze a user-provided Rspack trace file.
|
|
15
|
-
4. Guide a user to capture a performance profile.
|
|
16
|
-
|
|
17
|
-
## Workflow
|
|
18
|
-
|
|
19
|
-
### 1. Capture a Trace
|
|
20
|
-
|
|
21
|
-
First, ask the user to run their build with tracing enabled.
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
# Set environment variables for logging to a file
|
|
25
|
-
RSPACK_PROFILE=TRACE RSPACK_TRACE_LAYER=logger RSPACK_TRACE_OUTPUT=./trace.json pnpm build
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
This will generate a trace file in a timestamped directory like `.rspack-profile-{timestamp}-{pid}/trace.json`.
|
|
29
|
-
|
|
30
|
-
See [references/tracing-guide.md](references/tracing-guide.md) for more details on configuration.
|
|
31
|
-
|
|
32
|
-
### 2. Quick Diagnosis for Crashes/Errors
|
|
33
|
-
|
|
34
|
-
If the user wants to identify **which stage a crash or error occurred in**, use `tail` to quickly view the last events without running the full analysis:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Navigate to the generated profile directory
|
|
38
|
-
cd .rspack-profile-*/
|
|
39
|
-
|
|
40
|
-
# View the last 20 events to see where the build failed
|
|
41
|
-
tail -n 20 trace.json
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
The last events will show the span names and targets where the build stopped, helping to quickly pinpoint the problematic stage, plugin, or loader.
|
|
45
|
-
|
|
46
|
-
### 3. Full Performance Analysis
|
|
47
|
-
|
|
48
|
-
For detailed performance profiling (not just crash diagnosis), ask the user to run the bundled analysis script on the generated trace file.
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
# Navigate to the generated profile directory
|
|
52
|
-
cd .rspack-profile-*/
|
|
53
|
-
|
|
54
|
-
# Run the analysis script
|
|
55
|
-
node ${CLAUDE_PLUGIN_ROOT}/skills/tracing/scripts/analyze_trace.js trace.json
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### 4. Interpret Results
|
|
59
|
-
|
|
60
|
-
Use the output from the script to identify bottlenecks.
|
|
61
|
-
Consult [references/bottlenecks.md](references/bottlenecks.md) to map span names to actionable fixes.
|
|
62
|
-
|
|
63
|
-
### 5. Locate Slow Plugins
|
|
64
|
-
|
|
65
|
-
Based on the "Top Slowest Hooks" from the analysis script:
|
|
66
|
-
|
|
67
|
-
1. **Identify the Hook**: Note the hook name (e.g., `hook:CompilationOptimizeChunks`).
|
|
68
|
-
2. **Inspect Configuration**: Read `rspack.config.js` or `rsbuild.config.ts`.
|
|
69
|
-
3. **Map Hook to Plugin**: Look for plugins and their sources that tap into that specific hook.
|
|
70
|
-
4. **Output**: Output the paths, lines and columns of the suspected plugin source code.
|
|
71
|
-
|
|
72
|
-
## Common Scenarios & Quick Fixes
|
|
73
|
-
|
|
74
|
-
- [Bottleneck Reference](references/bottlenecks.md): Mapping spans to concepts.
|
|
75
|
-
- [Tracing Guide](references/tracing-guide.md): Detailed usage of `RSPACK_PROFILE`.
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# Understanding Rspack Performance Bottlenecks
|
|
2
|
-
|
|
3
|
-
This reference maps internal Rspack tracing spans to high-level concepts to help you identify performance issues.
|
|
4
|
-
|
|
5
|
-
## Core Compilation Phases
|
|
6
|
-
|
|
7
|
-
| Span Name | Description | Potential Bottlenecks |
|
|
8
|
-
| :---------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------------------------- |
|
|
9
|
-
| `tracing::profiling` | The entire build process. | Overall slowness. |
|
|
10
|
-
| `compiler::make` | **Make Phase**: Resolving, loading, and parsing modules. | Heavy loaders (babel/swc with complex configs), too many files, slow file system. |
|
|
11
|
-
| `compiler::seal` | **Seal Phase**: Optimizing, splitting chunks, generating code. | Complex code splitting, heavy minification, many modules. |
|
|
12
|
-
| `compiler::emit_assets` | **Emit Phase**: Writing files to disk. | Slow disk I/O, huge output files. |
|
|
13
|
-
|
|
14
|
-
## Detailed Spans
|
|
15
|
-
|
|
16
|
-
### Make Phase (Module Processing)
|
|
17
|
-
|
|
18
|
-
- `resolver::resolve`: Resolving import paths.
|
|
19
|
-
- **High Time?**: Check for complex `resolve.alias` or `resolve.modules`, or too many standard fallbacks.
|
|
20
|
-
- `loader::run_loaders`: Executing loaders (JavaScript/Rust).
|
|
21
|
-
- **High Time?**: Identify which loader is slow. If `sass-loader` or `babel-loader` is slow, consider caching (`cache: true` in config) or using `swc-loader`.
|
|
22
|
-
- `parser::parse`: Parsing source code into AST.
|
|
23
|
-
- **High Time?**: Large files?
|
|
24
|
-
|
|
25
|
-
### Seal Phase (Optimization)
|
|
26
|
-
|
|
27
|
-
- `compilation::code_generation`: Generating final code from AST.
|
|
28
|
-
- `compilation::optimize_chunks`: Splitting chunks (SplitChunksPlugin).
|
|
29
|
-
- `k_means_splitter`: If you see this, complex splitting logic is running.
|
|
30
|
-
- `js_minimizer`: Minification (SwcJsMinimizer).
|
|
31
|
-
- **High Time?**: Disable minimization in dev (`optimization.minimize: false`) for speed.
|
|
32
|
-
|
|
33
|
-
### General
|
|
34
|
-
|
|
35
|
-
- `read_file`: Reading files from disk.
|
|
36
|
-
- `write_file`: Writing artifacts to disk.
|
|
37
|
-
|
|
38
|
-
## Common Fixes
|
|
39
|
-
|
|
40
|
-
1. **Slow `make` phase**:
|
|
41
|
-
- Use `experiments.cache` (Persistent Cache).
|
|
42
|
-
- Exclude `node_modules` from expensive loaders.
|
|
43
|
-
- Switch to lighter loaders (e.g. `swc-loader` vs `babel-loader`).
|
|
44
|
-
2. **Slow `seal` phase**:
|
|
45
|
-
- Reduce `splitChunks` complexity.
|
|
46
|
-
- Disable `sourcemap` in production if acceptable cost.
|
|
47
|
-
- Upgrade to latest Rspack (performance improvements are frequent).
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Rspack Tracing Guide
|
|
2
|
-
|
|
3
|
-
Tracing allows you to visualize exactly what Rspack is doing during a build.
|
|
4
|
-
|
|
5
|
-
## Enabling Tracing
|
|
6
|
-
|
|
7
|
-
Rspack uses several environment variables to control tracing.
|
|
8
|
-
|
|
9
|
-
**Command:**
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
RSPACK_PROFILE=TRACE RSPACK_TRACE_LAYER=logger RSPACK_TRACE_OUTPUT=./trace.json rspack build
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
### Variables
|
|
16
|
-
|
|
17
|
-
**`RSPACK_PROFILE`**: Controls the granularity of the trace.
|
|
18
|
-
|
|
19
|
-
- `TRACE`: Captures all spans. (Recommended for deep analysis)
|
|
20
|
-
- `DEBUG`, `INFO`, `WARN`, `ERROR`, `CRITICAL`
|
|
21
|
-
- `OFF`: Disables tracing.
|
|
22
|
-
|
|
23
|
-
**`RSPACK_TRACE_LAYER`**: Controls the output format.
|
|
24
|
-
|
|
25
|
-
- `logger`: Outputs standard JSON logging (required for the analysis script).
|
|
26
|
-
|
|
27
|
-
## Output
|
|
28
|
-
|
|
29
|
-
After running the command, Rspack will generate the file specified in `RSPACK_TRACE_OUTPUT`.
|
|
30
|
-
|
|
31
|
-
## Using the Skill's Analysis Tool
|
|
32
|
-
|
|
33
|
-
This skill includes a script to summarize the trace file.
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
# Run the included script
|
|
37
|
-
node scripts/analyze_trace.js <path-to-trace-file>
|
|
38
|
-
```
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
// Parse duration string (e.g., "1.23ms", "456.78µs", "0.12s") to milliseconds
|
|
7
|
-
function parseDuration(durationStr) {
|
|
8
|
-
if (!durationStr) return 0;
|
|
9
|
-
|
|
10
|
-
const match = durationStr.match(/^([\d.]+)(ms|µs|s|ns)$/);
|
|
11
|
-
if (!match) return 0;
|
|
12
|
-
|
|
13
|
-
const value = parseFloat(match[1]);
|
|
14
|
-
const unit = match[2];
|
|
15
|
-
|
|
16
|
-
switch (unit) {
|
|
17
|
-
case 's':
|
|
18
|
-
return value * 1000;
|
|
19
|
-
case 'ms':
|
|
20
|
-
return value;
|
|
21
|
-
case 'µs':
|
|
22
|
-
return value / 1000;
|
|
23
|
-
case 'ns':
|
|
24
|
-
return value / 1000000;
|
|
25
|
-
default:
|
|
26
|
-
return value;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Get trace file path
|
|
31
|
-
const tracePath = process.argv[2] || path.join(__dirname, 'trace.json');
|
|
32
|
-
|
|
33
|
-
if (!fs.existsSync(tracePath)) {
|
|
34
|
-
console.error(`Error: Trace file not found at ${tracePath}`);
|
|
35
|
-
console.error('Usage: node analyze_trace.js <path-to-trace.json>');
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
console.log(`Analyzing trace file: ${tracePath}\n`);
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
const fileContent = fs.readFileSync(tracePath, 'utf8');
|
|
43
|
-
|
|
44
|
-
// Parse line-delimited JSON
|
|
45
|
-
const events = fileContent
|
|
46
|
-
.trim()
|
|
47
|
-
.split('\n')
|
|
48
|
-
.map(line => {
|
|
49
|
-
try {
|
|
50
|
-
return JSON.parse(line);
|
|
51
|
-
} catch (err) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
})
|
|
55
|
-
.filter(Boolean);
|
|
56
|
-
|
|
57
|
-
if (!events.length) {
|
|
58
|
-
console.error('No valid trace events found.');
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.log('=== Rspack Build Performance Analysis ===\n');
|
|
63
|
-
console.log(`Total events: ${events.length}\n`);
|
|
64
|
-
|
|
65
|
-
// Categorize events by target
|
|
66
|
-
const pluginStats = new Map();
|
|
67
|
-
const loaderStats = new Map();
|
|
68
|
-
|
|
69
|
-
events.forEach(event => {
|
|
70
|
-
const target = event.target;
|
|
71
|
-
const timeField = event.fields?.['time.busy'];
|
|
72
|
-
|
|
73
|
-
if (!timeField) return;
|
|
74
|
-
|
|
75
|
-
const duration = parseDuration(timeField);
|
|
76
|
-
|
|
77
|
-
if (target === 'Plugin Analysis') {
|
|
78
|
-
// Plugin performance
|
|
79
|
-
const pluginName = event.span?.name;
|
|
80
|
-
if (!pluginName) return;
|
|
81
|
-
|
|
82
|
-
if (!pluginStats.has(pluginName)) {
|
|
83
|
-
pluginStats.set(pluginName, {
|
|
84
|
-
count: 0,
|
|
85
|
-
total: 0,
|
|
86
|
-
max: 0,
|
|
87
|
-
min: Infinity,
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const stat = pluginStats.get(pluginName);
|
|
92
|
-
stat.count++;
|
|
93
|
-
stat.total += duration;
|
|
94
|
-
stat.max = Math.max(stat.max, duration);
|
|
95
|
-
stat.min = Math.min(stat.min, duration);
|
|
96
|
-
} else if (target === 'Loader Analysis') {
|
|
97
|
-
// Loader performance
|
|
98
|
-
let loaderName = event.span?.name;
|
|
99
|
-
|
|
100
|
-
// For pitch phase (span.name is null), use resource path
|
|
101
|
-
if (!loaderName) {
|
|
102
|
-
const resource = event.fields?.resource;
|
|
103
|
-
if (resource) {
|
|
104
|
-
// Extract filename from resource path
|
|
105
|
-
const cleanResource = resource.replace(/^"|"$/g, ''); // Remove quotes
|
|
106
|
-
const filename = cleanResource.split('/').pop();
|
|
107
|
-
loaderName = `Loader pitch for ${filename}`;
|
|
108
|
-
} else {
|
|
109
|
-
loaderName = 'Loader pitch (unknown resource)';
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!loaderStats.has(loaderName)) {
|
|
114
|
-
loaderStats.set(loaderName, {
|
|
115
|
-
count: 0,
|
|
116
|
-
total: 0,
|
|
117
|
-
max: 0,
|
|
118
|
-
min: Infinity,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const stat = loaderStats.get(loaderName);
|
|
123
|
-
stat.count++;
|
|
124
|
-
stat.total += duration;
|
|
125
|
-
stat.max = Math.max(stat.max, duration);
|
|
126
|
-
stat.min = Math.min(stat.min, duration);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// Display Plugin Analysis
|
|
131
|
-
if (pluginStats.size > 0) {
|
|
132
|
-
console.log('š Plugin Analysis (by name):');
|
|
133
|
-
console.log('ā'.repeat(80));
|
|
134
|
-
|
|
135
|
-
const sortedPlugins = [...pluginStats.entries()].sort(
|
|
136
|
-
(a, b) => b[1].total - a[1].total,
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
sortedPlugins.forEach(([name, stat]) => {
|
|
140
|
-
const avg = stat.total / stat.count;
|
|
141
|
-
console.log(`${name}`);
|
|
142
|
-
console.log(
|
|
143
|
-
` Total: ${stat.total.toFixed(2)}ms | Count: ${stat.count} | ` +
|
|
144
|
-
`Avg: ${avg.toFixed(2)}ms | Max: ${stat.max.toFixed(2)}ms | Min: ${stat.min.toFixed(2)}ms`,
|
|
145
|
-
);
|
|
146
|
-
console.log('');
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
const totalPluginTime = [...pluginStats.values()].reduce(
|
|
150
|
-
(sum, stat) => sum + stat.total,
|
|
151
|
-
0,
|
|
152
|
-
);
|
|
153
|
-
console.log(`Total Plugin Time: ${totalPluginTime.toFixed(2)}ms\n`);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Display Loader Analysis
|
|
157
|
-
if (loaderStats.size > 0) {
|
|
158
|
-
console.log('\nš§ Loader Analysis (by name):');
|
|
159
|
-
console.log('ā'.repeat(80));
|
|
160
|
-
|
|
161
|
-
const sortedLoaders = [...loaderStats.entries()].sort(
|
|
162
|
-
(a, b) => b[1].total - a[1].total,
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
sortedLoaders.forEach(([name, stat]) => {
|
|
166
|
-
const avg = stat.total / stat.count;
|
|
167
|
-
console.log(`${name}`);
|
|
168
|
-
console.log(
|
|
169
|
-
` Total: ${stat.total.toFixed(2)}ms | Count: ${stat.count} | ` +
|
|
170
|
-
`Avg: ${avg.toFixed(2)}ms | Max: ${stat.max.toFixed(2)}ms | Min: ${stat.min.toFixed(2)}ms`,
|
|
171
|
-
);
|
|
172
|
-
console.log('');
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const totalLoaderTime = [...loaderStats.values()].reduce(
|
|
176
|
-
(sum, stat) => sum + stat.total,
|
|
177
|
-
0,
|
|
178
|
-
);
|
|
179
|
-
console.log(`Total Loader Time: ${totalLoaderTime.toFixed(2)}ms\n`);
|
|
180
|
-
}
|
|
181
|
-
} catch (err) {
|
|
182
|
-
console.error('Error processing trace file:', err);
|
|
183
|
-
process.exit(1);
|
|
184
|
-
}
|