Skip to content

Conversation

@RJWadley
Copy link

@RJWadley RJWadley commented Oct 8, 2025

adds turbopack support to @vanilla-extract/next-plugin

turbopack doesn't have any sort of external API yet, so in order to evaluate the contents of our *.css.ts files we need to compile it separately using @vanilla-extract/compiler. To avoid import resolution mismatches, we defer module resolution to turbopack via its webpack-compatible api.

next/font doesn't work out of the box because turbopack has custom logic for it, so we transform any modules that use it in a css context to contain static references to the generated font family, style, and weight. most other next modules won't work in css.ts files

fixes #1367

@changeset-bot
Copy link

changeset-bot bot commented Oct 8, 2025

🦋 Changeset detected

Latest commit: eb2a5f9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@vanilla-extract/turbopack-plugin Minor
@vanilla-extract/next-plugin Minor
@vanilla-extract/compiler Minor
@vanilla-extract/css Patch
@vanilla-extract/vite-plugin Patch
@vanilla-extract/integration Patch
@vanilla-extract/rollup-plugin Patch
@vanilla-extract/esbuild-plugin Patch
@vanilla-extract/jest-transform Patch
@vanilla-extract/parcel-transformer Patch
@vanilla-extract/webpack-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@csorfab
Copy link

csorfab commented Oct 19, 2025

@mattcompiles @askoufis Can anyone take a look at this? This is a pretty important feature for next.js users. Or should we consider the project dead? Last PR was merged in early August, basically no activity from maintainers since then. Not meaning to bash anyone, I know it's thankless work maintaining open source software, but it would be nice to know what we can expect from this project. Thanks in advance!

@askoufis
Copy link
Contributor

Or should we consider the project dead? Last PR was merged in early August, basically no activity from maintainers since then.

A PR was merged in September. Reviews take time and ongoing work is often slow. All current maintainers have professional commitments and/or families.

I try to look at PRs when I have spare time/motivation, which is often quite sporadic. I'm currently on holiday, but I intend to make some headway on open PRs and repo maintenance in when I get back in early November.

@csorfab
Copy link

csorfab commented Oct 19, 2025

Thanks for your reply! I was a bit too dramatic, sorry about that. Enjoy your holiday, and let me know if I can help with anything to get this PR going.

@RJWadley RJWadley marked this pull request as draft October 23, 2025 04:49
@callum-gander
Copy link

I see there have been some recent commits pushed up to this PR. Are there any bits that you need help with that could be provided to speed up getting this merged in?

Appreciate that it's been a holiday period, but a lot of apps have performance issues with Next which has various potential solutions but the main recommendation seems to boil down to "just use Turbopack" vercel/next.js#48748. Obviously, the lack of support for Turbopack with Vanilla is effectively blocking us from getting those gains, which would be greatly appreciated ahead of Black Friday.

It would be great if there were a list of tasks that I or people within my company could help out with to speed this up, whether that's commits or just QAing. Cheers and thanks for the work on this so far!

@RJWadley
Copy link
Author

RJWadley commented Nov 17, 2025

If you're interested in trying this out, I've been using a preinstall script to download and install this branch:

"preinstall": "pnpm dlx gitpick https://github.com/RJWadley/vanilla-extract/tree/turbo-loader/ /tmp/vanilla-temp -f && cd /tmp/vanilla-temp && pnpm i && pnpm build"

You can install that temporary build with a link:

"@vanilla-extract/next-plugin": "link:/tmp/vanilla-temp/packages/next-plugin",

Although, you probably want to pin to a specific commit instead of the branch for the sake of stability:

"preinstall": "pnpm dlx gitpick RJWadley/vanilla-extract -b f5163f1 /tmp/vanilla-temp -f && cd /tmp/vanilla-temp && pnpm i && pnpm build"

Feedback or issues appreciated! I haven't seen many stats yet on speed or size of builds (compared to webpack) so if you have those I'd love to see some details.


The biggest issue with this at the moment is next specific modules not playing nicely. Since we must process styles outside of next.js there's not much that can be done. Think next/font, next/image, etc. Next has decent webpack loader support, but there are a few things missing that make it much harder (and in some cases impossible) for us to preprocess styles.

I'm gonna do a quick cleanup pass this week to prep this for merge, it's basically ready at this point but is still a bit messy while I'm experimenting with some stuff.

TLDR:

  • if your styles don't use next modules at all everything will work fine
  • next/font partially works
  • next/image imports don't work at all
  • other next modules may or may not work

@callum-gander
Copy link

callum-gander commented Nov 18, 2025

Hmmm, strange, I followed your steps and got this error

@frontend/app:dev:    ▲ Next.js 15.5.0
@frontend/app:dev:    - Local:        http://localhost:3000
@frontend/app:dev:    - Network:      http://10.100.22.2:3000
@frontend/app:dev:    - Environments: .env
@frontend/app:dev:    - Experiments (use with caution):
@frontend/app:dev:      ⨯ reactCompiler
@frontend/app:dev:      · optimizePackageImports
@frontend/app:dev: 
@frontend/app:dev:  ✓ Starting...
@frontend/app:dev: Warning: total number of custom routes exceeds 1000, this can reduce performance. Route counts:
@frontend/app:dev: headers: 5
@frontend/app:dev: rewrites: 2
@frontend/app:dev: redirects: 1246
@frontend/app:dev: See more info: https://nextjs.org/docs/messages/max-custom-routes-reached
@frontend/app:dev: Error: > Couldn't find a `pages` directory. Please create one under the project root
@frontend/app:dev:     at Object.webpack (../../../../../../../../private/tmp/vanilla-temp/packages/next-plugin/dist/vanilla-extract-next-plugin.cjs.dev.js:130:47)

That seemed to point at this specific line in the dist

 const findPagesDirResult = findPagesDir.findPagesDir(dir, ((_resolvedNextConfig$e = resolvedNextConfig.experimental) === null || _resolvedNextConfig$e === void 0 ? void 0 : _resolvedNextConfig$e.appDir) ?? false);

It's probably worth saying that we don't have a pages dir at all, we're fully on app dir. To be fair as well, I'm not sure that this would work for us anyway as we make heavy use of next/image, next/font, as well as other next modules.

When you say it's basically ready, do you mean basically ready minus support for next modules due to dependency on things turbopack isn't yet providing to help you preprocess styles?

If you have a solution to the above error, more than happy to give it a whirl

@RJWadley
Copy link
Author

RJWadley commented Nov 18, 2025

The error looks like resolution error in the webpack plugin setup. Should've seen that coming.
Switch back to the release version of next-plugin, then try configuring the loader manually:

"@vanilla-extract/turbopack-plugin": "link:/tmp/vanilla-temp/packages/turbopack-plugin",
  turbopack: {
    rules: {
      '**/*.css.{ts,tsx,js,jsx}': {
        loaders: [
          {
            loader: '@vanilla-extract/turbopack-plugin',
            options: { nextEnv: {} }, // include env vars set by next.config if any
          },
        ],
      },
    },
  },

As far as next/image support, you're free to style next images as this doesn't route through the plugin:

// page.ts
<Image className={myVanillaClass} />

The specific scenario that doesn't work is importing an image into a css.ts file and using it to generate styles:

// myStyles.css.ts
import coolThing from "./my-cool-image.png"

export const background = style({
  backgroundImage: `url(${coolThing.src})` // fails! use public dir instead
})

This is unlikely to change until we get better tools from turbopack.

For next/font, support is better. Anything under the style property is supported:

// myStyles.css.ts
import myFont from "./typography"

export const background = style({
  fontFamily: myFont.style.fontFamily
})

The specific scenario that doesn't work is extending font classNames in your styles:

// myStyles.css.ts
import myFont from "./typography"

export const background = style(myFont.className) // fails! set font family directly instead

This is also unlikely to change until we get better tools from turbopack.

TLDR using next modules is fine, but using next modules in your styles themselves is likely to fail unless I've specifically worked around it.

@Pnlvfx
Copy link
Contributor

Pnlvfx commented Nov 21, 2025

The error looks like resolution error in the webpack plugin setup. Should've seen that coming. Switch back to the release version of next-plugin, then try configuring the loader manually:

"@vanilla-extract/turbopack-plugin": "link:/tmp/vanilla-temp/packages/turbopack-plugin",
  turbopack: {
    rules: {
      '**/*.css.{ts,tsx,js,jsx}': {
        loaders: [
          {
            loader: '@vanilla-extract/turbopack-plugin',
            options: { nextEnv: {} }, // include env vars set by next.config if any
          },
        ],
      },
    },
  },

As far as next/image support, you're free to style next images as this doesn't route through the plugin:

// page.ts
<Image className={myVanillaClass} />

The specific scenario that doesn't work is importing an image into a css.ts file and using it to generate styles:

// myStyles.css.ts
import coolThing from "./my-cool-image.png"

export const background = style({
  backgroundImage: `url(${coolThing.src})` // fails! use public dir instead
})

This is unlikely to change until we get better tools from turbopack.

For next/font, support is better. Anything under the style property is supported:

// myStyles.css.ts
import myFont from "./typography"

export const background = style({
  fontFamily: myFont.style.fontFamily
})

The specific scenario that doesn't work is extending font classNames in your styles:

// myStyles.css.ts
import myFont from "./typography"

export const background = style(myFont.className) // fails! set font family directly instead

This is also unlikely to change until we get better tools from turbopack.

TLDR using next modules is fine, but using next modules in your styles themselves is likely to fail unless I've specifically worked around it.

For me is fine, thanks, I also had next font issues with webpack so I don't mind this approach,

thank you very much for your work,

I'll try this ASAP

@gavinthomas-valtech
Copy link

When is this is likely to be merged? more testing required?

@RJWadley
Copy link
Author

RJWadley commented Dec 8, 2025

Try out the prerelease using overrides:

It's built from this branch and is a merge of this PR with #1659

// package.json
"pnpm": {
  "overrides": {
    "@vanilla-extract/compiler": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/compiler@c1d4a88",
    "@vanilla-extract/css": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/css@c1d4a88",
    "@vanilla-extract/integration": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/integration@c1d4a88",
    "@vanilla-extract/next-plugin": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/next-plugin@c1d4a88",
    "@vanilla-extract/turbopack-plugin": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/turbopack-plugin@c1d4a88",
    "@vanilla-extract/webpack-plugin": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/webpack-plugin@c1d4a88"
  },
}

If you have issues, do let me know! As far as merging, next step is a review from a maintainer.

@askoufis let me know if there's anything I can do to make review easier! Happy to answer questions, revert bits, pull bits into their own PRs, etc. where possible for easier review. I know by nature it's a bit of a large PR so happy to do what I can to make it easier for you :)

@exequielbc
Copy link

exequielbc commented Dec 10, 2025

The specific scenario that doesn't work is importing an image into a css.ts file and using it to generate styles:

import coolThing from "./my-cool-image.png"

export const background = style({
 backgroundImage: `url(${coolThing.src})` // fails! use public dir instead
})

This is unlikely to change until we get better tools from turbopack.

@RJWadley the Panda CSS library gets around this by telling users to use the style prop on elements, their justification seems good enough to me. Built-in support could be added later if Turbo APIs become more open?

Sorry in advance if this wouldn't work, I thought it was a potential way to unblock this particular issue. It'd need to be a breaking change for @vanilla-extract/next-plugin if this was previously supported.

@gavinthomas-valtech
Copy link

btw. Wanted to call out the fantastic work of this library. I love how it works

@RJWadley
Copy link
Author

@exequielbc ended up finding an approach that works for now. Imports from images imports now work as expected:

import coolThing from "./my-cool-image.png"

export const background = style({
  backgroundImage: `url(${coolThing.src})`, // works ✅
  width: `${coolThing.width}px`, // works ✅
  height: `${coolThing.height}px`, // works ✅
})

Perhaps worth noting, this is just a stub for next/image. Very advanced cases will still fail. For example, if you configured a fancy custom turbopack loader in turbopack.rules to import powerpoint files, that won't work in css.ts files (and I'm not planning to implement this until turbopack supports module loading).

Try out the updated prerelease using overrides:
(built from this branch)

// package.json
"pnpm": {
  "overrides": {
    "@vanilla-extract/compiler": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/compiler@edaedbb",
    "@vanilla-extract/css": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/css@edaedbb",
    "@vanilla-extract/integration": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/integration@edaedbb",
    "@vanilla-extract/next-plugin": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/next-plugin@edaedbb",
    "@vanilla-extract/turbopack-plugin": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/turbopack-plugin@edaedbb",
    "@vanilla-extract/webpack-plugin": "https://pkg.pr.new/RJWadley/vanilla-extract/@vanilla-extract/webpack-plugin@edaedbb"
  },
}

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.

Cannot build a next app with Turbopack (Styles were unable to be assigned to a file)

7 participants