evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.16k stars 1.15k forks source link

Specify loader inside import URL #1727

Closed fregante closed 2 years ago

fregante commented 3 years ago

Webpack lets you specify its loaders inline: https://webpack.js.org/concepts/loaders/#inline

Via config you can also specify a custom URL parameter to change the load type, e.g.:

import x from './file.css?inline' // webpack with custom config

const style = document.createElement('style')
style.src = x
document.head.append(style)

I know this is somewhat possible via extension in esbuild:

esbuild --bundle source.js --loader:.css=dataurl

but that appears to only work per file extension, so it's every css file or nothing. Sometimes I want to bundle the CSS, sometimes I'd like to use its URL, in the same codebase.

Probably esbuild could support:

import x from 'dataurl:./file.css' // wish

const style = document.createElement('style')
style.src = x
document.head.append(style)
hyrious commented 3 years ago

You can use plugins api to handle that, simply find css file in onResolve callback and replace that with a data url string in onLoad callback:

name: 'dataurl',
setup({ onResolve, onLoad }) {
  const { resolve } = require('path')
  const { readFileSync } = require('fs')
  onResolve({ filter: /^dataurl:.+/ }, args => {
    let path = resolve(args.resolveDir, args.path.slice('dataurl:'.length))
    return { path, namespace: "dataurl" }
  })
  onLoad({ filter: /.*/, namespace: "dataurl" }, args => {
    return { contents: readFileSync(args.path), loader: 'dataurl' }
  })
}

You can find a more robust example in my style loader plugin.

evanw commented 2 years ago

Closing as out of scope. This can be added with plugins as described above (thanks for posting that comment).

mhsdesign commented 2 months ago

As simple solution i added .dataurl in the file like import dummyImage from './resource/dummy-image.dataurl.svg'; and adjusted my loaders:

loader: {
        '.dataurl.svg': 'dataurl',
        '.svg': 'text',
}

But that has the flaw obviously that you would have to duplicate your sources if you need them in one place as data url and another time as text ... or if you cannot control the file name.