Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

load styles before javascript - webpack 4

My JavaScript is loading before my styles, which is causing a jump and odd load.

Here is my demo: https://harp29.github.io/cb-pc/

How do I get the styles/css file to load before the JavaScript file runs via webpack? I tried setTimeout function and it works but this is a temporary solution, that is the best way to tackle this issue?

My webpack file: webpack.dev.js

const path = require("path")
const webpack = require("webpack")
const HTMLWebpackPlugin = require("html-webpack-plugin")
// const cssDev = ['style-loader', 'css-loader?sourceMap', 'sass-loader?sourceMap'];

module.exports = {
  entry: {
    main: [
      "webpack-hot-middleware/client?reload=true",
      "./src/script/main.js"
    ]
  },
  mode: "development",
  output: {
    filename: "[name]-bundle.js",
    path: path.resolve(__dirname, "../dist"),
    publicPath: "/"
  },
  devServer: {
    contentBase: "dist",
    overlay: true,
    stats: {
      colors: true
    }
  },
  devtool: "source-map",
  module: {
    rules: [{
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{
          loader: "babel-loader"
        }]
      },
      {
        test: /\.css$/,
        use: [{
            loader: "style-loader"
          },
          {
            loader: "css-loader"
          }
        ]
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader?sourceMap', 'sass-loader?sourceMap']
      },
      {
        test: /\.(jpeg|jpg|png|svg)$/,
        use: [{
          loader: "file-loader",
          options: {
            name: "images/[name].[ext]"
          }
        }]
      },
      {
        test: /\.html$/,
        use: [{
          loader: "html-loader"
        }]
      },
      {
        test: /\.pug$/,
        use: [{
          loader: "pug-loader"
        }]
      }
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HTMLWebpackPlugin({
      template: "./src/pug/index.pug",
      title: "Cervini Bhatia PC",
      inject: true
    })
  ]
}

my main.js file:

const scss = require('../scss/style.scss');
import index from '../pug/index.pug';
import favicon from '../images/favicon.png';
import logoSymbol from '../images/logo-symbol.svg';
import IntroAnimations from './module/IntroAnimations';

//Instaniate
new IntroAnimations()
.animateTimelines();

my index.pug file:

doctype html
html
  head.
    <meta charset="UTF-8">
    <title>Welcome - Cervini Bhatia PC</title>   
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" type="image/png" href="/images/favicon.png">
  body   
    include ./modules/_loading.pug
    include ./modules/_landing.pug
    include ./modules/_team-section.pug
    include ./modules/_experience.pug
    include ./modules/_firm.pug
    include ./modules/_communication.pug
    include ./layout/_footer.pug
like image 286
Harpreet Avatar asked Jul 06 '18 15:07

Harpreet


2 Answers

Easiest fix would be to include a small bit of CSS in your pug template that hides the <body>. And then include a line of JS to unhide the <body> before your animations start.


EDIT: if you would like to load your CSS file separately from your JS bundle, use the https://github.com/webpack-contrib/mini-css-extract-plugin. In your template, include a <link> tag to the public path of your generated CSS file.


This is happening because you're bundling with style-loader, which puts your CSS as a string inside your Javascript bundle.

So the HTML will render (very fast) while the browser is parsing your JS bundle (very slow). Towards the end of that bundle, the browser will find the module containing your CSS string. Then it'll parse that and apply the styles with Javascript.

like image 54
Atav32 Avatar answered Nov 16 '22 18:11

Atav32


Sounds like you have critical CSS or "above the fold" CSS.

Since you are already using pug, you should take a look at the documentation for the HtmlWebpackPlugin. They have an example of how to inline the <style>s you use that can be found here: inline example.

The basic idea is that the template has access to htmlWebpackPlugin.files which has a css property that you can iterate and append as <style>s before the <script>s which blocks parsing until the styles are applied.

Make sure that you keep this critical CSS lean. It "blocks", but this will be imperceptible as long as you don't inline a gigantic amount of CSS.

like image 43
zero298 Avatar answered Nov 16 '22 19:11

zero298