Isomorphic Style Loader

raw JSON →
5.4.0 verified Sat Apr 25 auth: no javascript

Webpack loader for CSS that optimizes critical path rendering and supports isomorphic (universal) React apps. Current stable version is 5.4.0, released April 2022. Works like style-loader but allows server-side collection of CSS strings via _getCss() and client-side injection via _insertCss(). Uses React Context API (StyleContext) with insertCss callback. Requires React 16.8+ and css-loader. Features withStyles HOC and useStyles hook for React components. Alternative to style-loader when SSR is needed.

error Module not found: Error: Can't resolve 'isomorphic-style-loader'
cause Forgetting to install the package or incorrect import path.
fix
Run 'npm install isomorphic-style-loader --save-dev' and ensure import uses correct subpath, e.g., 'isomorphic-style-loader/withStyles'.
error TypeError: styles._getCss is not a function
cause Using the style object incorrectly – likely imported from style-loader instead of isomorphic-style-loader.
fix
Ensure the webpack rule uses 'isomorphic-style-loader' and not 'style-loader'. The style object has _getCss and _insertCss methods.
error Warning: Failed context type: The context `insertCss` is marked as required in `withStyles`, but its value is `undefined`.
cause Missing StyleContext.Provider or insertCss callback not passed.
fix
Wrap your app in <StyleContext.Provider value={{ insertCss: ... }}> with a valid insertCss function.
error Invariant Violation: withStyles requires a React component
cause Calling withStyles(styles) without wrapping a React component.
fix
Use withStyles(styles)(Component) or withStyles(styles)(React.forwardRef(...)).
breaking Upgraded React Context API in v5, breaking older withStyles usage from 'isomorphic-style-loader/lib/withStyles'.
fix Use import from 'isomorphic-style-loader/withStyles' (without /lib/) and wrap app in StyleContext.Provider.
breaking React moved to peer dependencies in v5.2.0-beta.1; earlier versions bundled React.
fix Ensure react and react-dom are installed as regular dependencies or peer dependencies.
gotcha Default export from 'isomorphic-style-loader' is the Webpack loader function, not a React utility. Importing 'isomorphic-style-loader' as a module will not give you withStyles.
fix Always use subpath imports: 'isomorphic-style-loader/withStyles', 'isomorphic-style-loader/useStyles', etc.
gotcha Browser usage without SSR: if not using StyleContext, styles won't be injected because insertCss is not called.
fix In client-side only builds, ensure StyleContext provider is set up with a insertCss function that calls styles._insertCss().
deprecated HMR (Hot Module Replacement) now output on demand; old behavior may have been automatically injecting.
fix Check documentation for configuring HMR in webpack; no breaking change but behavior differs.
npm install isomorphic-style-loader
yarn add isomorphic-style-loader
pnpm add isomorphic-style-loader

Shows webpack config, component with withStyles, and SSR setup using StyleContext and insertCss callback.

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'isomorphic-style-loader',
          { loader: 'css-loader', options: { importLoaders: 1, modules: true } },
          'postcss-loader'
        ]
      }
    ]
  }
};

// App.js
import React from 'react';
import withStyles from 'isomorphic-style-loader/withStyles';
import s from './App.css';

function App() {
  return <div className={s.root}><h1>Hello</h1></div>;
}

export default withStyles(s)(App);

// server.js
import express from 'express';
import React from 'react';
import ReactDOM from 'react-dom/server';
import StyleContext from 'isomorphic-style-loader/StyleContext';
import App from './App.js';

const server = express();
server.get('*', (req, res) => {
  const css = new Set();
  const insertCss = (...styles) => styles.forEach(style => css.add(style._getCss()));
  const body = ReactDOM.renderToString(
    <StyleContext.Provider value={{ insertCss }}>
      <App />
    </StyleContext.Provider>
  );
  const html = `<!DOCTYPE html><html><head><style>${[...css].join('')}</style></head><body><div id="root">${body}</div></body></html>`;
  res.send(html);
});
server.listen(3000);