Skip to content

feat(css): add css.inject option to preserve CSS imports in JS output#808

Merged
sxzz merged 6 commits intomainfrom
sxzz/css-inject
Mar 7, 2026
Merged

feat(css): add css.inject option to preserve CSS imports in JS output#808
sxzz merged 6 commits intomainfrom
sxzz/css-inject

Conversation

@sxzz
Copy link
Member

@sxzz sxzz commented Mar 7, 2026

Summary

  • Add css.inject option that preserves import './style.css' statements in JS output, so library consumers automatically load CSS alongside JS
  • Support deprecated injectStyle top-level option for seamless tsup migration
  • Refactor CSS post-processing into standalone CssPostPlugin, with both CssPlugin functions returning Plugin[]
  • Fix CSS asset hash resolution bug for async/code-split chunks (filenames previously contained unresolved hash placeholders like !~{000}~)
  • Add migration transform: injectStyle: truecss: { inject: true }

Test plan

  • All 89 CSS tests pass including 4 new inject-specific tests
  • Async chunk + splitting test verifies CSS import injection into dynamic import chunks
  • Migration tests verify injectStylecss.inject AST transform
  • Typecheck and lint pass
  • Snapshot updated for fixed hash resolution in split CSS assets

🤖 Generated with Claude Code

When enabled, JS output retains `import './style.css'` statements pointing
to emitted CSS files so consumers automatically load the CSS.

- Add `css.inject` option to `CssOptions` (requires `@tsdown/css`)
- Support deprecated `injectStyle` top-level option for tsup migration
- Refactor `createCssPostHooks` into standalone `CssPostPlugin`
- Return `Plugin[]` from both `CssPlugin` functions
- Fix CSS asset hash resolution for async/split chunks
- Add migration transform: `injectStyle: true` → `css: { inject: true }`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@netlify
Copy link

netlify bot commented Mar 7, 2026

Deploy Preview for tsdown-main ready!

Name Link
🔨 Latest commit 95aac97
🔍 Latest deploy log https://app.netlify.com/projects/tsdown-main/deploys/69ac6256043fd40008a0601b
😎 Deploy Preview https://deploy-preview-808--tsdown-main.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 7, 2026

Open in StackBlitz

tsdown

pnpm add https://pkg.pr.new/tsdown@808 -D
npm i https://pkg.pr.new/tsdown@808 -D
yarn add https://pkg.pr.new/tsdown@808.tgz -D

create-tsdown

pnpm add https://pkg.pr.new/create-tsdown@808 -D
npm i https://pkg.pr.new/create-tsdown@808 -D
yarn add https://pkg.pr.new/create-tsdown@808.tgz -D

@tsdown/css

pnpm add https://pkg.pr.new/@tsdown/css@808 -D
npm i https://pkg.pr.new/@tsdown/css@808 -D
yarn add https://pkg.pr.new/@tsdown/css@808.tgz -D

@tsdown/exe

pnpm add https://pkg.pr.new/@tsdown/exe@808 -D
npm i https://pkg.pr.new/@tsdown/exe@808 -D
yarn add https://pkg.pr.new/@tsdown/exe@808.tgz -D

tsdown-migrate

pnpm add https://pkg.pr.new/tsdown-migrate@808 -D
npm i https://pkg.pr.new/tsdown-migrate@808 -D
yarn add https://pkg.pr.new/tsdown-migrate@808.tgz -D

commit: 253eaa1

Prepend a `;` to sourcemap mappings for each injected CSS import line,
keeping the JS sourcemap accurate after code modification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sxzz sxzz force-pushed the sxzz/css-inject branch from f59ade5 to 714c9aa Compare March 7, 2026 16:45
…nd sourcemap

Instead of removing pure CSS chunk imports and prepending CSS imports
(which reverses order and breaks sourcemap), swap the file extension
in-place (.mjs/.cjs/.js → .css). This preserves both CSS cascade
order and sourcemap line positions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sxzz sxzz mentioned this pull request Mar 7, 2026
16 tasks
sxzz and others added 3 commits March 8, 2026 01:26
- Add relaxed detection in removePureCssChunks for wrapper chunks (JS
  files that only import CSS) while preserving entry/dynamic entry chunks
- Exclude isEntry and isDynamicEntry from pureCssChunks in inject plugin
  so dynamic entries get CSS imports prepended correctly
- Add test for shared CSS-only chunk import rewriting
@sxzz sxzz merged commit ad74582 into main Mar 7, 2026
13 of 14 checks passed
@sxzz sxzz deleted the sxzz/css-inject branch March 7, 2026 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant