Styled-jsx: Conflict with transform-react-constant-elements plugin

Created on 20 Jan 2017  路  7Comments  路  Source: vercel/styled-jsx

When using the transform-react-constant-elements alongside the style-jsx plugin, the result is broken, see:

<html>
    <body>
        <div id="app"></div>
    </body>
    <script src="app.js"></script>
</html>
import React from 'react';
import { render } from 'react-dom';

function Component2() {
    return (
        <div>
            <style jsx>{`
                p {
                    color: red;
                }
            `}</style>
            <p>{'This should be red'}</p>
        </div>
    );
}

function Component1() {
    return (
        <div>
            <p>{'This should be black'}</p>
            <Component2 />
        </div>
    );
}

render(<Component1 />, document.getElementById('app'));

When using webpack configuration:

  {
      "presets": [
        ["es2015", { "modules": false }],
        "react",
        "stage-0"
      ],
      "plugins": [
        "styled-jsx/babel",
      ]
    }

image

When using webpack configuration:

  {
      "presets": [
        ["es2015", { "modules": false }],
        "react",
        "stage-0"
      ],
      "plugins": [
        "transform-react-constant-elements",
        "styled-jsx/babel",
      ]
    }

image

discussion enhancement help wanted

Most helpful comment

FYI made https://github.com/babel/babel/issues/5623 to discuss plugin ordering if anyone is interested

All 7 comments

Have you tried to invert the plugins order? By hoisting element creation styled-jsx can't transform those right now (it could but it would complicate things).

Yep, I've tried to revert plugin order

@romainneutron this issue is due to the fact that Babel is merging visitors so this happens:

styled-jsx's JSXElement visitors runs
annoying babel plugin's JSXElement visitors runs.

At this point the latter has optimized/replaced JSX and future attempt to run other visitors (eg. JSXOpeningElement) fail / don't apply.

A workaround is to run babel with the passPerPreset option set to true.

passPerPreset can unfortunately have other issues.

One solution I've found to this type of problem with my own custom plugins is to manually traverse. I think the idea is that doing so incurs a performance penalty, but it does generally fix this kind of plugin ordering issue.

Apparently rethinking plugin order is on the table for Babel's next big release.

Another solution could be to use just one visitor JSXElement and grab JSXOpeningElement by hand. To keep this sane we would split the business logic in smaller functions otherwise the visitor would be fairly big.

If anyone wants to give it a stab I am here to help and guide if necessary.

Related #84

FYI made https://github.com/babel/babel/issues/5623 to discuss plugin ordering if anyone is interested

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rauchg picture rauchg  路  25Comments

bernhardc picture bernhardc  路  15Comments

rauchg picture rauchg  路  18Comments

coox picture coox  路  26Comments

thisbejim picture thisbejim  路  18Comments