Open germansokolov13 opened 5 years ago
Do you know how other projects do this with loaders and such? Eg. if you have a sass project and build it with webpack (no styled-jsx). How do you solve this issue?
I think in majority of frontend projects that use Webpack css-loader
is always used. This loader is the one responsible for resolving url()
s in css-files. But css-loader
does something else too while doing this. Its output is somehow incompatible with styled-jsx
.
Most often other projects use a combination of style-loader
and css-loader
called at the very end of styles processing. I.e. first different kinds of loaders like sass
and so on are called. css-loader
is always the last but one being called. And style-loader
is normally the last one.
But I do not know how to integrate it with styled-jsx
Yes the styled-jsx
loader turns CSS into JavaScript, so the url resolving should be done earlier. Have you tried to run your CSS through https://www.npmjs.com/package/resolve-url-loader before passing it to the styled-jsx's loader?
I tried now. If invoked before styledJsxLoader it seems to do nothing for some reason. Urls remain unchanged. If invoked after styledJsxLoader then error occurrs during build:
Error: resolve-url-loader: CSS error <path to my file>: Unknown word
.
I am not sure how this loader works. I used it without any options. Maybe it should configured somehow.
I was having the same issue, ended up creating my own custom loader:
function isAbsolutePath(url) {
return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url)
}
module.exports = function (content) {
if (this.cacheable) this.cacheable()
this.addDependency(this.resourcePath)
let index = 0
let imports = ''
const output = content.replace(/(?:url(?:\s+)?)\((?:'|")?(.*[^'"])(?:'|")?\)/gi, (...args) => {
const url = args[1]
if (isAbsolutePath(url)) {
return args[0]
}
const name = `_temp_url_${index}`
const nameAsVar = '${' + name + '}'
imports = `${imports} import ${name} from '${url}';`
index++
return `url("${nameAsVar}")`
})
this.callback(null, `${imports} ${output}`)
}
Put this loader in between styled-jsx/webpack
and options.defaultLoaders.babel
(if you are using next.js) something like this:
config.module.rules.push({
test: /\.scss$/,
use: [
options.defaultLoaders.babel,
{
loader: path.join(__dirname, './lib/styled-jsx-url-loader'),
},
{
loader: require('styled-jsx/webpack').loader,
options: {
type: 'scoped',
},
},
],
})
It's not sure sophisticated, basically just one big regexp replace so there could be some false positives, but it does the job for me.
I made also a loader for that https://github.com/danielhusar/styled-jsx-url-loader
Do you want to request a feature or report a bug?
Request a feature or request docs addition
Images in
url()
do not resolve if separate css-files setup is used.https://github.com/zeit/styled-jsx#styles-in-regular-css-files Here it is documented how to use separate files for styles. However if we do that we can no longer insert images resolved by Webpack.
I tried to use
css-loader
but then the styles are rendered in such a way that it won't work at all.Are there any plans or ideas how to handle this properly? Css inside components doesn't seem right but images have to be handled with Webpack. Normally there are some means to parse them out of
url()
. Without Webpack I can't use image loaders like those that encode images in base64. Without separate files I can't use IDE css helping tools. Something is off.I ended up rolling my own Webpack loader to handle this but it seems like too much complexity.