Emotion: babel-plugin-emotion not working after upgrading to 10

Created on 23 Dec 2018  路  16Comments  路  Source: emotion-js/emotion

I upgraded from Emotion 9 to 10, and it seems like the babel plugin is now ignored. I've pinpointed the issue to the babel plugin version. If I keep Emotion at 10, and just revert the babel plugin back to 9.2.11, I will be able to see class labels in development again.

I don't know how to reproduce this, but when testing different git commits I was definitely able to pinpoint it to just upgrading the babel plugin from 9.2.11 to 10.0.5. I even tried using earlier versions of the 10 plugin (10.0.0 - 10.0.4) to no avail.

Is there any way I can debug it better, to provide you with more info?

Relevent code:

webpack:

 {
        test: /\.(js|tsx|ts)$/,
        exclude: /(node_modules)/,
        use: [{
          loader: 'babel-loader',
          options: { babelrc: true }
        },
        {
          loader: 'ts-loader',
          options: {
            transpileOnly: process.env.NODE_ENV !== 'production',
            getCustomTransformers: () => ({
              before: [tsTransformAsyncToMobxFlow()]
            })
          }
        }
        ]
      },

babelrc:

{
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    ["import", { "libraryName": "antd", "style": true }]
  ],
  "env": {
    "langs": {
      "plugins": [
        "@babel/plugin-transform-modules-commonjs"
      ]
    },
    "development": {
      "plugins": [
        ["@babel/plugin-transform-react-display-name"],
        ["emotion", { "sourceMap": true, "autoLabel": true }]
      ]

    },
    "production": {
      "comments": false,
      "plugins": [
        "@babel/plugin-transform-react-constant-elements",
        "@babel/plugin-transform-react-inline-elements",
        "transform-react-remove-prop-types",
        ["emotion"]
      ]
    }
  }
}

tsconfig:

{
 "compilerOptions": {
  "pretty": true,
  "noUnusedLocals": true,
  "noUnusedParameters": true,
  "outDir": "./typescript-build",
  "suppressImplicitAnyIndexErrors": true,
  "moduleResolution": "node",
  "jsx": "react",
  "module": "esnext",
  "noImplicitAny": true,
  "preserveConstEnums": true,
  "removeComments": true,
  "target": "esnext",
  "sourceMap": true,
  "allowSyntheticDefaultImports": true,
  "experimentalDecorators": true,
  "baseUrl": ".",
  "paths": {
    "~dpStores/*": ["src/stores/*"],
    "~dpTooltip": ["src/shared/components/tooltip.tsx"],
    "~dpEmotion": ["src/shared/themes/emotion.tsx"]
  }
 },
 "exclude": [
  "node_modules"
 ],
 "plugins": [
  {
      "name": "tslint-language-service",
      "alwaysShowRuleFailuresAsWarnings": false,
      "ignoreDefinitionFiles": true
  },
  {
    "name": "typescript-styled-plugin"
  },
  { "transform": "ts-transform-async-to-mobx-flow", "type": "config" }
  ]
}

Most helpful comment

@tkh44 I was able to work around this issue by placing the preset last in the order, because babel's preset follow a function composition order (last to first): https://babeljs.io/docs/en/presets#preset-ordering

All 16 comments

I also am not seeing "autoLabel"'s on v10

@Tsury if you are using TypeScript, you can try emotion-ts-plugin which work fine with ts-loader, and you will not need babel anymore.

And ts-import-plugin to deal with ant-design

@Brooooooklyn Interesting. Didn't know about it.
Seems like it's missing minification, but I'm not sure it's that important...

@Tsury I think it doesn't matter, because gzip is power enough for spaces.But we will still add the minification feature in future.

afaict, @babel/plugin-transform-react-inline-elements is incompatible with emotion 10.

@aaronjensen I'll try to remove it and see if it resolves it.
@Brooooooklyn I think I'd give it a go then, thanks for pointing it out

@Tsury the problem I had with it may be different than what you're seeing. Our setup is also quite different as we use babel to strip typescript types via @babel/preset-typescript. I'm also now using @emotion/babel-preset-css-prop to avoid the pragma stuff and that works well.

Could you try changing the order of plugins so that emotion is first in the list? The other plugins may be changing the code that emotion is looking for in order to run.

@aaronjensen Have you changed anything JSX-related in tsconfig.json in order to make @emotion/babel-preset-css-prop work? I have it installed and used in .babelrc, but it still does not apply the pragma for me. I need to add the /** @jsx jsx */ comment anyway.

I'm using typescript@next, @emotion/[email protected] and [email protected].

@karol-majewski what are you seeing w/o the pragma? If it's complaining about the css prop not existing, you could try adding @emotion/core to your compilerOptions.types. I didn't need to do that, but it could be that I have it imported somewhere... not sure how that all works exactly.

Thank you for getting back to me. When I don't write the pragma by hand, it doesn't resolve the css in runtime. My components are rendered as <section css="[object Object]">.

On the type level everything is fine. It does not complain about css prop not existing in JSX, becaue I have imported jsx in my source code (which pollutes the global namespace and adds css to JSX automatically, without having to add it to compilerOptions.types just like you said).

It sounds like @emotion/babel-preset-css-prop isn't working then. I'm assuming your typescript files are going through babel? Also, if you're using @emotion/babel-preset-css-prop, you shouldn't be importing jsx anywhere (except maybe once to pollute the global namespace, which may be what you're doing) since @emotion/babel-preset-css-prop will do that for you.

Could you post your babel config?

It sounds like @emotion/babel-preset-css-prop isn't working then

Precisely. @louiscenter has found a workaround which works for me though.

I'm assuming your typescript files are going through babel?

I'm using Parcel, so my understanding is that everything goes through Babel at some point.

lso, if you're using @emotion/babel-preset-css-prop, you shouldn't be importing jsx anywhere (except maybe once to pollute the global namespace,

Correct, I had imported it so it could extend the DOMAttributes interface.

My .babelrc in which @emotion/babel-preset-css-prop" does not seem to work:

{
  "presets": [
    [
      "@emotion/babel-preset-css-prop",
      {
        "autoLabel": true,
        "labelFormat": "[local]",
        "useBuiltIns": false,
        "throwIfNamespace": true,
        "sourceMap": true
      }
    ]
  ],
  "plugins": [
    "transform-inline-environment-variables",
    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
      }
    ],
    "add-react-displayname"
  ],
  "env": {
    "development": {
      "plugins": [
        "transform-react-jsx-source"
      ]
    }
  }
}

Interesting. I wonder if it has to do w/ preset ordering. I'm guessing parcel is changing the babel config in some way. Any way, glad you figured out a workaround.

@tkh44 I was able to work around this issue by placing the preset last in the order, because babel's preset follow a function composition order (last to first): https://babeljs.io/docs/en/presets#preset-ordering

If you are using typescript and you have a custom styled like in documentation maybe it could help you https://github.com/emotion-js/emotion/issues/1320#issuecomment-523123548

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hamlim picture hamlim  路  3Comments

mitchellhamilton picture mitchellhamilton  路  3Comments

kentcdodds picture kentcdodds  路  3Comments

mattfysh picture mattfysh  路  3Comments

rockmandash picture rockmandash  路  3Comments