Skip to content

Commit 75a49c1

Browse files
committed
fix($readme): prepare docs for react universal component 2.0 launch (1st draft)
1 parent 52eb7e0 commit 75a49c1

File tree

2 files changed

+87
-71
lines changed

2 files changed

+87
-71
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ notifications:
1313
email: false
1414
webhooks:
1515
urls:
16-
- https://webhooks.gitter.im/e/ba96487b164673728247
16+
- https://webhooks.gitter.im/e/5156be73e058008e1ed2
1717
on_success: always # options: [always|never|change] default: always
1818
on_failure: always # options: [always|never|change] default: always
1919
on_start: never # options: [always|never|change] default: always

README.md

+86-70
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
# extract-css-chunks-webpack-plugin [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/Reactlandia/Lobby)
1+
<a href="https://gitter.im/Reactlandia/Lobby" target="_blank">
2+
<img alt="Edit Redux-First Router Demo" src="http://cdn.reactlandia.com/chat-badge-reactlandia.png">
3+
</a>
4+
5+
# extract-css-chunks-webpack-plugin
26

37
<p align="center">
48
<a href="https://www.npmjs.com/package/extract-css-chunks-webpack-plugin">
@@ -14,74 +18,35 @@
1418
</a>
1519
</p>
1620

17-
> **UPDATE (July 7th):** [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import) is now required to asynchronously import both css + js. *Much Faster Builds!* You likely want to read [its intro article](https://medium.com/@faceyspacey/webpacks-import-will-soon-fetch-js-css-here-s-how-you-do-it-today-4eb5b4929852). Note: with *webpack-flush-chunks* you will have to use the `chunkNames` option instead of the `moduleIds` option to use it.
21+
> **UPDATE (July 7th):** [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import) is now required to asynchronously import both css + js. *Much Faster Builds!* You likely want to read [its intro article](https://medium.com/@faceyspacey/webpacks-import-will-soon-fetch-js-css-here-s-how-you-do-it-today-4eb5b4929852).
22+
23+
> **UPDATE (July 26th):** [babel-plugin-universal-import](https://github.com/faceyspacey/babel-plugin-universal-import) is what to use if you're using *React Universal Component*.
1824
1925
Like `extract-text-webpack-plugin`, but creates multiple css files (one per chunk). Then, as part of server side rendering, you can deliver just the css chunks needed by the current request. The result is the most minimal CSS initially served compared to emerging "render path" solutions.
2026

21-
For a demo, `git clone` this: https://github.com/faceyspacey/flush-chunks-boilerplate-webpack-chunknames
27+
For a demo, `git clone`: [universal-demo](https://github.com/faceyspacey/universal-demo)
2228

2329
*Note: this is a companion package to:*
2430
- [webpack-flush-chunks](https://github.com/faceyspacey/webpack-flush-chunks)
2531
- [react-universal-component](https://github.com/faceyspacey/react-universal-component)
26-
- [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import)
32+
- [babel-plugin-universal-import](https://github.com/faceyspacey/babel-plugin-universal-import) ***or*** [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import)
2733

28-
Read the intro article to all the "Universal" familar of packages:
29-
https://medium.com/@faceyspacey/code-cracked-for-code-splitting-ssr-in-reactlandia-react-loadable-webpack-flush-chunks-and-1a6b0112a8b8
3034

31-
32-
## Installation
35+
## Recommended Installation
3336
```
34-
yarn add --dev extract-css-chunks-webpack-plugin babel-plugin-dual-import
37+
yarn add react-universal-component webpack-flush-chunks
38+
yarn add --dev extract-css-chunks-webpack-plugin babel-plugin-universal-import
3539
```
3640

3741
*.babelrc:*
3842
```js
3943
{
40-
"presets": [whatever you usually have],
41-
"plugins": ["dual-import"]
44+
"plugins": ["universal-import"]
4245
}
4346
```
4447

4548
*webpack.config.js:*
4649
```js
47-
plugins: [
48-
new ExtractCssChunks,
49-
]
50-
```
51-
52-
## Desired Output
53-
Here's the sort of CSS you can expect to serve:
54-
55-
```
56-
<head>
57-
<link rel='stylesheet' href='/static/main.css' />
58-
<link rel='stylesheet' href='/static/0.css' />
59-
<link rel='stylesheet' href='/static/7.css' />
60-
</head>
61-
62-
<body>
63-
<div id="react-root"></div>
64-
65-
<script type='text/javascript' src='/static/vendor.js'></script>
66-
<script type='text/javascript' src='/static/0.js'></script>
67-
<script type='text/javascript' src='/static/7.js'></script>
68-
<script type='text/javascript' src='/static/main.js'></script>
69-
</body>
70-
```
71-
72-
If you use [webpack-flush-chunks](https://github.com/faceyspacey/webpack-flush-chunks), it will scoop up the exact stylesheets to embed in your response string for you.
73-
74-
***As for asynchronous calls to `import()`,*** [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import) is required. It requests both your js + your css. *Very Nice!* This is the new feature of the 2.0. Read *Sokra's* (author of webpack) article on how [on how this is the future of CSS for webpack](https://medium.com/webpack/the-new-css-workflow-step-1-79583bd107d7). Use this and be in the future today.
75-
76-
## Perks
77-
- **HMR:** It also has first-class support for **Hot Module Replacement** across ALL those css files/chunks!!!
78-
- cacheable stylesheets
79-
- smallest total bytes sent compared to "render-path" css-in-js solutions that include your CSS definitions in JS
80-
- Faster than the V1!
81-
82-
83-
## Usage
84-
```js
8550
const ExtractCssChunks = require("extract-css-chunks-webpack-plugin")
8651

8752
module.exports = {
@@ -107,36 +72,43 @@ module.exports = {
10772
}
10873
```
10974

110-
## API
111-
You can pass the same options as `extract-text-webpack-plugin` to `new ExtractCssChunks`, such as:
75+
## Desired Output
76+
Here's the sort of CSS you can expect to serve:
11277

113-
```javascript
114-
new ExtractCssChunk({
115-
filename: '[name].[contenthash].css'
116-
})
11778
```
79+
<head>
80+
<link rel='stylesheet' href='/static/main.css' />
81+
<link rel='stylesheet' href='/static/0.css' />
82+
<link rel='stylesheet' href='/static/7.css' />
83+
</head>
11884
119-
Keep in mind, by default `[name].css` is used when `process.env.NODE_ENV === 'deveopment'` and `[name].[contenthash].css` during production, so you can likely forget about having to pass anything.
120-
121-
The 2 exceptions are: `allChunks` will no longer do anything, and `fallback` will no longer do anything when passed to to `extract`. Basically just worry about passing your `css-loader` string and `localIdentName` 🤓
85+
<body>
86+
<div id="react-root"></div>
87+
88+
<script type='text/javascript' src='/static/vendor.js'></script>
89+
<script type='text/javascript' src='/static/0.js'></script>
90+
<script type='text/javascript' src='/static/7.js'></script>
91+
<script type='text/javascript' src='/static/main.js'></script>
12292
123-
## Usage with [react-universal-component](https://github.com/faceyspacey/react-universal-component), [webpack-flush-chunks](https://github.com/faceyspacey/webpack-flush-chunks) and [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import)
93+
<!-- stylsheets that will be requested when import() on user navigation is called -->
94+
<script>
95+
window.__CSS_CHUNKS__ = {
96+
Foo: '/static/Foo.css',
97+
Bar: '/static/Bar.css'
98+
}
99+
</script>
100+
</body>
101+
```
124102

125-
When using `webpack-flush-chunks` you will have to supply the `chunkNames` option, not the `moduleIds` option since the babel plugin is based on chunk names. Here's an example:
103+
If you use [webpack-flush-chunks](https://github.com/faceyspacey/webpack-flush-chunks), it will scoop up the exact stylesheets to embed in your response string for you. This is the recommended approach. Here's how you do it:
126104

127105
*src/components/App.js:*
128106
```js
129-
const UniversalComponent = universal(() => import('./Foo'), {
130-
resolve: () => require.resolveWeak('./Foo'),
131-
chunkName: 'Foo'
132-
})
133-
134-
const UniversalDynamicComponent = universal(() => import(`./base/${page}`), {
135-
resolve: ({ page }) => require.resolveWeak(`./base/${page}`),
136-
chunkName: ({ page }) => `base/${page}`
137-
})
107+
const UniversalComponent = universal(props => import(`./${props.page}`))
138108

109+
<UniversalComponent page='Foo' />
139110
```
111+
140112
*server/render.js:*
141113
```js
142114
import { flushChunkNames } from 'react-universal-component/server'
@@ -155,13 +127,43 @@ res.send(`
155127
</head>
156128
<body>
157129
<div id="root">${app}</div>
130+
${cssHash}
158131
${js}
159-
${cssHash}
160132
</body>
161133
</html>
162134
`)
163135
```
164136

137+
***As for asynchronous calls to `import()` on user navigation,*** [babel-plugin-universal-import](https://github.com/faceyspacey/babel-plugin-universal-import) is required if you're using [react-universal-component](https://github.com/faceyspacey/react-universal-component). And if you aren't, you must use: [babel-plugin-dual-import](https://github.com/faceyspacey/babel-plugin-dual-import).
138+
139+
These babel plugins request both your js + your css. *Very Nice!* This is the new feature of the 2.0. Read *Sokra's* (author of webpack) article on how [on how this is the future of CSS for webpack](https://medium.com/webpack/the-new-css-workflow-step-1-79583bd107d7). Use this and be in the future today.
140+
141+
## Perks
142+
- **HMR:** It also has first-class support for **Hot Module Replacement** across ALL those css files/chunks!!!
143+
- cacheable stylesheets
144+
- smallest total bytes sent compared to "render-path" css-in-js solutions that include your CSS definitions in JS
145+
- Faster than the V1!
146+
147+
148+
149+
150+
## API
151+
You can pass the same options as `extract-text-webpack-plugin` to `new ExtractCssChunks`, such as:
152+
153+
```javascript
154+
new ExtractCssChunk({
155+
filename: '[name].[contenthash].css'
156+
})
157+
```
158+
159+
Keep in mind, by default `[name].css` is used when `process.env.NODE_ENV === 'deveopment'` and `[name].[contenthash].css` during production, so you can likely forget about having to pass anything.
160+
161+
The 2 exceptions are: `allChunks` will no longer do anything, and `fallback` will no longer do anything when passed to to `extract`. Basically just worry about passing your `css-loader` string and `localIdentName` 🤓
162+
163+
164+
165+
166+
165167
## What about Aphrodite, Glamor, StyleTron, Styled-Components, Styled-Jsx, etc?
166168

167169
If you effectively use code-splitting, **Exract Css Chunks** can be a far better option than using emerging solutions like *StyleTron*, *StyledComponents*, and slightly older tools like *Aphrodite*, *Glamor*, etc. We aren't fans of either rounds of tools because of several issues, but particularly because they all have a runtime overhead. Every time your React component is rendered with those, CSS is generated and updated within the DOM. On the server, you're going to also see unnecessary cycles for flushing the CSS along the critical render path. *Next.js's* `styled-jsx`, by the way, doesn't even work on the server--*not so good when it comes to flash of unstyled content (FOUC).*
@@ -199,6 +201,17 @@ As an aside, so many apps share code between web and React Native--so the answer
199201
- pretty much already does everything covered by [@vjeux's 2014 css-in-js talk](https://speakerdeck.com/vjeux/react-css-in-js), besides dead code elimination. Dead code elimination is only solved for the other tools--as per the explanation above how the CSS is in the JS anyway--so much as Webpack and Uglify can remove **JS** that is not used. Either way, it's not a stretch to eventually add this feature to `extract-text-webpack-plugin` as well as this plugin. Hey, maybe it already has it??
200202

201203

204+
## Emotion!
205+
206+
[Emotion](https://github.com/tkh44/emotion) is different. They allow for the extraction of static styles via their *extract mode*. We're very much looking forward to this being the perfect companion to the css chunks approach.
207+
208+
Currently however *extract mode* does not support IE11. So that means it's a no go, but we have hopes that in the future they'll solve that problem.
209+
210+
The reason Emotion doesn't work in IE11+ is because they currently try to preserve any dynamic aspects of your CSS-in-JS by converting it CSS vars, which isn't supported in IE11. That was a very smart approach, but unfortunately not good enough.
211+
212+
The vision we'd like to see for that package is where dynamic css stays inline, and where only static CSS is extracted into stylesheets, in which case CSS vars aren't needed. I've heard from them they have some "hidden flags" that allow for something close to this. When, and if, they take this feature all the way, look forward to us pushing it as our recommended approach. *Go Emotion!*
213+
214+
202215
## Conclusion:
203216
**We love CSS modules; no less, no more.**
204217

@@ -208,3 +221,6 @@ As an aside, so many apps share code between web and React Native--so the answer
208221
## Contributing
209222
We use [commitizen](https://github.com/commitizen/cz-cli), so run `npm run cm` to make commits. A command-line form will appear, requiring you answer a few questions to automatically produce a nicely formatted commit. Releases, semantic version numbers, tags and changelogs will automatically be generated based on these commits thanks to [semantic-release](https://github.com/semantic-release/semantic-release). Be good.
210223

224+
## More from FaceySpacey in Reactlandia
225+
- [redux-first-router](https://github.com/faceyspacey/redux-first-router). It's made to work perfectly with *Universal*. Together they comprise our *"frameworkless"* Redux-based approach to what Next.js does (splitting, SSR, prefetching, and routing). *People are lovin it by the way* 😎
226+

0 commit comments

Comments
 (0)