Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
inlining-asynchronous-css
import assetsManifest from '../../build/client/assetsManifest.json';
//read the styles into an assets object during server startup
export const assets = Object.keys(assetsManifest)
.reduce((o, entry) => ({
...o,
[entry]: {
...assetsManifest[entry],
styles: assetsManifest[entry].css
? fs.readFileSync(`build/client/css/${assetsManifest[entry].css.split('/').pop()}`, 'utf8') : undefined,
},
}), {});
export const scripts = {
//loadCSS by filamentgroup
loadCSS: 'var loadCSS=function(e,n,t){func...',
loadRemainingCSS(route) {
return Object.keys(assetsManifest)
.filter((entry) => assetsManifest[entry].css && entry !== route.name && entry !== 'main')
.reduce((s, entry) => `${s}loadCSS("${assetsManifest[entry].css}");`, this.loadCSS);
},
};
//use the assets object to inline styles into your lateChunk template generation logic during runtime
lateChunk(route) {
return `
<style>${assets.main.styles}</style>
<style>${assets[route.name].styles}</style>
</head>
<body>
<div id="root">${app}</div>
<script>window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}</script>
<script src="${assets.webpackManifest.js}"></script>
<script src="${assets.vendor.js}"></script>
<script src="${assets.main.js}"></script>
<script>${scripts.loadRemainingCSS(route)}</script>
</body>
</html>
`;
},
//replace ExtractTextPlugin with ExtractCssChunks from 'extract-css-chunks-webpack-plugin'
module: {
rules: isProd ? [
{ test: /\.js$/, exclude: /node_modules/, use: ['babel-loader'] },
{ test: /\.css$/, loader: ExtractCssChunks.extract({ use: [{ loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'] }) },
//...
plugins: [
new ExtractCssChunks('css/[name].[contenthash:8].css'),
//this generates a css chunk alongside the js chunk for each dynamic import() call (route-split path in our case) for eg,
//main.hash.js, main.hash.css
//landing.hash.js, landing.hash.css
//cities.hash.js, cities.hash.css
//the landing.hash.css and cities.hash.css will contain the css rules for their respective chunks
//but will also contain shared rules between them like button, grid, typography css and so on
//to extract these shared rules to the main.hash.css use the CommonsChunkPlugin
//bonus: this also extracts the common js code shared between landing.hash.js and cities.hash.js into main.hash.js
new webpack.optimize.CommonsChunkPlugin({
children: true,
minChunks: 2,
}),
//use the assets-webpack-plugin to get a manifest of all the generated files
new AssetsPlugin({
filename: 'assetsManifest.json',
path: path.resolve('./build/client'),
prettyPrint: true,
}),
//...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment