vercel / styled-jsx

Full CSS support for JSX without compromises
http://npmjs.com/styled-jsx
MIT License
7.7k stars 261 forks source link

[BUG] in styled jsx loaders not apply Webpack Loaders to url images #631

Open MaxmaxmaximusGitHub opened 4 years ago

MaxmaxmaximusGitHub commented 4 years ago

i have files /pages/_App.js /res/images/image.jpg

export default function App() {

  // language=Stylus
  return <style jsx global>{ `
    body {
        background-image: url("../res/images/image.jpg");
    }
  ` }</style>
}

Problem

url("../res/images/image.jpg") will not replace to /_next/static/images/lol-c8bbed083d312e8f1cccb6069d6f7919.png. styled jsx not applied webpack loaders, and not create optimized next.js assets

Temporary solution

import imageUrl from "../res/images/image.jpg" // loader will applied

export default function App() {

  // language=Stylus
  return <style jsx global>{ `
    body {
        background-image: url(${ imageUrl  });
    }
  ` }</style>
}
MaxmaxmaximusGitHub commented 4 years ago

accordingly, we can’t use such things

https://github.com/JetBrains/svg-mixer/tree/master/packages/svg-transform-loader

MaxmaxmaximusGitHub commented 4 years ago

we also need an option to configure which transform links are in require (). default and which don't

temp solution:

_utils.js:

////////////////////////////////////////////////////////////////////////////////
// OUR HACK
////////////////////////////////////////////////////////////////////////////////
const urlRegExp = /url\(('|"|)?(.*?)\1\)/img
const {parse} = require('@babel/parser')

function addImportUrls(css, expressions) {
  return css.toString().replace(urlRegExp, (match, quote, url) => {

    if (url.indexOf('%%styled-jsx-placeholder-') === 0) {
      return match
    }

    const exp = parse(`require(${ JSON.stringify(url) }).default`).program.body[0].expression
    expressions.push(exp)

    return `url(%%styled-jsx-placeholder-${ expressions.length - 1 }%%)`
  })

}

export const processCss = (stylesInfo, options) => {

  //  code...

////////////////////////////////////////////////////////////////////////////////
// APPLY OUR HACK AFTER PRERPROCESSORS
////////////////////////////////////////////////////////////////////////////////
  transformedCss = addImportUrls(transformedCss, expressions)

  //  code...

  return {
    hash: dynamic ? hashString(hash + staticClassName) : hashString(hash),
    css: transformedCss,
    expressions: dynamic && expressions
  }
}

How can I write a plugin for this functionality that changes the state of the expressions array?