11

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

Elise Chant
  • 5,048
  • 3
  • 29
  • 36
  • Currently I think the best approach might actually be to not use Sass altogether. Although it doesn't directly solve this issue. – Elise Chant Jan 21 '17 at 23:52

2 Answers2

6

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 } }
            ]
        }
    )
}
Rafael Milewski
  • 788
  • 1
  • 8
  • 15
  • I have the same exact thing: JS components that rely on existing DOM style for various calculations. Using the singleton also worked for me, thanks for this. – Gavin Jun 12 '18 at 20:53
1

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!

Nico Prat
  • 686
  • 2
  • 6
  • 13