Emotion css prop using object styles produces no sourceMaps
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>
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 🤔
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.
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"
});
}
}
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
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
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" }}?
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