|
| 1 | +--- |
| 2 | +order: 3 |
| 3 | +section: 1-Getting started |
| 4 | +--- |
| 5 | + |
| 6 | +# How it Works |
| 7 | + |
| 8 | +Once you've [installed and configured](/installation) everything, you can start using it, |
| 9 | +but it's best to explain what happens under the hood. |
| 10 | + |
| 11 | +Compiled uses Babel (with pre-configuration options via Webpack and Parcel) to transform styles |
| 12 | +into atomic CSS determined at build time, resulting in **very performant components**. |
| 13 | + |
| 14 | +Let's take a typical component you might write: |
| 15 | + |
| 16 | +```jsx |
| 17 | +/** @jsxImportSource @compiled/react */ |
| 18 | +import { css } from '@compiled/react'; |
| 19 | +import type { ReactNode } from 'react'; |
| 20 | + |
| 21 | +type Props = { inverted?: boolean, children: ReactNode }; |
| 22 | + |
| 23 | +const largeTextStyles = css({ |
| 24 | + fontSize: '48px', |
| 25 | + padding: '8px', |
| 26 | + background: '#eee', |
| 27 | +}); |
| 28 | +const invertedStyles = css({ |
| 29 | + background: '#333', |
| 30 | + color: '#fff', |
| 31 | +}); |
| 32 | + |
| 33 | +export const LargeText = ({ inverted, children }: Props): JSX.Element => { |
| 34 | + return <span css={[largeTextStyles, inverted && invertedStyles]}>{children}</span>; |
| 35 | +}; |
| 36 | +``` |
| 37 | + |
| 38 | +## Runtime styles (unperformant) |
| 39 | + |
| 40 | +With the most basic Babel setup, Compiled will be transformed to **runtime styles**. |
| 41 | +This is typically used in a development or testing environments. |
| 42 | + |
| 43 | +It is **not recommended in production environments** as it will be less performant, but also mixing |
| 44 | +runtime and extraction can result in breaking visual changes from atomic specificity conflicts. |
| 45 | +Refer to [extracted styles](#extracted-styles) below for the recommendation. |
| 46 | + |
| 47 | +```bash |
| 48 | +$ babel src |
| 49 | +Successfully compiled 1 file with Babel (9ms) |
| 50 | +``` |
| 51 | + |
| 52 | +You'll see a few things happening in the code below: |
| 53 | + |
| 54 | +1. All styles are converted into [Atomic CSS](/atomic-css) for reuse. |
| 55 | +2. Some styles, such as `padding:8px` will be expanded out to `padding-left`, `padding-right`, etc, |
| 56 | + while others might be sorted. [Read more about this](shorthand) |
| 57 | +3. All `css()` calls are replaced with `null` and instead the styles are injected at runtime with the |
| 58 | + `className` inlined. Note that `cssMap()` works slightly differently and maintains the object syntax. |
| 59 | +4. There are a few internal runtime functions that are used to manage the styles like `ax` and `CC`. |
| 60 | + [Read more about this](/pkg-react-runtime) |
| 61 | +5. [Postcss](https://postcss.org/), [autoprefixer](https://github.com/postcss/autoprefixer), and some other |
| 62 | + optimizations will run over your code to make it more performant and safer for use. |
| 63 | + |
| 64 | +```jsx |
| 65 | +import { ax, ix, CC, CS } from '@compiled/react/runtime'; |
| 66 | +const _8 = '._syazu67f{color:#fff}'; |
| 67 | +const _7 = '._bfhk1d6m{background-color:#333}'; |
| 68 | +const _6 = '._bfhkr75e{background-color:#eee}'; |
| 69 | +const _5 = '._19bvftgi{padding-left:1pc}'; |
| 70 | +const _4 = '._n3tdftgi{padding-bottom:1pc}'; |
| 71 | +const _3 = '._u5f3ftgi{padding-right:1pc}'; |
| 72 | +const _2 = '._ca0qftgi{padding-top:1pc}'; |
| 73 | +const _ = '._1wybckbl{font-size:3pc}'; |
| 74 | +const largeTextStyles = null; |
| 75 | +const invertedStyles = null; |
| 76 | +export const LargeText = ({ inverted, children }) => { |
| 77 | + return ( |
| 78 | + <CC> |
| 79 | + <CS>{[_, _2, _3, _4, _5, _6, _7, _8]}</CS> |
| 80 | + <span |
| 81 | + className={ax([ |
| 82 | + '_1wybckbl _ca0qftgi _u5f3ftgi _n3tdftgi _19bvftgi _bfhkr75e', |
| 83 | + inverted && '_bfhk1d6m _syazu67f', |
| 84 | + ])}> |
| 85 | + {children} |
| 86 | + </span> |
| 87 | + </CC> |
| 88 | + ); |
| 89 | +}; |
| 90 | +``` |
| 91 | + |
| 92 | +## Extracted styles |
| 93 | + |
| 94 | +We highly suggest you turn on style extraction to distribute styles statically at build time, |
| 95 | +either through [NPM](https://npmjs.com/) or Production environments. Doing this, styles will |
| 96 | +have their **runtime stripped and styles extracted** to an [atomic style sheet](/atomic-css). |
| 97 | + |
| 98 | +Refer to [stylesheet extraction](/css-extraction-webpack) for more details. |
| 99 | + |
| 100 | +Let's compare this to runtime styles, assuming we have Parcel configured |
| 101 | + |
| 102 | +```bash |
| 103 | +$ parcel build ./src/index.html |
| 104 | +✨ Built in 4.94s |
| 105 | +dist/index.html 246 B 349ms |
| 106 | +dist/index.019bae5f.js 136.13 KB 806ms |
| 107 | +# This generates `index.compiled.css` file(s) too. |
| 108 | +🌽 ✅ Done in 6.26s |
| 109 | +``` |
| 110 | + |
| 111 | +You'll see a few different things are happening in the code below: |
| 112 | + |
| 113 | +1. All styles are moved into a separate file, `index.compiled.css`, that is imported into this file for |
| 114 | + your bundler to pick up and combine and serve to the user. |
| 115 | +2. The runtime injection of `<CS>` is no longer required because the styles are statically available. |
| 116 | + |
| 117 | +The main difference beyond the greatly reduced runtime cost is that the atomic styles can be completely deduplicated. |
| 118 | + |
| 119 | +```diff |
| 120 | ++import "./index.compiled.css"; |
| 121 | +-import { ax, ix, CC, CS } from '@compiled/react/runtime'; |
| 122 | ++import { ax, ix } from "@compiled/react/runtime"; |
| 123 | +-const _8 = '._syazu67f{color:#fff}'; |
| 124 | +-const _7 = '._bfhk1d6m{background-color:#333}'; |
| 125 | +-const _6 = '._bfhkr75e{background-color:#eee}'; |
| 126 | +-const _5 = '._19bvftgi{padding-left:8px}'; |
| 127 | +-const _4 = '._n3tdftgi{padding-bottom:8px}'; |
| 128 | +-const _3 = '._u5f3ftgi{padding-right:8px}'; |
| 129 | +-const _2 = '._ca0qftgi{padding-top:8px}'; |
| 130 | +-const _ = '._1wybckbl{font-size:3pc}'; |
| 131 | +var largeTextStyles = null; |
| 132 | +var invertedStyles = null; |
| 133 | +export const LargeText = ({ inverted, children }) => { |
| 134 | + return ( |
| 135 | +- <CC> |
| 136 | +- <CS>{[_, _2, _3, _4, _5, _6, _7, _8]}</CS> |
| 137 | + <span |
| 138 | + className={ax([ |
| 139 | + '_1wybckbl _ca0qftgi _u5f3ftgi _n3tdftgi _19bvftgi _bfhkr75e', |
| 140 | + inverted && '_bfhk1d6m _syazu67f', |
| 141 | + ])}> |
| 142 | + {children} |
| 143 | + </span> |
| 144 | +- </CC> |
| 145 | + ); |
| 146 | +}; |
| 147 | +``` |
| 148 | + |
| 149 | +For reference, the atomic stylesheet is created just as before, now in `index.compiled.css`, and with |
| 150 | +the bundler config, these `*.compiled.css` files will be merged together with duplicates removed, resulting |
| 151 | +in a drastically smaller CSS payload to the customer. |
| 152 | + |
| 153 | +These `*.compiled.css` files could be distributed via NPM or collected and bundled to customers. |
| 154 | + |
| 155 | +<!-- prettier-ignore --> |
| 156 | +```css |
| 157 | +._19bvftgi{padding-left:8px} |
| 158 | +._1wybckbl{font-size:3pc} |
| 159 | +._bfhk1d6m{background-color:#333} |
| 160 | +._bfhkr75e{background-color:#eee} |
| 161 | +._ca0qftgi{padding-top:8px} |
| 162 | +._n3tdftgi{padding-bottom:8px} |
| 163 | +._syazu67f{color:#fff} |
| 164 | +._u5f3ftgi{padding-right:8px} |
| 165 | +``` |
0 commit comments