Learn Webpack in React Js | A step-by-step Guide 2022 ( Part-II )

M Umair Awan
5 min readAug 21, 2022

--

Unleashing the Power of Styles: Using style-loader, css-loader, and sass-loader in React with Webpack.

Recap

In the previous part of this series, we discussed the basics of webpack, and we followed through with a simple example that tells you how to set up webpack, webpack-cli and we got a brief overview for HtmlWebpackPlugin.

Overview

In this article, we would focus on how we can bundle any static resource way beyond JavaScript. And loaders are the way to do that.

Loaders are transformations that are applied to the source code of a module. They allow you to pre-process files as you import or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or load inline images as data URLs. Loaders even allow you to do things like import CSS files directly from your JavaScript modules!
source: https://webpack.js.org/concepts/loaders

Before we move to the actual implementation of loaders, let's first look at our current webpack.config.js file.

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
entry: path.resolve(__dirname, "src/index.js"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack App by M Umair",
filename: "index.html",
template: "src/template.html",
}),
],
};

Let’s discuss a few keywords in this file.

  1. entry: The entry object is from where the webpack starts building the bundle.
  2. output: The output key contains a set of options that tells webpack on how and where it should output your bundles, assets, and anything else you bundle or load with webpack.
  3. plugins: This plugin option is used to customize the webpack build process in a variety of ways. Webpack comes with a variety of built-in plugins available, and these plugins allow you to customize the behavior and process of the build in many ways.
  4. mode: With possible values being ‘development’ | ‘production’ | ‘none’, this object defines the value for process.env.NODE_ENV on the DefinePlugin (we will discuss this object in more detail later in the series)
    source: https://webpack.js.org/

Other than these objects, there is another interesting one that we are going to use today.

module: This object helps us load discrete chunks of functionality that we call modules in our application. e.g “style-loader”, “css-loader”, “sass-loader”

Ok. Enough with theoretical stuff, let’s move to the actual example

Tutorial

In the first part of the series, we created a js file and our html template, and made a build of those files, but our html does not look that good. I think we should style that a little.

So, lets create a new file src/styles/style.scss with following content.

body {
background-color: black;
}
.btn {
background: #5e5df0;
border-radius: 999px;
box-shadow: #5e5df0 0 10px 20px -10px;
box-sizing: border-box;
color: #ffffff;
cursor: pointer;
font-family: Inter, Helvetica, "Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols, -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", sans-serif;
font-size: 16px;
font-weight: 700;
line-height: 24px;
opacity: 1;
outline: 0 solid transparent;
padding: 16px 36px;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
width: fit-content;
word-break: break-word;
border: 0;
margin: auto;
transition: all 1s;
margin-top: 20px;
}
.btn:hover {
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
transform: scale(0, 0, 0);
perspective: 1000px;
}
@keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}
20%, 80% {
transform: translate3d(2px, 0, 0);
}
30%, 50%, 70% {
transform: translate3d(-2px, 0, 0);
}
40%, 60% {
transform: translate3d(2px, 0, 0);
}
}

Now let's try to import this file into our src/index.js file.

import demo from "./demo";
import "./styles/style.scss";
console.log(demo());

Let’s make a build now

npm run build

Oh! What’s this? We got an error :(

You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

Looks like our general does not have enough preparation for this strange scenario. Let’s provide him with some help

npm i -D style-loader css-loader sass-loader sass

Now let's send these helpers to our camp webpack.config.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: "development",
entry: path.resolve(__dirname, "src/index.js"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "main.js",
},
module: {
rules: [{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
}, ],
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack App by M Umair",
filename: "index.html",
template: "src/template.html",
}),
],
};

So, as you can see, we have defined a module rule that says for files with scss extension, use style-loader, css-loader, and sass-loader

Note:
The webpack applies rules from last to first, so first, our sass-loader will compile the scss file, then the css-loader will create a string containing all the css referenced in our code and then the style loader will inject that string to the <style> in our html code.

Now let’s create our build again

npm run build
Build Successful :)

Now let’s open our dist/index.html file in the browser

Hooray!!!

Great! You can see that our styles are successfully loaded in our build.

That’s all for this part of the series, next we will discuss how to build images and how to achieve hot reloading in our app, just like when you create react app using create-react-app. So stay tuned!

--

--