Learn Webpack in React Js | A step-by-step Guide 2022 ( Part-II )
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 likeimport
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.
- entry: The
entry
object is from where the webpack starts building the bundle. - 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. - 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. - 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 :(
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
Now let’s open our dist/index.html file in the browser
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!