Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with Vite's new Sass JS API and @blakedarlin/sass-json-importer #18961

Closed
7 tasks done
Nathan7139 opened this issue Dec 14, 2024 · 6 comments · Fixed by #18970
Closed
7 tasks done

Issue with Vite's new Sass JS API and @blakedarlin/sass-json-importer #18961

Nathan7139 opened this issue Dec 14, 2024 · 6 comments · Fixed by #18970
Labels
feat: css p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@Nathan7139
Copy link

Nathan7139 commented Dec 14, 2024

Describe the bug

Describe the bug
I'm attempting to use Vite's new Sass JS API for a project where I need to convert JSON files into Sass variables. Previously, I used the node-sass-json-importer package with the old Vite configuration. Here's an example of the old config:

import jsonImporter from 'node-sass-json-importer';

export default {
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: '@use "@BBB/assets/scss/utils" as *;',
        importer: jsonImporter(),
      },
    },
    // Specific PostCSS config file folder.
    postcss: '../../packages/AAA',
  },
};

With the new API, I switched to using @blakedarlin/sass-json-importer. Below is my updated Vite config:

import jsonImporter from '@blakedarlin/sass-json-importer';

export default {
  css: {
    preprocessorOptions: {
      scss: {
        api: 'modern-compiler',
        additionalData: '@use "@BBB/assets/scss/utils" as *;',
        importers: [jsonImporter()],
        silenceDeprecations: ['mixed-decls', 'import'],
      },
    },
    // Specific PostCSS config file folder.
    postcss: '../../packages/AAA',
  },
};

However, the @blakedarlin/sass-json-importer package doesn't work as expected in the Vite environment. When I print out the url from the canonicalize method, it always returns @BBB/assets/scss/utils. This is problematic because utils/index.scss is not a JSON file, and canonicalize returns null. Once canonicalize returns null, other @use, @forward, or @import statements inside utils/index.scss are skipped by this importer and are only processed by the default importer.

I confirmed that this package is designed to work specifically with sass-embedded. I also raised this issue in the Sass community, and the conclusion was that Sass itself seems to process the input correctly, so this might be a Vite-related issue.

Reproduction

https://codesandbox.io/p/devbox/k8xtqw?file=%2Fvite.config.js
(or as zip to download vite-18961-sass-json.zip)

Steps to reproduce

  1. Run pnpm install && pnpm dev in the example project.
  2. This will start Vite and reproduce the issue in the Vite environment.
  3. The vite.config.js file also uses sass.compileAsync to compile index.scss.
    • Using sass.compileAsync, everything works fine, and the console output shows:
      .logo {
        border: 1px solid #323232;
      }
      This is the expected result.
  4. However, Vite throws the following error:
    [vite] Pre-transform error: [sass] Error: expected "}".
    ╷
    1 │ {
    │ ^
    ╵
    /project/workspace/src/assets/json/colors.json 1:1           @import
    /project/workspace/src/assets/scss/utils/colors.scss 1:9     @use
    /project/workspace/src/assets/scss/utils/variables.scss 1:1  @forward
    /project/workspace/src/assets/scss/utils/index.scss 1:1      @use
    /project/workspace/src/App.vue 1:1                           root stylesheet
    
  • The issue occurs when Vite tries to handle imports within utils/index.scss, and the importer doesn't process JSON correctly after canonicalize returns null.
  • The standalone sass.compileAsync appears to handle everything correctly, so this seems to be specific to Vite's handling of the Sass API.

Is this issue related to Vite's Sass integration, the way I'm using the @blakedarlin/sass-json-importer, or the implementation of the package itself?

Any guidance or recommendations would be appreciated!

Thanks in advance for your support!

System Info

System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M1
    Memory: 39.52 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.20.2 - ~/.nvm/versions/node/v18.20.2/bin/node
    Yarn: 1.22.5 - /usr/local/bin/yarn
    npm: 10.5.0 - ~/.nvm/versions/node/v18.20.2/bin/npm
    pnpm: 8.7.6 - /usr/local/bin/pnpm
  Browsers:
    Chrome: 131.0.6778.140
    Safari: 17.6
    Safari Technology Preview: 18.0
  npmPackages:
    @vitejs/plugin-vue: ^5.1.5 => 5.2.1 
    vite: ^5.4.11 => 5.4.11

Used Package Manager

pnpm

Logs

No response

Validations

@hi-ogawa
Copy link
Collaborator

Can you move your reproduction somewhere else? It now says "Out of credits".

Copy link

Hello @Nathan7139. Please provide a minimal reproduction using a GitHub repository or StackBlitz. Issues marked with needs reproduction will be closed if they have no activity within 3 days.

@Nathan7139
Copy link
Author

Sorry about that, I assumed you would fork a copy to run it directly. Here’s another link to the reproduction: New Link.

The reason I’m not using StackBlitz is that it seems to have issues with sass-embedded, which prevents it from running correctly. Otherwise, I agree that StackBlitz would have been more convenient.

Let me know if you encounter any issues with this new link!

@hi-ogawa
Copy link
Collaborator

hi-ogawa commented Dec 16, 2024

I simplified a repro https://stackblitz.com/edit/vitejs-vite-nhtz78vk?file=src%2Ftest.scss (again this needs to be downloaded and run locally for sass-embedded)

I haven't dug deeper, but it looks like user's custom importer is not kicking in when the file is loaded via Vite's internal custom importer (in this case @ alias).

// [working]
@import './scss/colors.scss';

// [not working]
@import "@/scss/colors.scss";

@hi-ogawa
Copy link
Collaborator

The custom importer order does't look intuitive, but I'd assume sass spec says so somewhere. Probably we should check with them too.

[user canonicalize] @/scss/colors.scss -> null
[vite canonicalize] @/scss/colors.scss -> /path-to/scss/colors.scss
[vite load]         /path-to/scss/colors.scss -> ...
[vite canonicalize] file:///path-to/json/colors.json -> /path-to/json/colors.json
[user canonicalize] ../json/colors.json (called only when I patch above "vite canonicalize json" to return null)

For Vite side, considering we check extension on load side, it sounds fine to reject non css extensions during canonicalize.

async load(canonicalUrl) {
const ext = path.extname(canonicalUrl.pathname)
let syntax: Sass.Syntax = 'scss'
if (ext === '.sass') {
syntax = 'indented'
} else if (ext === '.css') {
syntax = 'css'
}

@Nathan7139
Copy link
Author

It sounds like some implementations in Vite caused the custom importer not to work correctly. Am I understanding this correctly? Thank you for the fix and the quick response!

@sapphi-red sapphi-red added feat: css p3-minor-bug An edge case that only affects very specific usage (priority) labels Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: css p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants