diff --git a/.agents/skills/create-draft-release-notes/SKILL.md b/.agents/skills/create-draft-release-notes/SKILL.md index 82b2fa3096..3e33ff01a7 100644 --- a/.agents/skills/create-draft-release-notes/SKILL.md +++ b/.agents/skills/create-draft-release-notes/SKILL.md @@ -1,13 +1,13 @@ --- name: create-draft-release-notes -description: Create or update draft GitHub releases for the current project's main GitHub repository, then organize GitHub-generated release notes into user-friendly sections without rewriting release note items. Use for preparing, formatting, categorizing, creating, or updating GitHub release notes or draft releases, including optional highlights when the user asks for them. +description: Create or update draft GitHub release notes, or output organized Markdown when draft creation is unavailable. Use for release notes, draft releases, release PR checks, npm staged publishing checks, and optional highlights. --- # Create Draft Release Notes ## Overview -Create a GitHub draft release, organize the generated notes by conventional commit type, and save the organized body back to the draft. Preserve each release note item exactly; only split accidentally joined bullets, move bullets into sections, and adjust headings. Add a top `## Highlights` section only when the user explicitly asks for highlights. +Create a GitHub draft release when possible, organize the generated notes by conventional commit type, and save the organized body back to the draft. If `gh` cannot create or edit the draft, return the organized Markdown in the conversation with manual creation steps. Preserve each release note item exactly; only split accidentally joined bullets, move bullets into sections, and adjust headings. Add a top `## Highlights` section only when the user explicitly asks for highlights. ## Security Notes @@ -28,36 +28,59 @@ Input: a release tag/title such as `v2.0.6`. If title and tag differ, ask for th release_title="$release_tag" ``` -3. Verify access and ensure the release does not already exist: +3. Verify access and whether the release already exists: ```bash gh auth status - gh repo view "$repo" --json nameWithOwner --jq '.nameWithOwner' + gh repo view "$repo" --json nameWithOwner,defaultBranchRef,viewerPermission gh release view "$release_tag" -R "$repo" --json tagName,isDraft,url ``` If the release exists, stop unless the user explicitly asked to update that draft. -4. Infer the previous tag: + If `gh` is not logged in, `viewerPermission` is below `WRITE`, or release create/edit later fails for permissions, continue with the [Markdown Fallback Workflow](#markdown-fallback-workflow). + +4. Infer the default branch and previous tag: ```bash + default_branch="$(gh repo view "$repo" --json defaultBranchRef --jq '.defaultBranchRef.name')" previous_tag="$(gh release list -R "$repo" --exclude-drafts --exclude-pre-releases --limit 1 --json tagName --jq '.[0].tagName')" gh release list -R "$repo" --exclude-drafts --exclude-pre-releases --limit 5 ``` Ask for confirmation if the previous tag is missing, surprising, or part of a non-standard range. -5. Before creating anything, state the repo and range: `previous_tag -> release_tag`. If the user did not explicitly ask to create the draft in this turn, ask for confirmation. +5. Check the latest release PR before generating notes. Prefer repository conventions; otherwise search release-like PR titles or branches targeting the default branch. + + ```bash + gh pr list -R "$repo" --base "$default_branch" --state open --search "release in:title" --limit 20 --json number,title,url,headRefName,updatedAt + gh pr list -R "$repo" --base "$default_branch" --state all --search "release in:title" --limit 10 --json number,title,state,mergedAt,url,headRefName,headRefOid,updatedAt + ``` + + If a release PR for this release is still open, or the latest release PR candidate has `mergedAt: null`, stop and ask the user to merge it into the default branch first. + +6. If the repository uses npm staged publishing, verify packages from the latest merged release PR are already live on npm. + + ```bash + rg -n "\b(npm|pnpm)\s+stage(\s+publish)?\b" package.json pnpm-workspace.yaml .github 2>/dev/null + release_pr_number="" + gh pr diff "$release_pr_number" -R "$repo" --name-only | rg '(^|/)package\.json$' + npm view "$package_name@$package_version" version --json + ``` + + For changed public packages, read `name` and `version` from the PR head or merged branch. Skip `"private": true`. If any version is missing from npm, stop and list the missing packages; tell the user to approve the staged packages with `npm stage approve ` or from the npm website's Staged Packages tab, then rerun the workflow. + +7. Before creating anything, state the repo and range: `previous_tag -> release_tag`. If the user did not explicitly ask to create the draft in this turn, ask for confirmation. -6. Create the draft with GitHub-generated notes: +8. Create the draft with GitHub-generated notes: ```bash gh release create "$release_tag" -R "$repo" --draft --generate-notes --notes-start-tag "$previous_tag" --title "$release_title" ``` - Add `--verify-tag` when the release must use an existing remote tag. + Add `--verify-tag` when the release must use an existing remote tag. If this fails because of auth or permissions, switch to the [Markdown Fallback Workflow](#markdown-fallback-workflow). -7. Organize the draft body: +9. Organize the draft body: ```bash tmp_dir="$(mktemp -d)" @@ -65,17 +88,45 @@ Input: a release tag/title such as `v2.0.6`. If title and tag differ, ask for th node .agents/skills/create-draft-release-notes/scripts/create-draft-release-notes.mjs "$tmp_dir/generated.md" > "$tmp_dir/organized.md" ``` -8. Select the final notes file. Use `$tmp_dir/organized.md` by default. If the user asked for highlights, run the [Optional Highlights Workflow](#optional-highlights-workflow), write the result to `$tmp_dir/final.md`, and use that file instead. +10. Select the final notes file. Use `$tmp_dir/organized.md` by default. If the user asked for highlights, run the [Optional Highlights Workflow](#optional-highlights-workflow), write the result to `$tmp_dir/final.md`, and use that file instead. -9. Save the final body: +11. Save the final body: + + ```bash + gh release edit "$release_tag" -R "$repo" --draft --title "$release_title" --notes-file "$tmp_dir/organized.md" + ``` + + Replace `$tmp_dir/organized.md` with `$tmp_dir/final.md` when highlights were generated. If editing fails because of auth or permissions, return the final notes through the [Markdown Fallback Workflow](#markdown-fallback-workflow). + +12. Return the draft URL with `gh release view "$release_tag" -R "$repo" --json url --jq '.url'`. + +## Markdown Fallback Workflow + +Use this whenever `gh` is not logged in or cannot create/edit the draft release. Still run the release PR and staged publishing checks whenever repository metadata is available. + +1. Generate notes without creating a release when read access is available: ```bash - gh release edit "$release_tag" -R "$repo" --draft --title "$release_title" --notes-file "$tmp_dir/organized.md" + tmp_dir="$(mktemp -d)" + gh api "repos/$repo/releases/generate-notes" \ + -f tag_name="$release_tag" \ + -f previous_tag_name="$previous_tag" \ + -f name="$release_title" \ + --jq '.body' > "$tmp_dir/generated.md" + node .agents/skills/create-draft-release-notes/scripts/create-draft-release-notes.mjs "$tmp_dir/generated.md" > "$tmp_dir/organized.md" ``` - Replace `$tmp_dir/organized.md` with `$tmp_dir/final.md` when highlights were generated. + If generated notes cannot be fetched, ask the user to provide the GitHub-generated Markdown or log in with repository read access. + +2. Apply the [Optional Highlights Workflow](#optional-highlights-workflow) if requested. + +3. Return the final Markdown in a fenced `markdown` block and state that no draft was created because of auth or permissions. -10. Return the draft URL with `gh release view "$release_tag" -R "$repo" --json url --jq '.url'`. +4. Give concise manual creation guidance: + - Open `https://github.com///releases/new`. + - Use tag `$release_tag` and title `$release_title`. + - Paste the Markdown body exactly as provided. + - Save it as a draft release after any missing staged npm packages have been approved. ## Markdown-Only Workflow diff --git a/.agents/skills/release-blog-writer/SKILL.md b/.agents/skills/release-blog-writer/SKILL.md index 44b20a6176..26eaa5ca80 100644 --- a/.agents/skills/release-blog-writer/SKILL.md +++ b/.agents/skills/release-blog-writer/SKILL.md @@ -25,7 +25,7 @@ Use the project's existing blog metadata and component conventions. If the produ Each feature section should usually follow this pattern: - Describe the change clearly so readers understand its background, purpose, use cases, and user-facing benefits such as performance gains. -- If a code or configuration example is useful, include one precise and concise example that makes the change easy to understand at a glance. +- Avoid exhaustive API lists; select the key APIs or behaviors readers need, and when useful, use one precise code or configuration example to make the change clear at a glance. ## Headings @@ -33,12 +33,17 @@ Each feature section should usually follow this pattern: - Keep headings short and specific. - Keep anchors stable and readable. - If the website is built with Rspress, use the Rspress anchor syntax, such as `\{#foo-bar}`. + - For multilingual posts, treat the English post as the source of truth for section anchors. Matching headings in other languages should resolve to the same final anchor as the English heading, adding `\{#anchor-id}` when their generated anchor would differ. + - Default English anchors are generated by lowercasing the heading, removing punctuation, replacing whitespace with hyphens, and appending numeric suffixes for duplicates. If the English heading is long or the generated anchor is not stable enough, choose a short semantic custom anchor and apply it to every language version. + - Do not add a custom anchor when it is identical to the default generated anchor. ## Tone - Be professional, direct, and understated. - Avoid vague claims such as "greatly improved" unless the improvement is explained or quantified. +- Avoid slogan-like positioning in feature updates unless intentionally discussing product vision. - Qualify benchmark numbers with enough context to make them credible. +- When presenting performance gains, bold only the key improvement numbers, avoid frequent emphasis, and use tables or images when they make the comparison clearer at a glance. - Use product and ecosystem terms consistently. - Write naturally in the target language; do not let the prose read like a literal translation from another language. @@ -52,6 +57,8 @@ Add links where they help readers continue: Do not over-link common terms. Link the first meaningful occurrence or the option name users are likely to search for. +For Rstack documentation links on `rspack.rs`, `rsbuild.rs`, `rspress.rs`, `rslib.rs`, `rsdoctor.rs`, and `rstest.rs`, match the URL language to the blog language. In Chinese posts, prefer `/zh/` paths such as `https://rspack.rs/zh/`; in English posts, omit `/zh/` because the default docs are English. Apply the same rule to deeper documentation URLs. + ## Revision behavior When revising an existing blog: diff --git a/skills-lock.json b/skills-lock.json index a98e6022f2..812b494941 100644 --- a/skills-lock.json +++ b/skills-lock.json @@ -5,7 +5,7 @@ "source": "rstackjs/agent-skills", "sourceType": "github", "skillPath": "skills/create-draft-release-notes/SKILL.md", - "computedHash": "ac0fd0bc0eb7abde798501f8915a87905125c67a52cee37fb1913f178dbe517d" + "computedHash": "cb32485c5a35e45acba920a690a14d10f878c92fbbd2312ec3d0ce4bf2012abc" }, "pr-creator": { "source": "rstackjs/agent-skills", @@ -17,7 +17,7 @@ "source": "rstackjs/agent-skills", "sourceType": "github", "skillPath": "skills/release-blog-writer/SKILL.md", - "computedHash": "964ac00607c45fd5004192f50e82019ee45b2c8e06e03fa7e06c35970b6388ce" + "computedHash": "24bdde0407813d43e4f42336fa0d433f53e5c5c8a516f46acbc3505c557f68ea" }, "rspress-description-generator": { "source": "rstackjs/agent-skills", diff --git a/website/docs/en/blog/_meta.json b/website/docs/en/blog/_meta.json index e5ce58c5f9..6b36e5c7db 100644 --- a/website/docs/en/blog/_meta.json +++ b/website/docs/en/blog/_meta.json @@ -1 +1 @@ -["index", "v2-0", "v1-0", "v0-7", "v0-6", "v0-5", "v0-4", "v0-3", "v0-2", "v0-1"] +["index", "v2-1", "v2-0", "v1-0", "v0-7", "v0-6", "v0-5", "v0-4", "v0-3", "v0-2", "v0-1"] diff --git a/website/docs/en/blog/v2-1.mdx b/website/docs/en/blog/v2-1.mdx new file mode 100644 index 0000000000..1ca43bfe75 --- /dev/null +++ b/website/docs/en/blog/v2-1.mdx @@ -0,0 +1,205 @@ +--- +description: 'Rsbuild 2.1 is out, featuring the Rust-based React Compiler, TanStack Start support, a Tailwind CSS v4 plugin, and support for CSS URL imports and Worker query imports.' +date: 2026-06-26 12:00:00 +sidebar: false +authors: + - name: Jiahan Chen + avatar: 'https://github.com/chenjiahan.png' + github: 'chenjiahan' +--- + +import { BlogAuthors } from '@rstack-dev/doc-ui/blog-authors'; + +# Announcing Rsbuild 2.1 + +_June 26, 2026_ + + + +We are pleased to announce the official release of Rsbuild 2.1! + +The main improvements in 2.1 include: + +- Framework and ecosystem: + - [Upgrade to Rspack 2.1](#upgrade-to-rspack-21) + - [Rust-based React Compiler](#rust-react-compiler) + - [TanStack Start support](#tanstack-start-support) + - [Tailwind CSS plugin](#tailwind-css-plugin) +- New features: + - [Automatic externals](#auto-external) + - [Parallel Babel and SVGR](#parallel-babel-and-svgr) +- Resource imports: + - [CSS URL imports](#css-url-imports) + - [Worker query imports](#worker-query-imports) + - [Wasm source import](#wasm-source-import) + +## Upgrade to Rspack 2.1 + +Rsbuild 2.1 is powered by Rspack 2.1. This brings faster builds, the Rust implementation of React Compiler, new output optimization capabilities, and many improvements under the hood. + +For more details, see the [Rspack 2.1 announcement post](https://rspack.rs/blog/announcing-2-1). + +## Rust-based React Compiler \{#rust-react-compiler} + +[React Compiler](https://react.dev/learn/react-compiler) can automatically optimize React components and Hooks at build time. Previously, React Compiler was primarily integrated through a Babel plugin, which introduced additional Babel transform overhead and increased build time. + +Rspack 2.1 includes the [Rust implementation of React Compiler](https://github.com/react/react/pull/36173), and Rsbuild 2.1 exposes this capability through `@rsbuild/plugin-react`. You can now enable the [`reactCompiler`](/plugins/list/plugin-react#reactcompiler) option in the React plugin to use React Compiler. + +When measuring only the additional compilation time introduced by React Compiler, our benchmarks show that the Rust implementation is **7-13x** faster than the Babel implementation. + +```ts title="rsbuild.config.ts" +import { defineConfig } from '@rsbuild/core'; +import { pluginReact } from '@rsbuild/plugin-react'; + +export default defineConfig({ + plugins: [ + pluginReact({ + reactCompiler: true, + }), + ], +}); +``` + +For projects using React 17 or React 18, you need to install `react-compiler-runtime` and explicitly set the target React version for React Compiler: + +```ts title="rsbuild.config.ts" +pluginReact({ + reactCompiler: { + target: '18', + }, +}); +``` + +For more options, see the [React plugin documentation](/plugins/list/plugin-react#reactcompiler). + +## TanStack Start support + +[TanStack Start](https://tanstack.com/start/latest) is a full-stack React framework powered by TanStack Router. It provides full-document SSR, streaming rendering, Server Functions, client and server builds, and more. + +In the Rsbuild 2.0 announcement, we mentioned that we were working with the TanStack team to explore an integration. TanStack Start now officially supports using Rsbuild as the build tool. You can keep using familiar Rsbuild configuration and plugins, and only need to add the TanStack Start plugin: + +```ts title="rsbuild.config.ts" +import { defineConfig } from '@rsbuild/core'; +import { pluginReact } from '@rsbuild/plugin-react'; +import { tanstackStart } from '@tanstack/react-start/plugin/rsbuild'; + +export default defineConfig({ + plugins: [pluginReact(), tanstackStart()], +}); +``` + +See the [TanStack Start blog](https://tanstack.com/blog/start-adds-rsbuild-support) or the [guide](/guide/framework/react#tanstack-start) for more details. + +## Tailwind CSS plugin + +Rsbuild now provides the [Tailwind CSS plugin](/plugins/list/plugin-tailwindcss) for integrating Tailwind CSS v4 with Rsbuild. The plugin is built on top of Tailwind CSS's official [`@tailwindcss/webpack`](https://www.npmjs.com/package/@tailwindcss/webpack) loader. + +Compared with using `@tailwindcss/postcss`, this avoids running Tailwind CSS compilation through PostCSS. In our tests, it improved build performance by up to **30%**. + +```ts title="rsbuild.config.ts" +import { defineConfig } from '@rsbuild/core'; +import { pluginTailwindcss } from '@rsbuild/plugin-tailwindcss'; + +export default defineConfig({ + plugins: [pluginTailwindcss()], +}); +``` + +## Automatic externals \{#auto-external} + +When building Node.js applications or SSR output, some dependencies are not suitable for bundling. Examples include observability SDKs, native addons, packages that require runtime instrumentation, or peer dependencies that should be provided by the host application. In the past, these cases usually required manual `output.externals` configuration. + +Rsbuild now supports the [`output.autoExternal`](/config/output/auto-external) option. It reads dependency fields from `package.json` and automatically generates external rules. This capability was previously used mainly in Rslib, and can now be used directly in Rsbuild applications. + +```ts title="rsbuild.config.ts" +export default { + output: { + target: 'node', + autoExternal: true, + }, +}; +``` + +## Parallel Babel and SVGR + +Babel and SVGR both provide flexible transformation capabilities, but they can be relatively expensive to run. When a project has many modules that need Babel processing, or needs to convert many SVG files into React components, this overhead can become significant. + +[`@rsbuild/plugin-babel`](/plugins/list/plugin-babel#parallel) and [`@rsbuild/plugin-svgr`](/plugins/list/plugin-svgr#parallel) now provide the `parallel` option. This option uses Rspack's parallel loader to distribute transformation tasks to worker threads, reducing pressure on the main thread and improving overall build performance. + +```ts title="rsbuild.config.ts" +import { pluginBabel } from '@rsbuild/plugin-babel'; +import { pluginSvgr } from '@rsbuild/plugin-svgr'; + +export default { + plugins: [ + pluginBabel({ + parallel: true, + }), + pluginSvgr({ + parallel: true, + }), + ], +}; +``` + +> Options passed to worker threads must be structured-cloneable. If you pass functions in Babel or SVGR options, keep using the default serial mode, or rewrite that logic as serializable configuration. + +## CSS URL imports + +Rsbuild now supports [CSS `?url` imports](/guide/styling/css-usage#url) to access the URL of a compiled CSS file. When importing a stylesheet with `?url`, Rsbuild runs the full CSS compilation pipeline and emits the result as a separate asset. In JavaScript, you receive the final CSS file URL, and the stylesheet is not automatically injected into the page. + +This is useful when runtime code needs to decide when to load styles, such as in micro-frontends, theme customization, or Web Components. + +```js title="src/index.js" +import darkThemeUrl from './dark-theme.css?url'; + +const link = document.createElement('link'); +link.rel = 'stylesheet'; +link.href = darkThemeUrl; +document.head.appendChild(link); +``` + +## Worker query imports + +Rsbuild now supports importing a Worker constructor directly with the [`?worker` query](/guide/basic/web-workers). This lets Worker scripts be imported like regular modules, making it easier to preserve the existing code structure when migrating from tools such as Vite. + +```js title="src/index.js" +import MyWorker from './worker.js?worker'; + +const worker = new MyWorker(); + +worker.onmessage = (event) => { + console.log(event.data); +}; + +worker.postMessage(10); +``` + +By default, Worker scripts are emitted as separate chunks in production builds. If you want to inline the Worker code into the main bundle, add the `inline` query: + +```js title="src/index.js" +import InlineWorker from './worker.js?worker&inline'; + +const worker = new InlineWorker(); +``` + +For scenarios that require the full [`WorkerOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker#options) object, such as `type: 'module'` or `credentials: 'include'`, we still recommend using the [standard Worker constructor syntax](/guide/basic/web-workers#import-with-constructors). + +## Wasm source import + +Rsbuild 2.1 supports the [`import source`](/guide/basic/wasm-assets#source-import) syntax from the [Source Phase Imports](https://github.com/tc39/proposal-source-phase-imports) proposal, allowing you to obtain the compiled `WebAssembly.Module` directly. + +Unlike a regular import, which returns the Wasm module's exports directly, `import source` is better suited for scenarios where you need to instantiate the module manually, provide different imports, create multiple instances, or pass the module to a Worker. + +```js title="src/index.js" +import source wasmModule from './add.wasm'; + +const instance = await WebAssembly.instantiate(wasmModule); +const { add } = instance.exports; + +console.log(add(1, 2)); // 3 +``` + +## Upgrade + +If you are already using Rsbuild 2.0, you only need to upgrade the relevant `@rsbuild/*` packages to version 2.1. For more details, see [Upgrade Rsbuild](/guide/upgrade/upgrade-rsbuild). diff --git a/website/docs/zh/blog/_meta.json b/website/docs/zh/blog/_meta.json index e5ce58c5f9..6b36e5c7db 100644 --- a/website/docs/zh/blog/_meta.json +++ b/website/docs/zh/blog/_meta.json @@ -1 +1 @@ -["index", "v2-0", "v1-0", "v0-7", "v0-6", "v0-5", "v0-4", "v0-3", "v0-2", "v0-1"] +["index", "v2-1", "v2-0", "v1-0", "v0-7", "v0-6", "v0-5", "v0-4", "v0-3", "v0-2", "v0-1"] diff --git a/website/docs/zh/blog/v2-1.mdx b/website/docs/zh/blog/v2-1.mdx new file mode 100644 index 0000000000..2a7d678a34 --- /dev/null +++ b/website/docs/zh/blog/v2-1.mdx @@ -0,0 +1,205 @@ +--- +description: 'Rsbuild 2.1 带来 Rust 版本 React Compiler、TanStack Start 支持、Tailwind CSS v4 插件,以及 CSS url、Worker 等资源导入 query 支持。' +date: 2026-06-26 12:00:00 +sidebar: false +authors: + - name: Jiahan Chen + avatar: 'https://github.com/chenjiahan.png' + github: 'chenjiahan' +--- + +import { BlogAuthors } from '@rstack-dev/doc-ui/blog-authors'; + +# Rsbuild 2.1 发布 + +_2026 年 6 月 26 日_ + + + +我们很高兴地宣布 Rsbuild 2.1 已经正式发布! + +2.1 版本的主要改进包括: + +- 框架与生态: + - [升级到 Rspack 2.1](#upgrade-to-rspack-21) + - [React Compiler Rust 版本](#rust-react-compiler) + - [TanStack Start 支持](#tanstack-start-support) + - [Tailwind CSS 插件](#tailwind-css-plugin) +- 新特性: + - [自动 external](#auto-external) + - [并行编译](#parallel-babel-and-svgr) +- 资源导入: + - [CSS URL 导入](#css-url-imports) + - [Worker 导入](#worker-query-imports) + - [Wasm 导入](#wasm-source-import) + +## 升级到 Rspack 2.1 \{#upgrade-to-rspack-21} + +Rsbuild 2.1 基于 Rspack 2.1 构建,带来了更快的构建性能、React Compiler Rust 版本、新的产物优化能力,以及多项底层改进。 + +更多详情请参考 [Rspack 2.1 发布公告](https://rspack.rs/zh/blog/announcing-2-1)。 + +## React Compiler Rust 版本 \{#rust-react-compiler} + +[React Compiler](https://react.dev/learn/react-compiler) 可以在构建阶段自动优化 React 组件和 Hooks。过去,React Compiler 主要通过 Babel 插件接入,这会引入额外的 Babel 转换开销,并增加项目的构建时间。 + +Rspack 2.1 内置了 [Rust 版本的 React Compiler](https://github.com/react/react/pull/36173),Rsbuild 2.1 则通过 `@rsbuild/plugin-react` 对这一能力进行了封装。现在你只需要开启 [`reactCompiler`](/plugins/list/plugin-react#reactcompiler) 选项,就可以在 React 插件中使用 React Compiler。 + +在我们的基准测试中,针对 React Compiler 带来的额外编译耗时,Rust 版本比 Babel 版本快 **7-13 倍**。 + +```ts title="rsbuild.config.ts" +import { defineConfig } from '@rsbuild/core'; +import { pluginReact } from '@rsbuild/plugin-react'; + +export default defineConfig({ + plugins: [ + pluginReact({ + reactCompiler: true, + }), + ], +}); +``` + +对于 React 17 或 React 18 项目,你需要安装 `react-compiler-runtime`,并显式设置 React Compiler 的目标 React 版本: + +```ts title="rsbuild.config.ts" +pluginReact({ + reactCompiler: { + target: '18', + }, +}); +``` + +更多选项可以参考 [React 插件文档](/plugins/list/plugin-react#reactcompiler)。 + +## TanStack Start 支持 \{#tanstack-start-support} + +[TanStack Start](https://tanstack.com/start/latest) 是一个由 TanStack Router 驱动的全栈 React 框架。它提供整页文档 SSR、流式渲染、Server Functions、客户端/服务端构建等能力。 + +在 Rsbuild 2.0 发布时,我们提到正在与 TanStack 团队合作探索集成。现在,TanStack Start 已经官方支持使用 Rsbuild 作为构建工具。你可以继续使用熟悉的 Rsbuild 配置与插件,只需额外注册 TanStack Start 插件: + +```ts title="rsbuild.config.ts" +import { defineConfig } from '@rsbuild/core'; +import { pluginReact } from '@rsbuild/plugin-react'; +import { tanstackStart } from '@tanstack/react-start/plugin/rsbuild'; + +export default defineConfig({ + plugins: [pluginReact(), tanstackStart()], +}); +``` + +参考 [TanStack Start 博客](https://tanstack.com/blog/start-adds-rsbuild-support) 或 [指南](/guide/framework/react#tanstack-start) 了解更多。 + +## Tailwind CSS 插件 \{#tailwind-css-plugin} + +Rsbuild 现在提供了 [Tailwind CSS 插件](/plugins/list/plugin-tailwindcss),用于在 Rsbuild 中集成 Tailwind CSS v4。该插件基于 Tailwind CSS 官方的 [loader](https://www.npmjs.com/package/@tailwindcss/webpack) 实现。 + +相比通过 `@tailwindcss/postcss` 进行转换,这种方式不需要再经过 PostCSS 执行 Tailwind CSS 编译。在我们的测试中,它可以带来至多 **30%** 的构建性能提升。 + +```ts title="rsbuild.config.ts" +import { defineConfig } from '@rsbuild/core'; +import { pluginTailwindcss } from '@rsbuild/plugin-tailwindcss'; + +export default defineConfig({ + plugins: [pluginTailwindcss()], +}); +``` + +## 自动 external \{#auto-external} + +在构建 Node.js 应用或 SSR 产物时,某些依赖并不适合打包进 bundle。例如观测 SDK、原生插件、需要运行时插桩的包,或应由宿主应用提供的 peer dependencies。过去这类场景通常需要手动配置 `output.externals`。 + +Rsbuild 现在支持 [`output.autoExternal`](/config/output/auto-external) 选项。它会读取 `package.json` 中的依赖字段,并自动生成 external 规则。这个能力此前主要用于 Rslib,现在也可以直接用于 Rsbuild 应用。 + +```ts title="rsbuild.config.ts" +export default { + output: { + target: 'node', + autoExternal: true, + }, +}; +``` + +## 并行编译 \{#parallel-babel-and-svgr} + +Babel 和 SVGR 都提供了灵活的转换能力,但执行性能较差。当项目中存在大量需要 Babel 处理的模块,或需要将大量 SVG 转换为 React 组件时,这部分开销会变得明显。 + +[`@rsbuild/plugin-babel`](/plugins/list/plugin-babel#parallel) 和 [`@rsbuild/plugin-svgr`](/plugins/list/plugin-svgr#parallel) 现在新增了 `parallel` 选项,可以借助 Rspack 的 parallel loader 将转换任务分配到 worker 线程中执行,从而降低主线程压力,提升整体构建性能。 + +```ts title="rsbuild.config.ts" +import { pluginBabel } from '@rsbuild/plugin-babel'; +import { pluginSvgr } from '@rsbuild/plugin-svgr'; + +export default { + plugins: [ + pluginBabel({ + parallel: true, + }), + pluginSvgr({ + parallel: true, + }), + ], +}; +``` + +> 传递给 worker 线程的选项必须能够被结构化克隆。如果你在 Babel 或 SVGR 选项中传入函数,需要继续使用默认的串行模式,或将这部分逻辑改写为可序列化配置。 + +## CSS URL 导入 \{#css-url-imports} + +Rsbuild 现在支持通过 [CSS `?url` 导入](/guide/styling/css-usage#url)来获取编译后样式文件的 URL。通过 `?url` 导入样式文件时,Rsbuild 会对 CSS 执行完整的编译处理,并将结果作为单独资源输出。在 JavaScript 中,你获取到的是最终 CSS 文件的 URL,样式不会自动注入页面。 + +这适用于需要由运行时代码决定何时加载样式的场景,例如微前端、主题定制或 Web Components 等。 + +```js title="src/index.js" +import darkThemeUrl from './dark-theme.css?url'; + +const link = document.createElement('link'); +link.rel = 'stylesheet'; +link.href = darkThemeUrl; +document.head.appendChild(link); +``` + +## Worker 导入 \{#worker-query-imports} + +Rsbuild 现在支持通过 [`?worker` query](/guide/basic/web-workers) 直接导入 Worker 构造器。这种写法让 Worker 脚本可以像普通模块一样被导入,在从 Vite 等工具迁移时也更容易保留原有代码结构。 + +```js title="src/index.js" +import MyWorker from './worker.js?worker'; + +const worker = new MyWorker(); + +worker.onmessage = (event) => { + console.log(event.data); +}; + +worker.postMessage(10); +``` + +默认情况下,Worker 脚本会在生产构建中输出为独立 chunk。如果你希望将 Worker 代码内联到主 bundle 中,可以添加 `inline` query: + +```js title="src/index.js" +import InlineWorker from './worker.js?worker&inline'; + +const worker = new InlineWorker(); +``` + +对于需要传入完整 [`WorkerOptions`](https://developer.mozilla.org/zh-CN/docs/Web/API/Worker/Worker#%E5%8F%82%E6%95%B0) 的场景,例如 `type: 'module'` 或 `credentials: 'include'`,仍然建议使用[标准 Worker 构造器写法](/guide/basic/web-workers#使用-worker-构造器)。 + +## Wasm 导入 \{#wasm-source-import} + +Rsbuild 2.1 支持 [Source Phase Imports](https://github.com/tc39/proposal-source-phase-imports) 提案中的 [`import source`](/guide/basic/wasm-assets#source-import) 语法,可以直接获取编译后的 `WebAssembly.Module`。 + +相比普通导入直接获取 Wasm 模块导出,`import source` 更适合需要手动实例化、传入不同 imports、创建多个实例,或将模块传递给 Worker 的场景。 + +```js title="src/index.js" +import source wasmModule from './add.wasm'; + +const instance = await WebAssembly.instantiate(wasmModule); +const { add } = instance.exports; + +console.log(add(1, 2)); // 3 +``` + +## 升级 + +如果你已经在使用 Rsbuild 2.0,只需要将相关 `@rsbuild/*` 包升级到最新版本即可,升级方式可以参考 [升级 Rsbuild](/guide/upgrade/upgrade-rsbuild)。 diff --git a/website/docs/zh/guide/framework/react.mdx b/website/docs/zh/guide/framework/react.mdx index a058191fbb..bd627bc9fc 100644 --- a/website/docs/zh/guide/framework/react.mdx +++ b/website/docs/zh/guide/framework/react.mdx @@ -29,7 +29,7 @@ import { PackageManagerTabs } from '@theme'; ### TanStack Start -[TanStack Start](https://tanstack.com/start/latest) 是一个由 TanStack Router 驱动的全栈 React 框架。它提供 full-document SSR、流式渲染、Server Functions、客户端/服务端构建等能力。 +[TanStack Start](https://tanstack.com/start/latest) 是一个由 TanStack Router 驱动的全栈 React 框架。它提供整页文档 SSR、流式渲染、Server Functions、客户端/服务端构建等能力。 - [文档](https://tanstack.com/start/latest) - [基础示例](https://github.com/rstackjs/rstack-examples/tree/main/rsbuild/tanstack-start) diff --git a/website/docs/zh/guide/framework/solid.mdx b/website/docs/zh/guide/framework/solid.mdx index f1543d08a0..f3af72140d 100644 --- a/website/docs/zh/guide/framework/solid.mdx +++ b/website/docs/zh/guide/framework/solid.mdx @@ -29,7 +29,7 @@ import { PackageManagerTabs } from '@theme'; ### TanStack Start -[TanStack Start](https://tanstack.com/start/latest) 是一个由 TanStack Router 驱动的全栈框架。它提供 full-document SSR、流式渲染、Server Functions、客户端/服务端构建等能力。 +[TanStack Start](https://tanstack.com/start/latest) 是一个由 TanStack Router 驱动的全栈框架。它提供整页文档 SSR、流式渲染、Server Functions、客户端/服务端构建等能力。 - [文档](https://tanstack.com/start/latest) - [示例项目](https://github.com/rstackjs/rstack-examples/tree/main/rsbuild/tanstack-start-solid) diff --git a/website/theme/index.scss b/website/theme/index.scss index d1bcf06df3..7db6c290f3 100644 --- a/website/theme/index.scss +++ b/website/theme/index.scss @@ -1,6 +1,6 @@ :root { --rp-c-brand: #ff5e00; - --rp-c-brand-dark: #ff704d; + --rp-c-brand-dark: var(--rp-c-brand); --rp-c-brand-darker: #ff704d; --rp-c-brand-light: #ff7524; --rp-c-brand-lighter: #ff7524;