DEV Community

Cover image for The Mysterious Case of Emotion and "exports is not defined"
Lauren Ashpole
Lauren Ashpole

Posted on • Originally published at blog.laurenashpole.com

3 2

The Mysterious Case of Emotion and "exports is not defined"

Thought I’d share a bug I ran into a while back that sent me on a Poirot style investigation full of red herrings and unexpected culprits.

This is tangentially related to my recent page speed woes at work. We’d started using Emotion for CSS-in-JS in our component library and, combined with lazy and conditional component loading, it helped with some of the “Reduce unused CSS” warnings we were seeing in Lighthouse.

So adding Emotion as a styling option in our main codebase seemed like an obvious choice. We’d already installed @emotion/core (v10) when we started importing from our component library which meant it should be a quick, two-step process: 1) running yarn add @emotion/babel-preset-css-prop and 2) adding it to our babel.config.js presets after @babel/preset-react. I followed those steps, ran Webpack, and promptly got the error "ReferenceError: exports is not defined".

Weird.

That sent me on a lengthy wild goose chase. Stack Overflow had one question with no accepted answer. Babel was the primary suspect so I tried reordering all my presets and then upgrading to the latest version. I poked around in the Webpack config. The Emotion repo’s issues page wasn’t any help. I tried completely switching up our Emotion implementation but that created a whole new set of problems.

After hours of running around in circles, I finally went back to that first Stack Overflow link. What did my babel.config.js have in common with the babel.config.js posted there? The @babel/plugin-transform-modules-commonjs plugin. Searching for @babel/plugin-transform-modules-commonjs and “exports is not defined” got a ton of hits and revealed that @babel/plugin-transform-modules-commonjs is a pretty common answer to the question “How do I fix an ‘exports is not defined’ error?” Finally a clue! Now why did it stop working?

It turns out plugin/preset order can be pretty important in Babel. @babel/plugin-transform-modules-commonjs needed to run after @emotion/babel-preset-css-prop but plugins always run first. Since presets are just collections of plugins, I tried uninstalling @emotion/babel-preset-css-prop, looking at its source code, and installing each plugin individually. So my babel.config.js went from looking something like this:

{
  presets: [
    ...
    '@babel/preset-react',
    '@emotion/babel-preset-css-prop'
  ],
  plugins: [
    ...
    '@babel/plugin-transform-modules-commonjs'
  ]
}
Enter fullscreen mode Exit fullscreen mode

to more like:

{
  presets: [
    ...
    '@babel/preset-react'
  ],
  plugins: [
    ...
    [
      '@emotion/babel-plugin-jsx-pragmatic',
      {
        export: 'jsx',
        module: '@emotion/core',
        import: '___EmotionJSX'
      }
    ],
    [
      '@babel/plugin-transform-react-jsx',
      {
        pragma: '___EmotionJSX',
        pragmaFrag: 'React.Fragment'
      }
    ],
    'emotion',
    '@babel/plugin-transform-modules-commonjs'
  ]
}
Enter fullscreen mode Exit fullscreen mode

And that solved the mystery. It took a while but I did learn a lot more about Babel.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay