Skip to content

fix(css): workaround tsx esModule interop of sass-embedded import#19182

Closed
hi-ogawa wants to merge 1 commit intovitejs:mainfrom
hi-ogawa:fix-tsx-workaround-sass-cjs-interop
Closed

fix(css): workaround tsx esModule interop of sass-embedded import#19182
hi-ogawa wants to merge 1 commit intovitejs:mainfrom
hi-ogawa:fix-tsx-workaround-sass-cjs-interop

Conversation

@hi-ogawa
Copy link
Contributor

@hi-ogawa hi-ogawa commented Jan 11, 2025

Description

As seen in privatenumber/tsx#627, tsx unwraps named exports for __esModule and thus strips off default export. The issue seems to be acknowledged as node inconsistency bug, but I'm not sure about the plan. Vite side fallback is simple, so probably it's worth having it.

From my quick read through, tsx transforms import(xxx) to unwrap default for __esModule automatically (transform-dynamic-import.ts). This seems to happen for all esm code loaded via tsx (load.ts).

I tested four combinations locally based on https://github.com/hi-ogawa/reproductions/tree/main/vite-19182-sass-tsx

  • node + sass-embedded
  • node + sass
  • tsx + sass-embedded (this was failing before)
  • tsx + sass

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 11, 2025

Open in Stackblitz

npm i https://pkg.pr.new/vite@19182

commit: fb54eaf

@hi-ogawa hi-ogawa marked this pull request as ready for review January 11, 2025 07:05
@bluwy
Copy link
Member

bluwy commented Jan 13, 2025

I personally prefer to not add special handling here and have it fixed in tsx instead. It looks like it's going to affect more modules that only sass-embedded, and also it's not clear to me why it's mangling the exports of .js files in node_modules.

@jorisw
Copy link

jorisw commented Feb 12, 2025

The solution to the original issue referred to by this PR — Cannot read properties of undefined (reading 'initAsyncCompiler') — is simple:

Add to vite.config.ts:

    css: {
      preprocessorOptions: {
        scss: {
          api: 'legacy',
        },
      },
    },

@roman-petrov
Copy link

roman-petrov commented Jun 25, 2025

The situation has just changed after Vite 7 release. As mentioned in migration guide in Vite 7 there is no way to use legacy or modern-compiler SCSS API.
We used modern-compiler API in our projects so we unable to upgrade to Vite 7 now.

There are already three PRs in Vite trying to fix this:

All three PRs are almost identical :)

I know that the source of the problem probably the issue in tsx, but as I understand it might be quite hard to fix it and the issue .

My points to go ahead with such fix (maybe, we should change the PR a bit):

  • I do not see any workarounds with Vite 7 if we want to use complex TypeScript configuration files. Right now we use tsx and it almost perfectly solves the problem. I tried Node.js type stripping with amaro import loader, Vite --configLoader option - but without success, tsx still seems to be the best solution for Vite + TypeScript configuration
  • SASS default import is deprecated long time ago. Link to SASS code. So as understand we actually can just remove .default property access when importing SASS
  • This fix seems to be quite simple and safe and can possibly make many Vite users happy :)

I am ready to provide any additional context or to create another PR with suggested changes if needed. @hi-ogawa, can we please proceed with this?

@roman-petrov
Copy link

Just an update. I finally found a quite simple and reliable way to use complex TypeScript Vite configurations in our project.

Earlier before Vite 7 release we used --import=tsx Node flag when running Vite. It worked almost perfectly, but now I understand that this is not a quite reliable way to run Vite. And here comes this issue and PR with SASS.

Now we removed --import-tsx from our Node environment and run Vite in "normal" way.

Instead, we now use tsx ESM Register API. It works like a charm without any errors and, because we use import statement - type information doesn't get lost.

So finally, I think I am done with this approach.

I am actually now not sure if we should fix this "SASS import" issue. Instead, maybe we can make Vite a bit better when using it with complex TypeScript configurations (#5370)? I know, there is now a --configLoader runner option in Vite 7, but it seems to be not working with dynamic imports in config files.

So finally here are couple of things to consider: maybe we can just document how to use tsx with Vite TypeScript configurations or implement --configLoader tsx Vite option?

@pakb
Copy link

pakb commented Sep 3, 2025

I'm currently experiencing an issue when using Vite+Vue+Cypress@15.0.0+TypeScript that can be fixed by this PR's changes (I've applied these change as patch, and it works well afterward).

Since Cypress version 15.0.0, they've switched to using TSX under the hood, and we are having difficulty using Vite as file preprocessor ever since (if we have sass or sass-embedded in our packages).

Here's the issue on Cypress repo: cypress-io/cypress#32362

Can these PR be included in a (near) future version of Vite?

@IlCallo
Copy link

IlCallo commented Oct 2, 2025

I'm one of Quasar framework maintainers, this is a blocker for supporting Cypress 15 in our Cypress integration package

Related: quasarframework/quasar-testing#403

@sapphi-red
Copy link
Member

Fixed by #20918

@sapphi-red sapphi-red closed this Oct 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sass dynamic import is undefined when building with "modern-compiler" and sass-embedded

7 participants