Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure that hot CSS loads before JS in webpack-dev-server?

I'm using webpack-dev-server to hot load all of my assets including CSS. Currently though, my CSS loads after the JavaScript which causes my application issues in some places that depend on layout existing.

How can I ensure that the CSS loads before the JavaScript executes?

I'm thinking there must be a way to do this from module, perhaps a a callback I could hook in to? Or maybe by configuring the style-loader to have priority?

This is my index.js:

import './styles/main.scss';
import './scripts/main.js';

if (module.hot) {
  module.hot.accept();
}

and this is my styles loader:

{
        test: /\.(scss)$/,
        loader: 'style!css?&sourceMap!postcss!resolve-url!sass?sourceMap'
},

A similar question has been asked at this style-loader Github Issue: https://github.com/webpack/style-loader/issues/121

like image 619
Elise Chant Avatar asked Sep 08 '16 20:09

Elise Chant


2 Answers

I was having the exacly same issue, in production the css are extracted so it always work, however in development because of the style-loader "sometimes executing after the main bundle" i had issues where the main bundle would calculate the size of some nodes in the DOM which was set by the css... so it could result to wrong sizes as the main css still havent loaded... i fixed this issue by having the option singleton:true.

example:

{
    test: /\.s?css$/,
    loader: ExtractTextPlugin.extract({
            fallback: [
                {
                    loader: 'style-loader',
                    options: { singleton: true }
                }
            ],
            use: [
                {
                    loader: 'css-loader',
                    options: {
                        importLoaders: 1,
                        minimize: !isProduction,
                        sourceMap: !isProduction
                    }
                },
                { loader: 'postcss-loader', options: { sourceMap: !isProduction, ...postcss } },
                { loader: 'resolve-url-loader', options: { sourceMap: !isProduction } },
                { loader: 'sass-loader', options: { sourceMap: true } }
            ]
        }
    )
}
like image 199
Rafael Milewski Avatar answered Oct 27 '22 12:10

Rafael Milewski


Looks like there's no event, callback or any way to detect that the style has been loaded. After long hours of searching in vain, I had to do something really dirty:

function checkCSS() {
  const repeat = requestAnimationFrame(checkCSS);
  // CSS loaded?
  if(getComputedStyle(document.body).boxSizing === 'border-box') {
    routes.loadEvents() // Init JS
    cancelAnimationFrame(repeat) // Cancel next frame
  }
}
if (process.env.NODE_ENV !== 'production') {
  checkCSS()
} else {
  $(document).ready(() => {
    routes.loadEvents()
  })
}

Because I have * { box-sizing: border-box; } in my styles and that I'm pretty sure native CSS styles won't never look like this, I can be ~99% sure that my own CSS is loaded.

I died a little writing this. Hopefully we'll find a better way!

like image 20
Nico Prat Avatar answered Oct 27 '22 13:10

Nico Prat