Getting Started with Webpack: A Beginner’s Guide - Part 2
In the previous blog, we have seen how webpack has evolved, webpack core concepts, and installation & setup. If you didn't read the previous article, read it before reading this article. Here is the link for Part 1
In this blog, we will look into some loaders & plugins that we commonly use during development, with examples.
Difference between Webpack and Loader
Firstly, let's see the difference between Webpack and Loader.
Loaders transform the files into modules that Webpack can understand and include in the bundle. They handle different file types, like CSS, images, or modern JavaScript, and convert them so Webpack can include them in your project.
some of the loaders like Babel Loader (which transpiles modern JavaScript), CSS Loader (which handles CSS files), and File Loader (which manages file assets like images). We will go through an example.
Now what does Webpack do?🤔
Webpack puts all your files and dependencies together into one or more bundles. It uses loaders to process the files and then combines them into a final output file (like bundle.js
). It also optimizes the files and handles things like splitting code into chunks.
In short, loaders process individual files, while Webpack bundles everything together and makes sure it all works as one.
Role of Plugins
We have seen the difference between loaders and Webpack; then what is the role of the plugins here? 🤔
Plugins in Webpack extend and customize its functionality beyond what loaders can do. For example-
Optimize Bundles: Improve performance by minimizing and compressing files.
Generate Files: Create additional files, like an HTML file that links to your bundles.
Run Custom Code: Perform custom tasks during the build process.
Commonly used loaders and plugins
Before learning about Babel loader, first we should know about Babel
What is babel?
Babel is a JavaScript compiler that converts modern JavaScript code into a version that is compatible with older browsers.
Some key features of Babel
Transpiling Modern JavaScript: Converts new JavaScript syntax (like arrow functions, classes, etc.) into older syntax so it can run in all browsers.
Polyfilling: Adds missing features to older browsers. For example, if you use
Promise
in your code, Babel can add code (polyfill) to make it work in older browsers that don't support itPromise
.Presets are collections of plugins. For example,
@babel/preset-env
is a preset that includes all necessary plugins to transform modern JavaScript.Source Maps: This helps with debugging by mapping your transformed code back to the original source code.
Babel Loader
We have learnt about Babel and Webpack. To integrate both of them, we use babel-loader
. In terms of a typical definition, Babel Loader is a tool that lets you use Babel with Webpack. It transforms modern JavaScript into an older version that can run in all browsers during the Webpack build process.
Then how to use Babel Loader in our application. let's see
How to Use Babel Loader
Install Babel and Babel Loader:
First, let's install the required modules in our application. Make sure Node is installed on your system before running these commands.
npm install --save-dev @babel/core @babel/preset-env babel-loader core-js
@babel/core: The main engine of Babel that processes and transforms modern JavaScript code into a version compatible with older browsers.
@babel/preset-env: A set of rules for Babel that automatically determines which modern JavaScript features need to be transformed based on the browsers you want to support.
core-js: It is a library that provides polyfills to add support for new JavaScript features in browsers that don’t support them natively.
Babel configuration
We have different options for this. We can directly give the babel configuration directly in the
webpack.config.js
file, or We can create a file calledbabel.config.js
or.babelrc
in our project root. For now, I will choosebabel.config.js
file.{ "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3 }] ] }
Here, the useBuiltIns option tells how polyfills are added to your code.
"useBuiltIns": "usage"
means Babel automatically adds the necessary polyfills for the features you use in your code. It analyzes your code and includes only the polyfills that are needed, which helps to reduce the final bundle size."corejs":3
option species which version ofcore-js
to use.core-js
is a library that provides polyfills for modern JavaScript features.
If you want to add presets directly to webpack.config.js
file, you can write like this:
const path = require('path');
module.exports = {
mode: 'development', // or 'production'
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3
}]
]
}
}
}
]
}
};
Here,
module.rules: This option sets the rules for processing files
test: /\.js$/
This option specifies that Babel Loader should process files ending with.js
.exclude: /node_modules/
This option specifies that you ignore the JavaScript files innode_modules
folder to improve build performance.use: { loader: 'babel-loader'}
: This option specifies thatbabel-loader
should handle the transmissionoptions: {}
It allows the configuration of Babel options directly within Webpack.
Some Examples:
Transpiling ES6+ Syntax to ES5 for arrow functions
JS Input (ES6+):
const add = (a, b) => a + b;
JS output (after processing with Babel):
Arrow functions are converted to regular function expressions for compatibility with older browsers.
function add(a, b) { return a + b; }
Polyfilling: New features
for example,
Array.prototype.includes
JS Input:
const numbers = [1, 2, 3]; console.log(numbers.includes(2));
JS output (after processing with Babel):
Polyfills are added to support new methods (
Array.prototype.includes
) in environments that don’t natively support themrequire('core-js/modules/es.array.includes'); const numbers = [1, 2, 3]; console.log(numbers.includes(2));
Transforming JSX (React)
JSX Input:
const element = <div>Hello, world!</div>;
JS output (after processing with Babel):
JSX is converted to React.createElement calls, which are compatible with the React library.
const element = React.createElement('div', null, 'Hello, world!');
What is PostCSS?
We have seen what Babel does in the case of javascript; likewise, PostCSS also do the same thing in the case of CSS transformation.
PostCSS is a tool that processes your CSS using JavaScript plugins. These plugins can do various things, like add browser prefixes, minify your CSS, and enable new CSS features
Some key features of PostCSS
Usage of plugins: PostCSS uses plugins to perform different tasks, like adding browser prefixes or minifying CSS.
For example: Adding Vendor Prefixes
To add browser-specific prefixes automatically (e.g.,-webkit--moz-
), use the Autoprefixer plugin.
For PostCSS configuration, we usepostcss.config.js
file. Add this code to the configuration file:module.exports = { plugins: [ require('autoprefixer') ] };
CSS Input:
.display { display: grid; }
CSS output (after processing):
.display { display: -ms-grid; display: grid; }
Compatibility: It helps make your CSS work in all browsers by automatically adding necessary prefixes.
For example: To use the new CSS featuresnesting
, you can use thepostcss-preset-env
plugin which enables modern CSS featuresAdd this code to the postcss configuration file:
module.exports = { plugins: [ require('postcss-preset-env')({ stage: 0 // Here this value enable the all modern CSS features }) ] };
CSS Input:
.card { border: 1px solid black; .title { font-weight: bold; } }
CSS output (after processing):
.card { border: 1px solid black; } .card .title { font-weight: bold; }
Optimization: Minify your CSS to make it smaller and load faster.
For example, to reduce the size of your CSS for production, use the
cssnano
plugin. In the modification process, it will remove comments, remove spaces, remove redundant code, remove unused CSS rules, etc.Add this code to the postcss configuration file:
module.exports = { plugins: [ require('cssnano')({ preset: 'default' }) ] };
CSS Input:
.card { border: 1px solid black; padding: 10px; }
CSS output (after processing):
.card{border:1px solid #000;padding:10px}
How to set up PostCSS
Install required packages
npm install --save-dev postcss postcss-loader autoprefixer cssnano postcss-preset-env
Create PostCSS Configuration:
Create a file named
postcss.config.js
in your project rootmodule.exports = { plugins: [ require('postcss-preset-env')({ stage: 0 }), require('autoprefixer'), require('cssnano')({ preset: 'default', }) ] };
Configure Webpack to use PostCSS:
const path = require('path'); module.exports = { mode: 'development', // or 'production' entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, // exclude: /node_modules/, use: 'babel-loader' }, { test: /\.css$/, use: [ 'style-loader', 'css-loader', 'postcss-loader' ] } ] } };
Let's see how all CSS loaders work together:
CSS Import:
Import CSS into the JavaScript file:
import './styles.css';
Processing with
css-loader
:css-loader
processes the CSS file, handling@import
andurl()
statements, and converts the CSS into a JavaScript module.PostCSS Transformation with
postcss-loader
:postcss-loader
applies PostCSS plugins to the CSS, performing tasks such as adding vendor prefixes, enabling modern CSS features, and optimizing the CSS.Injecting into the DOM with
style-loader
:style-loader
injects the processed CSS into a<style>
tag in the DOM, making sure that the styles are applied to your page.
Like this, we have some other loaders
Sass Loader (sass-loader): It compiles Sass or SCSS files into CSS.
TypeScript Loader (ts-loader): It transpiles TypeScript files into JavaScript.
File Loader (file-loader): It handles importing files like images and fonts. It emits the files to the output directory and returns the URL to the file.
Html Loader (html-loader): It handles importing HTML files, inlining them or converting them into modules
Conclusion
From this blog, we learned about Webpack and how it helps with web development:
What Webpack Does: It bundles and optimizes your code and assets for better performance
Loaders: These tools preprocess different file types, like converting JavaScript with Babel or compiling Sass into CSS with examples
Optimization: Webpack can make your site faster by reducing file sizes and loading only what's needed.
Why It’s Important
Understanding Webpack helps you build faster, more efficient websites and manage your code and assets effectively. It’s a must-have tool for modern web development
References
https://webpack.js.org/concepts
https://github.com/rajeshpolarati/Webpack-Example-Project
Want to dive deeper into web development topics and stay updated? Connect with me on LinkedIn and Instagram for more insights and tips. See you there!
Subscribe to my newsletter
Read articles from Rajesh Polarati directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Rajesh Polarati
Rajesh Polarati
Full Stack Developer experienced in creating scalable web applications. Proficient in React, Express.js, Node.js, and SQL, MongoDB, Kafka, DSA. Skilled in team collaboration and passionate about building efficient, responsive solutions