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 (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.
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:
babel-cli and emotion after setting up CRApackage.json file to add a babel entry point:"babel": {
"plugins": [
"emotion/babel"
]
}
babel-plugin-transform-object-rest-spread if you use { ...object })"scripts": {
"compile-emotion": "babel src/ --out-dir src/",
// or for a cleaner dev experience:
// "compile-emotion": "babel someSourceDirectory/ --out-dir src/"
}
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// directory structure:
someOtherSrcDirectory/
app.js // where you actually write the code
src/
app.js // compiled out after running `yarn run compile-emotion`
(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.)
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:
react-scripts in the futureplugins: [ "emotion/babel" ] to the babel section of package.jsonI 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:
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.
Most helpful comment
In the meantime, if anyone finds this thread.
// config-overrides.js
// package.json