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

Manually resolved path in CSS url() #831

Closed
joelmoss opened this issue Feb 17, 2021 · 4 comments
Closed

Manually resolved path in CSS url() #831

joelmoss opened this issue Feb 17, 2021 · 4 comments

Comments

@joelmoss
Copy link

joelmoss commented Feb 17, 2021

So I have a plugin that resolves all CSS url() directives to a custom URL path. For example:

body {
  background: url('./user/avatar.png');
}

Which should return:

body {
  background: url('/images/user/avatar.png');
}

Now I know the files loader will rewrite the image file name, but I do not want that, and need to maintain the path structure, while also resolving relative and absolute paths.

The problem I have is that the resulting CSS ends up being:

body {
  background: url(data:text/plain;base64,L2xpYi9hdmF0YXIucG5n);
}

Which is incorrect.

Here's my plugin:

    build.onResolve({ filter: /\.png$/ }, args => {
      return {
        path: resolve(args.resolveDir, args.path),
        namespace: 'image'
      }
    })

    build.onLoad({ filter: /\.png$/, namespace: 'image' }, args => {
      console.log(args)

      return {
        contents: args.path.slice(absWorkingDir.length),
        loader: 'text'
      }
    })

So even though I'm returning the text loader, it's converting it to a data URL. Is that expected behaviour?

thanks in advance

@evanw
Copy link
Owner

evanw commented Feb 18, 2021

Once you get to the point where an onLoad callback is being called, your import has already been set to be included in the bundle. It sounds like you don't even want to get to that point because you don't want the file in the bundle. In that case you should be returning external: true from your onResolve callback. That should prevent onLoad from being called in the first place and will make sure the file is excluded from the bundle.

@joelmoss
Copy link
Author

Ah but that would mean the path returned will be untouched.

I need './user/avatar.png' to be rewritten to '/images/user/avatar.png'.

It works when importing into JS...

import img from './user/avatar.png'

will end with img equalling /images/user/avatar.png. which is what I want.

Not sure if that explained it any better

@evanw
Copy link
Owner

evanw commented Feb 18, 2021

You can do both. You can return a modified path and mark that modified path as external:

build.onResolve({ filter: /\.png$/ }, args => {
  let absPath = require('path').resolve(args.resolveDir, args.path)
  return {
    path: absPath.slice(absWorkingDir.length),
    external: true,
  }
})

@joelmoss
Copy link
Author

Worked perfectly! Thank you!

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

No branches or pull requests

2 participants