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

Emotion css prop using object styles produces no sourceMaps #160

Open
soconnor-affinity opened this issue Mar 19, 2023 · 7 comments
Open

Comments

@soconnor-affinity
Copy link

soconnor-affinity commented Mar 19, 2023

The Emotion swc plugin doesn't produce a sourceMappingURL comment when using the css prop with the object styles syntax.

I found existing tests for the Emotion plugin that handle the css prop w/ the css JS template literal syntax I could not find any tests for the css prop w/ object styles.

Examples

Creates sourceMappingURL

<div css={css`color: red`}>Hello</div>

Missing sourceMappingURL

<div css={{ color: 'red' }}>Hello</div>
@Codex-
Copy link
Contributor

Codex- commented Jan 12, 2024

Are you still finding this to be the case?

When transpiling:

import { css } from "@emotion/react";
import { PureComponent } from "react";

export class SimpleComponent extends PureComponent {
  render() {
    return (
      <div
        css={css`
          color: red;
        `}
      >
        Hello
      </div>
    );
  }
}

swc emits:

import { jsx as _jsx } from "react/jsx-runtime";
import { css } from "@emotion/react";
import { PureComponent } from "react";
export class SimpleComponent extends PureComponent {
    render() {
        return /*#__PURE__*/ _jsx("div", {
            css: /*#__PURE__*/ css("color:red;", "SimpleComponent", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3JjL2luZGV4LnRzeCIsInNvdXJjZXMiOlsic3JjL2luZGV4LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjc3MgfSBmcm9tIFwiQGVtb3Rpb24vcmVhY3RcIjtcbmltcG9ydCB7IFB1cmVDb21wb25lbnQgfSBmcm9tIFwicmVhY3RcIjtcblxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXZcbiAgICAgICAgY3NzPXtjc3NgXG4gICAgICAgICAgY29sb3I6IHJlZDtcbiAgICAgICAgYH1cbiAgICAgID5cbiAgICAgICAgSGVsbG9cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPYSJ9 */"),
            children: "Hello"
        });
    }
}

Which contains the sourceMappingURL 🤔

@soconnor-affinity
Copy link
Author

soconnor-affinity commented Jan 12, 2024

Your example uses the css JS template literal syntax — which does produce the sourceMappingURL. The bug is that this syntax didn't:

import { css } from "@emotion/react";
import { PureComponent } from "react";

export class SimpleComponent extends PureComponent {
  render() {
    return (
      <div css={{ color: 'red' }}>
        Hello
      </div>
    );
  }
}

I haven't checked if this is fixed in a recent release.

@Codex-
Copy link
Contributor

Codex- commented Jan 12, 2024

Ah I see what you're saying, my apologies.

This this usage of the CSS prop we also get sourceMappingURL caching got me

This is indeed still an issue:

import { jsx as _jsx } from "react/jsx-runtime";
import { PureComponent } from "react";
export class SimpleComponent extends PureComponent {
    render() {
        return /*#__PURE__*/ _jsx("div", {
            css: {
                color: "red"
            },
            children: "Hello"
        });
    }
}

@Codex-
Copy link
Contributor

Codex- commented Jan 13, 2024

Did some further digging into why this is the case, it's because the swc emotion plugin doesn't currently implement cssPropOptimization which is enabled by default with @emotion/babel-plugin

Using this babel cfg:

...
[
  "@emotion",
  {
    autoLabel: "always",
    cssPropOptimization: false
  },
],
...

We get:

import { PureComponent } from "react";
import { jsx as _jsx } from "react/jsx-runtime";
export class SimpleComponent extends PureComponent {
  render() {
    return /*#__PURE__*/_jsx("div", {
      css: {
        color: "red"
      },
      children: "Hello"
    });
  }
}

With the option set to true, or removed, we get:

function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
import { PureComponent } from "react";
import { jsx as _jsx } from "react/jsx-runtime";
var _ref = process.env.NODE_ENV === "production" ? {
  name: "72n1bk-SimpleComponent",
  styles: "color:red;label:SimpleComponent;"
} : {
  name: "72n1bk-SimpleComponent",
  styles: "color:red;label:SimpleComponent;",
  map: "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbmRleC50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBS2dCIiwiZmlsZSI6Ii4uLy4uL3NyYy9pbmRleC50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjc3MgfSBmcm9tIFwiQGVtb3Rpb24vcmVhY3RcIjtcbmltcG9ydCB7IFB1cmVDb21wb25lbnQgfSBmcm9tIFwicmVhY3RcIjtcblxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIDxkaXYgY3NzPXt7IGNvbG9yOiBcInJlZFwiIH19PkhlbGxvPC9kaXY+O1xuICB9XG59XG4iXX0= */",
  toString: _EMOTION_STRINGIFIED_CSS_ERROR__
};
export class SimpleComponent extends PureComponent {
  render() {
    return /*#__PURE__*/_jsx("div", {
      css: _ref,
      children: "Hello"
    });
  }
}

So the real request is here a feature request to implement cssPropOptimization which would be great.

We'd need to extend the behaviour of how we handle fold_jsx_element to handle the prop similarly to here

@Codex-
Copy link
Contributor

Codex- commented Jan 15, 2024

I did a little proof of concept implementing this feature and got the following output:

export class SimpleComponent extends PureComponent {
  render() {
    return /*#__PURE__*/ _jsx("div", {
      css: /*#__PURE__*/ css(
        {
          color: "red",
        },
        "label:SimpleComponent",
        "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gXCJAZW1vdGlvbi9yZWFjdFwiO1xuaW1wb3J0IHsgUHVyZUNvbXBvbmVudCB9IGZyb20gXCJyZWFjdFwiO1xuXG5leHBvcnQgY2xhc3MgU2ltcGxlQ29tcG9uZW50IGV4dGVuZHMgUHVyZUNvbXBvbmVudCB7XG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gPGRpdiBjc3M9e3sgY29sb3I6IFwicmVkXCIgfX0+SGVsbG88L2Rpdj47XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLcUIifQ== */"
      ),
      children: "Hello",
    });
  }
}

This seems to be more inline with what you're expecting, is that right?

There are a few remaining issues to work through with my approach though, as it leverages having css imported from emotion, meaning cases where this is not imported would need to have this import added which feels a bit meh

@soconnor-affinity
Copy link
Author

This seems to be more inline with what you're expecting, is that right?

Yes it looks correct AFAICT.

In the output you pasted above I saw that it also uses / imports css():

import { jsx as _jsx } from "react/jsx-runtime";
import { css } from "@emotion/react";
import { PureComponent } from "react";
export class SimpleComponent extends PureComponent {
    render() {
        return /*#__PURE__*/ _jsx("div", {
            css: /*#__PURE__*/ css("color:red;", "SimpleComponent", "/*# sourceMappingURL=[snip] */"),
            children: "Hello"
        });
    }
}

There are a few remaining issues to work through with my approach though, as it leverages having css imported from emotion, meaning cases where this is not imported would need to have this import added which feels a bit meh

Is this a unique problem for css={{ color: "red" }}?

@Codex-
Copy link
Contributor

Codex- commented Jan 17, 2024

Yeah importing css is the wrong behaviour here, from what I can tell its expected that you're using emotion jsx and the prop object is tranformed similarly though so it's progress and I'll look into it more when I can

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants