Webpack’s import() will soon fetch JS + CSS— Here’s how you do it today

James Gillmore
Jul 7, 2017 · 6 min read
the future

“The big plan

In the long term we want to make it possible to add first-class module support for CSS to webpack. This will work the following way:

  • We adjust the Chunk Templates to write two files. One for the javascript and one of the stylesheets (in a .css file).
  • We adjust the chunk loading logic to allow loading of stylesheets. We need to wait for CSS applied or at least loaded, before executing the JS.
  • When we generate a chunk load we may load the js chunk and the stylesheet chunk in parallel (combined by Promise.all).”
  • one with CSS injection via style-loader

BACKSTORY

For this all to make sense, and if this is the first time you’re hearing about any of this, you probably want to check out:

Being able to control what static CSS files you send to clients really is a nice way to handle this problem. It’s why @sokra came to this conclusion. Being able to automatically do it is even better.

Introducing Babel-Plugin-Dual-Import + Extract CSS Chunks Webpack Plugin 2.o

babel-plugin-dual-import transforms your request to a Promise.all just as Sokra talked about, and as bonus it automatically comes up with a webpackChunkName for you. “Magic comments” are so magical they’ve disappeared. Under the hood of course I use them to generate your chunk names.

INSTALLATION

Since today we are primarily introducing the babel plugin, that’s what we’ll focus on:

yarn add --dev babel-plugin-dual-import
{
  "presets": [whatever you usually have],
  "plugins": ["dual-import"]
}
import('./Foo.js')

      ↓ ↓ ↓ ↓ ↓ ↓

import { importCss } from 'babel-plugin-dual-import/importCss.js'

Promise.all([
  import( /* webpackChunkName: 'Foo' */ './Foo'),
  importCss('Foo')
]).then(promises => promises[0]);
import(`../base/${page}`)

      ↓ ↓ ↓ ↓ ↓ ↓

import { importCss } from 'babel-plugin-dual-import/importCss.js'

Promise.all([
  import( /* webpackChunkName: 'base/[request]' */ `./base/${page}`),
  importCss(`base/${page}`)]
).then(promises => promises[0]);
import flushChunks from 'webpack-flush-chunks'
import * as Universal from 'react-universal-component/server'const appString = ReactDOM.renderToString(<App />)
                                          
const { js, styles, cssHash } = flushChunks(webpackStats, {
  chunkNames: Universal.flushChunkNames(),
})res.send(`
  <html>
    <head>
      ${styles}
    </head>
    <body>
      <div id='root'>${appString}</div>
      ${js}
      ${cssHash}
    </body>
  </html>
`)

CONCLUSION

There’s not much left to say today. So I won’t waste your time. Git clone the demo to see all 4 packages in action:


Reactlandia

The React Stack: Idiomatic Javascript in Reactlandia

James Gillmore

Written by

http://www.faceyspacey.com + http://twitter.com/faceyspacey

Reactlandia

The React Stack: Idiomatic Javascript in Reactlandia