You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					347 lines
				
				8.0 KiB
			
		
		
			
		
	
	
					347 lines
				
				8.0 KiB
			| 
											3 years ago
										 | # @emotion/babel-plugin
 | ||
|  | 
 | ||
|  | > Babel plugin for the minification and optimization of emotion styles.
 | ||
|  | 
 | ||
|  | `@emotion/babel-plugin` is highly recommended, but not required in version 8 and | ||
|  | above of Emotion. | ||
|  | 
 | ||
|  | ## Features
 | ||
|  | 
 | ||
|  | <table> | ||
|  |   <thead> | ||
|  |     <tr> | ||
|  |       <th>Feature/Syntax</th> | ||
|  |       <th>Native</th> | ||
|  |       <th>Babel Plugin Required</th> | ||
|  |       <th>Notes</th> | ||
|  |     </tr> | ||
|  |   </thead> | ||
|  |   <tbody> | ||
|  |     <tr> | ||
|  |       <td><code>css``</code></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td></td> | ||
|  |     </tr> | ||
|  |     <tr> | ||
|  |       <td><code>css(...)</code></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td>Generally used for object styles.</td> | ||
|  |     </tr> | ||
|  |     <tr> | ||
|  |       <td>components as selectors</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td>Allows an emotion component to be <a href="https://emotion.sh/docs/styled#targeting-another-emotion-component">used as a CSS selector</a>.</td> | ||
|  |     </tr> | ||
|  |     <tr> | ||
|  |       <td>Minification</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td>Any leading/trailing space between properties in your <code>css</code> and <code>styled</code> blocks is removed. This can reduce the size of your final bundle.</td> | ||
|  |     </tr> | ||
|  |     <tr> | ||
|  |       <td>Dead Code Elimination</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td>Uglifyjs will use the injected <code>/*#__PURE__*/</code> flag comments to mark your <code>css</code> and <code>styled</code> blocks as candidates for dead code elimination.</td> | ||
|  |     </tr> | ||
|  |     <tr> | ||
|  |       <td>Source Maps</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td>When enabled, navigate directly to the style declaration in your javascript file.</td> | ||
|  |     </tr> | ||
|  |     <tr> | ||
|  |       <td>Contextual Class Names</td> | ||
|  |       <td align="center"></td> | ||
|  |       <td align="center">✅</td> | ||
|  |       <td>Generated class names include the name of the variable or component they were defined in.</td> | ||
|  |     </tr> | ||
|  |   </tbody> | ||
|  | </table> | ||
|  | 
 | ||
|  | ## Example
 | ||
|  | 
 | ||
|  | **In** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const myStyles = css` | ||
|  |   font-size: 20px; | ||
|  |   @media (min-width: 420px) { | ||
|  |     color: blue; | ||
|  |     ${css` | ||
|  |       width: 96px; | ||
|  |       height: 96px; | ||
|  |     `}; | ||
|  |     line-height: 26px; | ||
|  |   } | ||
|  |   background: green; | ||
|  |   ${{ backgroundColor: 'hotpink' }}; | ||
|  | ` | ||
|  | ``` | ||
|  | 
 | ||
|  | **Out** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const myStyles = /* #__PURE__ */ css( | ||
|  |   'font-size:20px;@media(min-width:420px){color:blue;', | ||
|  |   /* #__PURE__ */ css('width:96px;height:96px;'), | ||
|  |   ';line-height:26px;}background:green;', | ||
|  |   { backgroundColor: 'hotpink' }, | ||
|  |   ';' | ||
|  | ) | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Installation
 | ||
|  | 
 | ||
|  | ```bash | ||
|  | yarn add --dev @emotion/babel-plugin | ||
|  | ``` | ||
|  | 
 | ||
|  | or if you prefer npm | ||
|  | 
 | ||
|  | ```bash | ||
|  | npm install --save-dev @emotion/babel-plugin | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Usage
 | ||
|  | 
 | ||
|  | ### Via `.babelrc` (Recommended)
 | ||
|  | 
 | ||
|  | **.babelrc** | ||
|  | 
 | ||
|  | Without options: | ||
|  | 
 | ||
|  | ```json | ||
|  | { | ||
|  |   "plugins": ["@emotion"] | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | With options: | ||
|  | 
 | ||
|  | _Defaults Shown_ | ||
|  | 
 | ||
|  | ```js | ||
|  | { | ||
|  |   "plugins": [ | ||
|  |     [ | ||
|  |       "@emotion", | ||
|  |       { | ||
|  |         // sourceMap is on by default but source maps are dead code eliminated in production | ||
|  |         "sourceMap": true, | ||
|  |         "autoLabel": "dev-only", | ||
|  |         "labelFormat": "[local]", | ||
|  |         "cssPropOptimization": true | ||
|  |       } | ||
|  |     ] | ||
|  |   ] | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | Recommended Setup | ||
|  | 
 | ||
|  | **.babelrc** | ||
|  | 
 | ||
|  | ```json | ||
|  | { | ||
|  |   "plugins": ["@emotion"] | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Via CLI
 | ||
|  | 
 | ||
|  | ```bash | ||
|  | babel --plugins @emotion/babel-plugin script.js | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Via Node API
 | ||
|  | 
 | ||
|  | ```javascript | ||
|  | require('@babel/core').transform('code', { | ||
|  |   plugins: ['@emotion/babel-plugin'] | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Options
 | ||
|  | 
 | ||
|  | ### `sourceMap`
 | ||
|  | 
 | ||
|  | `boolean`, defaults to `true`. | ||
|  | 
 | ||
|  | This option enables the following: | ||
|  | 
 | ||
|  | - Injected source maps for use in browser dev tools | ||
|  | 
 | ||
|  | [**Documentation**](https://emotion.sh/docs/source-maps) | ||
|  | 
 | ||
|  | > Note:
 | ||
|  | > | ||
|  | > Source maps are on by default in @emotion/babel-plugin but they will be removed in production builds
 | ||
|  | 
 | ||
|  | ### `autoLabel`
 | ||
|  | 
 | ||
|  | `'dev-only' | 'always' | 'never'`, defaults to `dev-only`. | ||
|  | 
 | ||
|  | This option enables the following: | ||
|  | 
 | ||
|  | - Automatically adds the `label` property to styles so that class names | ||
|  |   generated by `css` or `styled` include the name of the variable the result is | ||
|  |   assigned to. | ||
|  | - Please note that non word characters in the variable will be removed | ||
|  |   (Eg. `iconStyles$1` will become `iconStyles1`) because `$` is not valid | ||
|  |   [CSS ClassName Selector](https://stackoverflow.com/questions/448981/which-characters-are-valid-in-css-class-names-selectors#449000) | ||
|  | 
 | ||
|  | Each possible value for this option produces different output code: | ||
|  | 
 | ||
|  | - with `dev-only` we optimize the production code, so there are no labels added there, but at the same time we keep labels for development environments, | ||
|  | - with `always` we always add labels when possible, | ||
|  | - with `never` we disable this entirely and no labels are added. | ||
|  | 
 | ||
|  | #### css
 | ||
|  | 
 | ||
|  | **In** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const brownStyles = css({ color: 'brown' }) | ||
|  | ``` | ||
|  | 
 | ||
|  | **Out** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const brownStyles = /*#__PURE__*/ css({ color: 'brown' }, 'label:brownStyles;') | ||
|  | ``` | ||
|  | 
 | ||
|  | `brownStyles`'s value would be `css-1q8eu9e-brownStyles` | ||
|  | 
 | ||
|  | ### `labelFormat`
 | ||
|  | 
 | ||
|  | `string`, defaults to `"[local]"`. | ||
|  | 
 | ||
|  | This option only works when `autoLabel` is set to `'dev-only'` or `'always'`. It allows you to | ||
|  | define the format of the resulting `label`. The format is defined via string where | ||
|  | variable parts are enclosed in square brackets `[]`. | ||
|  | For example `labelFormat: "my-classname--[local]"`, where `[local]` will be replaced | ||
|  | with the name of the variable the result is assigned to. | ||
|  | 
 | ||
|  | Allowed values: | ||
|  | 
 | ||
|  | - `[local]` - the name of the variable the result of the `css` or `styled` expression is assigned to. | ||
|  | - `[filename]` - name of the file (without extension) where `css` or `styled` expression is located. | ||
|  | - `[dirname]` - name of the directory containing the file where `css` or `styled` expression is located. | ||
|  | 
 | ||
|  | This format only affects the label property of the expression, meaning that the `css` prefix and hash will | ||
|  | be prepended automatically. | ||
|  | 
 | ||
|  | #### css
 | ||
|  | 
 | ||
|  | **In** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | // BrownView.js | ||
|  | // autoLabel: 'dev-only' | ||
|  | // labelFormat: '[filename]--[local]' | ||
|  | const brownStyles = css({ color: 'brown' }) | ||
|  | ``` | ||
|  | 
 | ||
|  | **Out** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const brownStyles = /*#__PURE__*/ css( | ||
|  |   { color: 'brown' }, | ||
|  |   'label:BrownView--brownStyles;' | ||
|  | ) | ||
|  | ``` | ||
|  | 
 | ||
|  | `BrownView--brownStyles`'s value would be `css-hash-BrownView--brownStyles` | ||
|  | 
 | ||
|  | #### styled
 | ||
|  | 
 | ||
|  | **In** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const H1 = styled.h1({ | ||
|  |   borderRadius: '50%', | ||
|  |   transition: 'transform 400ms ease-in-out', | ||
|  |   boxSizing: 'border-box', | ||
|  |   display: 'flex', | ||
|  |   ':hover': { | ||
|  |     transform: 'scale(1.2)' | ||
|  |   } | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | **Out** | ||
|  | 
 | ||
|  | ```javascript | ||
|  | const H1 = /*#__PURE__*/ styled('h1', { | ||
|  |   label: 'H1' | ||
|  | })({ | ||
|  |   borderRadius: '50%', | ||
|  |   transition: 'transform 400ms ease-in-out', | ||
|  |   boxSizing: 'border-box', | ||
|  |   display: 'flex', | ||
|  |   ':hover': { | ||
|  |     transform: 'scale(1.2)' | ||
|  |   } | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | `H1`'s class name attribute would be `css-hash-H1` | ||
|  | 
 | ||
|  | ### `cssPropOptimization`
 | ||
|  | 
 | ||
|  | `boolean`, defaults to `true`. | ||
|  | 
 | ||
|  | This option assumes that you are using something to make `@emotion/react`'s `jsx` function work for all jsx. If you are not doing so and you do not want such optimizations to occur, disable this option. | ||
|  | 
 | ||
|  | ### `importMap`
 | ||
|  | 
 | ||
|  | This option allows you to tell @emotion/babel-plugin what imports it should look at to determine what it should transform so if you re-export Emotion's exports, you can still use the Babel transforms | ||
|  | 
 | ||
|  | An example file: | ||
|  | 
 | ||
|  | ```js | ||
|  | import { anotherExport } from 'my-package'; | ||
|  | import { someExport, thisIsTheJsxExport } from 'some-package'; | ||
|  | ``` | ||
|  | 
 | ||
|  | An example config: | ||
|  | 
 | ||
|  | ```json | ||
|  | { | ||
|  |   "my-package": { | ||
|  |     "anotherExport": { | ||
|  |       "canonicalImport": ["@emotion/styled", "default"], | ||
|  |       "styledBaseImport": ["my-package/base", "anotherExport"] | ||
|  |     } | ||
|  |   }, | ||
|  |   "some-package": { | ||
|  |     "someExport": { | ||
|  |       "canonicalImport": ["@emotion/react", "css"] | ||
|  |     }, | ||
|  |     "thisIsTheJsxExport": { | ||
|  |       "canonicalImport": ["@emotion/react", "jsx"] | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Babel Macros
 | ||
|  | 
 | ||
|  | Instead of using `@emotion/babel-plugin`, you can use emotion with [`babel-plugin-macros`](https://github.com/kentcdodds/babel-plugin-macros). Add `babel-plugin-macros` to your babel config (which is included in Create React App 2.0) and use the imports/packages shown below. | ||
|  | 
 | ||
|  | ```jsx | ||
|  | import { | ||
|  |   css, | ||
|  |   keyframes, | ||
|  |   injectGlobal, | ||
|  |   flush, | ||
|  |   hydrate | ||
|  | } from '@emotion/css/macro' | ||
|  | import { jsx, css, Global, keyframes } from '@emotion/react/macro' | ||
|  | import styled from '@emotion/styled/macro' | ||
|  | ``` |