Emotion: Document how to get working with create react app

Created on 3 Jul 2017  路  14Comments  路  Source: emotion-js/emotion

We should have a section in the readme similar to the css modules block that explains how to set emotion up when using create-react-app


Edit by @mitchellhamilton:

Emotion now works in create-react-app without any setup beyond installing emotion (and react-emotion if you want styled) with yarn or npm. It does NOT require ejecting or using react-app-rewired.


You can optionally eject or use react-app-rewired to get extra features listed here but it is NOT required at all.


Most helpful comment

In the meantime, if anyone finds this thread.

npm install react-app-rewired --save-dev

// config-overrides.js

const babelLoader = function(conf) {
  if (!conf.loader) return false;
  return conf.loader.indexOf('babel-loader') > -1;
};

function rewireEmotion(config, env) {
  const babelrc = config.module.rules.find(babelLoader).options;
  babelrc.plugins = ['emotion/babel'].concat(babelrc.plugins || []);

  return config;
}

module.exports = function override(config, env) {
  config = rewireEmotion(config, env);
  return config;
};

// package.json

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test --env=jsdom"
},

All 14 comments

Just going to document a few of my notes I have collected while trying to get both Emotion and Styled-JSX working with create-react-app.

Short Story: Currently its pretty difficult as far as I can tell, and sometimes requires manual editing of the compiled files to get it to play nicely.

Documented some of this in this gist: https://gist.github.com/hamlim/ede060b163a1d323ffebad97ef1cc03f which is specifically for Styled-JSX but follows the same pattern:

  1. Install babel-cli and emotion after setting up CRA
  2. Edit the package.json file to add a babel entry point:
"babel": {
  "plugins": [
    "emotion/babel"
  ]
}
  • You may also need to install any plugins/presets as well and include them in the babel entry point if you are using anything that babel won't understand (i.e. babel-plugin-transform-object-rest-spread if you use { ...object })

    1. Add a script to compile out Emotion uses:

"scripts": {
  "compile-emotion": "babel src/ --out-dir src/",
  // or for a cleaner dev experience:
  // "compile-emotion": "babel someSourceDirectory/ --out-dir src/"
}
  • Optionally copy src files to another dir like cleanSrc or any name so you can edit the source code in a clean folder and compile to /src where react-scripts will compile to browser runnable code
    Example:
// directory structure:
someOtherSrcDirectory/
  app.js // where you actually write the code
src/
  app.js // compiled out after running `yarn run compile-emotion`
  1. (Optional) If you do split the actual source code out to a new location you will need to copy over the compiled out *.emotion.css files to the src/ directory so they can get picked up when CRA picks up the second stage of compiling. (I haven't found an easy way to manually do this but I assume there is some unix command that you can run to copy those files over in the same directory structure.) (You would also need to do this for any other static assets like images, etc.)

  2. In some of the compiled files babel might add some code at the top of the file above import statements. This will break CRA, and the only fix I have found so far is to manually move the imports above the code babel adds to the top of the file within the compiled src files (i.e. the ones that get generated after running compile-emotion from above).

Those are a few of the general steps I have found to get Emotion (as well as other babel-based libraries) to work with CRA. Ideally there should be an issue opened within create-react-app to track this pain point and address it at some point as it is pretty limiting in my opinion.

If you find something that I missed/found a way to get around any of these steps feel free to let me know/call it out. I would happy to open a PR to add some of this information to the docs once more people agree on the steps/phrasing!

@hamlim thanks for the info. It looks... complicated.

Have you seen this https://github.com/timarney/react-app-rewired

I think we may be able to do something like this.
https://github.com/timarney/react-app-rewired/blob/master/packages/react-app-rewire-relay/index.js#L7

Why go through all that? Why not eject? (genuinely curious)

Added some more comments to the twitter thread, figured I would come back here and explain some more. I haven't yet tried ejecting from CRA so not sure on the benefits/losses in doing so (Unsure on what you lose and what you gain out of ejecting).

React-app-rewired sounds like a really great solution to this issue, and sounds a lot (like a ton) better than my complicated process!

@hamlim thank you for your help. I got it working with react-app-rewired! I just need to release it

In the meantime, if anyone finds this thread.

npm install react-app-rewired --save-dev

// config-overrides.js

const babelLoader = function(conf) {
  if (!conf.loader) return false;
  return conf.loader.indexOf('babel-loader') > -1;
};

function rewireEmotion(config, env) {
  const babelrc = config.module.rules.find(babelLoader).options;
  babelrc.plugins = ['emotion/babel'].concat(babelrc.plugins || []);

  return config;
}

module.exports = function override(config, env) {
  config = rewireEmotion(config, env);
  return config;
};

// package.json

"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test --env=jsdom"
},

For what it's worth, I've made an example of configuring an ejected Create React App application to use Emotion in conjunction with React Toolbox and CSS Modules. It's a lot simpler than what was described earlier here, but not as simple as using react-app-rewired.

This example shows not only how to eject Create React App and configure Webpack and Babel for use with Emotion, but also how to configure them for React Toolbox, a popular material design implementation for React which utilizes CSS Modules.

Since emotion also plays well with CSS Modules, I thought I'd experiment with configuring CRA to utilize the two libraries together. This wasn't a ton of work, but could help out others looking to use CRA with Emotion if they're not interested to use a custom react-scripts implementation. It was largely for my own learning in how CSS Modules works and can be configured and composed, but I thought I might share it here in case it could be useful to someone else.


All it involves is:

  • Ejecting CRA to expose config and manually update react-scripts in the future
  • Adding plugins: [ "emotion/babel" ] to the babel section of package.json
  • Configuring Webpack files for React Toolbox and Emotion without conflict by using each library's suggested config settings

I tend to prefer to eject CRA instead of using third party react-scripts implementations like react-app-rewired, so I just wanted to document what that process would look like. But, since Emotion plays well with CSS Modules, I decided to also take this as an opportunity to finally configure React Toolbox the more idiomatic way, instead of using their themr.

In all honesty, an example of ejecting CRA and not involving react toolbox may be more beneficial to your users, but since this was a learning opportunity for myself, I involved it with the intent to explore composing the two together somehow before ruling out react toolbox for a beneficial example for emotion users altogether.

Finally, there's still some work to do to clean up the example a little bit, but it'll involve myself becoming a bit more familiar with Webpack and CSS Modules - so the example is in a "100% working but not perfect" stage for now.


Finally back to the issue, would it be beneficial to have two blessed examples for CRA usage with Emotion? I.e., 1 without ejecting, and 1 with ejecting?

For anyone trying to get emotion to work in a typescript CRA app:
https://gist.github.com/mrlundis/ca809eea890fa9fd5d98facd51cde731

@mrlundis This is amazing :-) !

I have spent a huge amount of time looking for a solution for exactly that :-) !

What is the reason for the babel config's need for further changes for production builds :-) ? Would yo be able to provide an example for a babel config :-) ?

Update to the comment above by @tkh44 on using react-app-rewired
Using [email protected] & [email protected] my config-overrides.js file was much simpler.

const { injectBabelPlugin } = require('react-app-rewired');

rewireEmotion = (config) => {
  return injectBabelPlugin('emotion/babel', config);
};


module.exports = rewireEmotion;

aldreth's solution is almost perfect, I had to change emotion/babel to just emotion

As of today, this is working:

// config-overrides.js
const { injectBabelPlugin } = require('react-app-rewired');

rewireEmotion = (config) => {
    return injectBabelPlugin('emotion', config); // <-- updated
};


module.exports = rewireEmotion;

for reference, this is the error I get when using emotion/babel instead of emotion:

Module build failed: ReferenceError: Unknown plugin "emotion/babel" specified in "base" at 0, attempted to resolve relative to [path]

Version used:

  • react-scripts: 1.1.4
  • react-app-rewired: 1.5.2
  • babel-plugin-emotion: 9.2.6

As far as I understand react-app-rewired is no longer necessary for create-react-app 2.* are here

So I guess you can now do

import styled from 'react-emotion/macro'

More info

https://emotion.sh/docs/babel-plugin-emotion#babel-macros


Sorry about commenting on closed issue but this is first Google hit for "react-create-app emotion" and there's no mention about the macro.

Was this page helpful?
0 / 5 - 0 ratings