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

url with relative path in sass/scss is broken when main.js and assets are in subdirectory #11012

Open
7 tasks done
andyexeter opened this issue Nov 21, 2022 · 12 comments
Open
7 tasks done
Labels
feat: css p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@andyexeter
Copy link

Describe the bug

Following on from my comment in #7651 - the linked PR (#10741) doesn't solve the issue when main.js and assets are stored in a top level assets directory, e.g.:

├── assets
│   ├── images
│   │   └── vite.svg
│   ├── main.js
│   └── styles
│       ├── pages
│       │   └── home.scss
│       └── style.scss
├── index.html
├── package.json
├── package-lock.json
├── public
│   └── vite.svg
└── README.md

You can see in the linked reproducer that url('../../images/vite.svg') does not resolve the image correctly, even though that is the correct relative path to the file from assets/styles/pages/home.scss. When the path is changed to url('../images/vite.svg') it resolves correctly.

Reproduction

https://github.com/andyexeter/vitejs-vite-2btrkm

Steps to reproduce

Run npm install followed by npm run dev

System Info

System:
    OS: Linux 5.15 Ubuntu 20.04.5 LTS (Focal Fossa)
    CPU: (12) x64 11th Gen Intel(R) Core(TM) i5-11600 @ 2.80GHz
    Memory: 6.97 GB / 15.47 GB
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.18.1 - /usr/bin/node
    Yarn: 1.22.17 - /usr/bin/yarn
    npm: 8.19.2 - /usr/bin/npm
  Browsers:
    Chrome: 107.0.5304.110
    Firefox: 107.0

Used Package Manager

npm

Logs

No response

Validations

@sapphi-red
Copy link
Member

Thanks for creating this.
The reason why this is happening is explained in #7651:

Current Vite's implementation

It is implemented by this rebaseUrls function. This function is called inside importer option which is passed to sass. But importer will only be called if it is not a relative import because of the resolve order.

Loads are resolved by trying, in order:

  • Loading a file from disk relative to the file in which the @use or @import appeared.
  • Each custom importer.
  • Loading a file relative to the current working directory.
  • Each load path in includePaths.
  • Each load path specified in the SASS_PATH environment variable, which should be semicolon-separated on Windows and colon-separated elsewhere.

Interface LegacyStringOptions importer

Which means if a file is resolved by relative path, rebaseUrls functions won't be called. The example is below.

/* src/foo.scss */
@import "./nested/bar.scss";
/* @import "/@/nested/bar.scss"; */ /* if a alias is used `rebaseUrls` will be called */

/* ---- */
/* src/nested/bar.scss */
.bar {
  background: url('./bar.png');
}

But I forgot about this while creating #10741.

@roydukkey
Copy link

I believe I'm seeing the same symptom. I'm just not sure if the cause is the same. Here is my reproduction: https://github.com/roydukkey/moist/tree/vite/issue-11012

@nonsensation
Copy link

I think I ran into the same issue:

created a new vite-vanilla-typescript project, added npm i bootstrap-icons and have these files:

├── src
│   ├── main.ts
│   └── style.scss
└── index.html

In main.ts I import the bootstrap-icons via import "./style.scss";
In style.scss I import the bootstrap-icons.scss via @use "../node_modules/bootstrap/scss/bootstrap";
And it fails with:

downloadable font: download failed (font-family: "bootstrap-icons" style:normal weight:400 stretch:100 src index:0): status=2147746065 source: http://localhost:5173/MyProject/fonts/bootstrap-icons.woff2?24e3eb84d0bcaf83d77f904c78ac1f47

But when using @use "../node_modules/bootstrap/scss/bootstrap.css"; it works as expected.

(It also fails with the same error when importing *.scss)

Came here after a long time of finding out what might be wrong while learning web dev with vite/scss from here: twbs/icons#1381

(vite 4.1.0)

@tlyau62
Copy link

tlyau62 commented Dec 6, 2023

I think I ran into the same issue:

created a new vite-vanilla-typescript project, added npm i bootstrap-icons and have these files:

├── src
│   ├── main.ts
│   └── style.scss
└── index.html

In main.ts I import the bootstrap-icons via import "./style.scss"; In style.scss I import the bootstrap-icons.scss via @use "../node_modules/bootstrap/scss/bootstrap"; And it fails with:

downloadable font: download failed (font-family: "bootstrap-icons" style:normal weight:400 stretch:100 src index:0): status=2147746065 source: http://localhost:5173/MyProject/fonts/bootstrap-icons.woff2?24e3eb84d0bcaf83d77f904c78ac1f47

But when using @use "../node_modules/bootstrap/scss/bootstrap.css"; it works as expected.

(It also fails with the same error when importing *.scss)

Came here after a long time of finding out what might be wrong while learning web dev with vite/scss from here: twbs/icons#1381

(vite 4.1.0)

I have faced similar problems when using the library from @ArcGIS.
The relative path in the library css fails to be resolved if .scss is imported,
but it works when changing back to .css.

Thanks for the information.

@oussama-he
Copy link

Is there any news about this bug or workaround? I'm facing this issue with the bootstrap-icons library.
I'm using vite 4.4.11

@dherbst
Copy link

dherbst commented Jan 4, 2024

@oussama-he the workaround for bootstrap-icons is to unroll the variable interpolation before you load the bootstrap-icons.scss file. You should determine where the locations will be based on where the packages are installed, the values below work for me.

This works because $bootstrap-icons-font-fileis marked !default:

// NOTE: this is a workaround for the vite-sass issue of loading the woff files in bootstrap-icons.scss using variables
$bootstrap-icons-font-file: "~bootstrap-icons/font/fonts/bootstrap-icons";
@import "~bootstrap-icons/font/bootstrap-icons.scss";

@frederikbosch
Copy link

@dherbst Small side question, how did you manage to get the tilde (~) to work in Vite? I am getting Unable to resolve @import "~normalize.css/normalize.css"``?

@dherbst
Copy link

dherbst commented Jan 10, 2024

@frederikbosch you add it to the alias section of the vite.config.js see https://vitejs.dev/config/shared-options.html#resolve-alias

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      '~bootstrap': fileURLToPath(new URL('./node_modules/bootstrap', import.meta.url)),
      '~bootstrap-icons': fileURLToPath(new URL('./node_modules/bootstrap-icons', import.meta.url)),
    }
  }
})

@rjgotten
Copy link

rjgotten commented Feb 2, 2024

Getting this as well, and it is the one thing that is absolutely blocking me from easily moving off of Create React App.

[Edit]
Indeed declaring @fonts and @images alias paths works.
... I actually don't really have a problem with that approach. But on principle, this still has me a bit uneasy that it might break in the future on third-party CSS being imported.

@eXaminator
Copy link

This is currently blocking us from moving from a custom webpack build on a larger legacy app to vite. We have a lot of scss files for fonts etc. that are imported in a variety of other scss files. Sadly this breaks right now as we get errors like these:

../../../assets/fonts/opensans/opensans-extrabold-webfont.svg referenced in /some/path/to/screen.scss didn't resolve at build time, it will remain unchanged to be resolved at runtime

Is there any feasible workaround for this that doesn't include changing all the relative paths?

@nckirik
Copy link

nckirik commented Mar 10, 2024

facing the same issue here.
relative paths in scss files aren't handled correctly.

@unekinn
Copy link

unekinn commented Apr 29, 2024

Also encountering this problem. It does not seem to require that "main.js and assets are in subdirectory", as per title.

Given this directory structure

styles/
    main.scss
    base/
        _fonts.scss
        path/
            to/
                font.ttf
index.js

Simply using url('./path/to/font.ttf') from styles/base/_fonts.scss which is then @imported from styles/main.scss gives

./path/to/font.ttf referenced in <projectPath>/styles/main.scss didn't resolve at build time, it will remain unchanged to be resolved at runtime

So I find it quite strange that the documentation still states:

In addition, relative url() references inside imported Sass/Less files that are in different directories from the root file are also automatically rebased to ensure correctness.

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

No branches or pull requests