Skip to content

Lundalogik/sparta-isomorphic-style-loader

 
 

Repository files navigation

Isomorphic CSS style loader for Webpack

NPM version NPM downloads Build Status Dependency Status Chat

An alternative CSS style loader, which works similarly to style-loader, but is optimized for isomorphic apps. In addition to what style-loader provides, it allow to render critical path CSS during server-side rendering (SSR), by adding two helper methods on to the styles object - ._insertCss() (injects CSS into the DOM) and ._getCss() (returns CSS string).

How to Install

$ npm install isomorphic-style-loader --save-dev

Getting Started

Webpack configuration:
{
  module: {
    loaders: [
      {
        test: /\.scss$/,
        loaders: [
          'isomorphic-style-loader',
          'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:3]',
          'postcss-loader'
        ]
      }
    ]
  }
}

Note: Configuration is the same for both client-side and server-side bundles.

React component example
// MyComponent.scss
.root { padding: 10px; }
.title { color: red; }
// MyComponent.js
import React, { PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './MyComponent.scss';

function MyComponent(props, context) {
  return (
    <div className={s.root}>
      <h1 className={s.title}>Hello, world!</h1>
    </div>
  );
}

export default withStyles(MyComponent, s);        // <--

P.S.: It works great with CSS Modules! Just decorate your React component with the withStyles higher-order component, and pass a function to your React app via insertCss context variable (see React's context API) that either calls styles._insertCss() on a client, or styles._getCss() on the server. See server-side rendering example below:

import express from 'express';
import ReactDOM from 'react-dom';
import router from './router.js'; // <-- isomorphic router, see react-starter-kit for example

const server = express();
const port = process.env.PORT || 3000;

// Server-side rendering of the React app
server.get('*', (req, res, next) => 
  const css = []; // CSS for all rendered React components
  const context = { insertCss: (styles) => css.push(styles._getCss()) };
  router.dispatch({ ...req, context }).then((component, state) => {
    const body = ReactDOM.renderToString(component);
    const html = `<!doctype html>
      <html>
        <head>
          <script async src="/client.js"></script>
          <style type="text/css">${css.join('')}</style>
        </head>
        <body>
          <div id="root">${body}</div>
        </body>
      </html>`;
    res.status(state.statusCode).send(html);
  }).catch(next);
});

server.listen(port, () => {
  console.log(`Node.js app is running at http://localhost:${port}/`);
});

It should generate an HTML output similar to this one:

<html>
  <head>
    <title>My Application</title>                                    
    <script async src="/client.js"></script>
    <style type="text/css">
      .MyComponent_root_Hi8 { padding: 10px; }
      .MyComponent_title_e9Q { color: red; } 
    </style>
  </head>
  <body>
    <div id="root">
      <div class="MyComponent_root_Hi8" data-reactid=".cttboum80" data-react-checksum="564584530">
        <h1 class="MyComponent_title_e9Q" data-reactid=".cttboum80.0">Hello, World!</h1>
      </div>
    </div>
  </body>
</html>

Regardless of how many styles components there are in the app.js bundle, only critical CSS is going to be rendered on the server inside the <head> section of HTML document. Critical CSS is what actually used on the requested web page, effectively dealing with FOUC issue and improving client-side performance. CSS of the unmounted components will be removed from the DOM.

Backers

♥ Isomorphic Style Loader? Help us keep it alive by donating funds to cover project expenses!

Related Projects

Support

License

The MIT License © 2015-2016 Kriasoft, LLC. All rights reserved.


Made with ♥ by Konstantin Tarkus (@koistya) and contributors

Packages

No packages published

Languages

  • JavaScript 100.0%