mhyeganeh's avatar

Problem loading font & image from css url() using Vite.JS

I'm trying to migrate from Laravel-Mix to Vite.JS

Almost everything is OK except the problem with loading assets which are referenced inside css/scss files! e.g:

background-image: url(/img/logo.png)

loading fonts using @font-face:

src: url(/fonts/Digital-7/Digital-7.woff) format('woff')

By running npm run build there is no problem. But by starting dev server, the browser tries to request assets from 5173 port which cause 404 Error beacause the root of this server is the root of laravel project and not public directory!

❌ Path the browser sends the request and get 404 error:

http://127.0.0.1:5173/img/logo.png

✅ Path that actually works:

http://127.0.0.1:5173/public/img/logo.png

Or:

http://127.0.0.1:8000/img/logo.png

What's the right pattern and syntax for path to assets which are located inside public directory of laravel project. I dont' want vite.js to make duplicate from images and fonts and store in public/build/assets directory. I just want to refferene them like before with laravel-mix :(

Here is a simple demo project of my problem:

https://github.com/mhyeganeh/vite-test

Thanks in advance.

0 likes
17 replies
Snapey's avatar

5173? Is that the port Vite tells you it is using?

thinkverse's avatar

Use absolute URLs instead of relative ones. Vite will rebase all @import and CSS url() as per their documentation.

In addition, all CSS url() references, even if the imported files are in different directories, are always automatically rebased to ensure correctness.

mhyeganeh's avatar

@thinkverse I beleieve by using leading / as the first charachter, it's an absolute path not relative!

background-image: url(/img/logo.png);

And I can't/don't want to use Full-URL path like http://example.test/img/logo.png

Can you give me an example of what you mean?

thinkverse's avatar

@mhyeganeh Non-full URLs will be rebased automatically by Vite, even those with an implicit domain name because that domain name will be Vite's dev server, or the build path when built unless otherwise specified.

mhyeganeh's avatar

@thinkverse I don't agree. According to documentations and practical tests, only realative paths rewritten and urls with leading / are not relative. So they remains untouched.

The problem is that the root of dev server is root of project and the root of laravel application is public directory and it causes 404 errors!

Sinnbeck's avatar

Try with relative paths

/*=== Digital-7 ===*/
@font-face {
    font-family: Digital-7;
    src: url(../../public/fonts/Digital-7/Digital-7.woff) format('woff'),
    url(../../public/fonts/Digital-7/Digital-7.eot) format('eot');
    font-weight: normal;
    font-style: normal;
}

body{
    max-width: 1400px;
    margin: 50px auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

    .version{
        font-size: 1.5rem;

        .digit-font{
            font-family: Digital-7, Arial, serif;
            color: #d91b3d;
        }
    }

    .logo-wrapper{
        width: 250px;
        height: 250px;
        border: 2px solid #ECECEC;
        background: url(../../public/img/logo.png) no-repeat center / contain;
    }
}
2 likes
mhyeganeh's avatar

@Sinnbeck This way the assets loads successfully in dev server mode and also build mode.

But after running npm run build Vite create a duplicate of every assets inside public/build/assets directory in a flat structure and refference to them instead of files already exists in public direcotry.

Porejct structure ofter build:

- app
- ...
- public
   - build
      - assets
         - logo.b51249ca9.png
         - Digital-7.c6cac16.woff
   - img
      - logo.png
   - fonts
      - Digital-7.woff
- resources
- ...
	

Beside the dificulty of working with relative paths, do you think this is a good approach or I'm missing something here?

2 likes
Sinnbeck's avatar

@mhyeganeh Yeah I can see how that might be annoying. I have never had a need to use it myself, so honestly I dont know currently.

I would probably move the needed files to /resources/assets and reference them there, but there might be a better way that I am not aware of :)

1 like
rhand's avatar

@mhyeganeh Did you ever find a better solution to load font or images in sass that is accepted by Vite?

mhyeganeh's avatar

@rhand Unfortunately not yet! I gave up and returned back to Laravel Mix again since then.

I beleive the only right pattern to use Vite is what @naknak987 and other friends mentioned before. But I'm not OK with this approach, because of duplications in files, reference urls from resources directory and...

1 like
rhand's avatar

@mhyeganeh yeah I am using absolute paths now and duplicated public placed assets in /assets/fonts or assets/images and so on for Vite to load them in properly. That seems to work. Also using sass @use instead of @import helps loading in sass assets on time like _variables.scss. Now just need to adjust build location and test all again. Been quite a journey thus far migrating. See https://laracasts.com/discuss/channels/vite/laravel-mix-to-vite-upgrade-issues-on-laravel-9-vue2

Snapey's avatar

@rhand I have absolutely no idea why you woukd want to budle asset# in vite/mix when you can just link to them directly in your view files

Rida Makhchan's avatar

My understanding we don't have to work on files directly from public on dev. We reference images on CSS based on their URL under resources/ folder, and Vite takes care for the rest. Once done with dev, we do build and VITE moves assets to public and adjust images URLs inside CSS.

1 like
naknak987's avatar

If you move your static assets to the resources directory then in your css/scss reference them from the resources directory.

background-image: url(/resources/images/test.jpg);

Vite will then serve your assets from the resources directory during development, npm run dev, but when you build for production, npm run build, it will compile the URL to the public path /build/assets/test.1a04fbd3.jpg. This works fine for me out of the box in a new Laravel project with no extra config.

The extra bit added when you build for production, 1a04fbd3 , is the way that Vite versions assets.

4 likes
dcranmer's avatar

@mhyeganeh @rida makhchan I just found this thread after running into this very issue. Up to now (with webpack), I've partially relied on importing a sass file coming from a node module. But this sounds as though I need to copy any imported external .scss files into /resources/sass and change the background-image urls in order to develop with them. Is this correct?

rhand's avatar

@dcranmer Did you have come up with a clearer solution to load relative Sass paths for images, fonts and so on that is accepted by Vite?

Please or to participate in this conversation.