Get In Touch
admin@victoriaweb.me
Back

Basics of building Frontend projects with Webpack

As of 2025, Webpack remains one of the most popular build tools, alongside Vite. This article provides a detailed, step-by-step guide on how to build a simple landing page, which I practiced myself.

webpack logo

Step 1 – Installing Node.js

The first thing you need is to have Node.js and Node Package Manager (npm) installed. Both can be installed together using this link: https://nodejs.org/en/download/prebuilt-installer/current. During installation, you can select the necessary parameters, such as your operating system, architecture, etc. Here’s the link to the Prebuilt Installer.

To verify if the installation was successful, enter the following two commands sequentially in the command line:

node -v 
npm -v

Перша має показати яка версія node.js встановлена на комп`ютері, друга – версію npm.

Step 2 – Creating Project Structure

The standard project structure involves a src folder for development, containing all the project files (HTML, CSS, images, JS, etc.). The final build output goes into the dist folder, which is created automatically when the build command is run for the first time. These two folders are located within the main project directory, which should be named accordh during development and production, and adds it to “dependencies”.ing to the rules outlined below.

For a landing page (a single-page site), create a folder named after your project, for example, ModernLandingPage. It’s best to use folder names without spaces to avoid renaming issues later, especially if you’re working with Git. Follow these best practices for naming folders:

1. Use of permitted characters

Use only letters (Latin), numbers, hyphens (-), and underscores (_). Avoid using spaces and special characters (e.g. @, #, !, %, etc.). Use spaces by replacing them with hyphens or underscores, e.g. my-project or my_project.

2. Character Case

It is best to use lowercase for naming to avoid confusion on different operating systems that may be case sensitive (for example, Linux distinguishes between Folder and folder).

3. Name Length

Avoid very long file and folder names. Short and descriptive names are better for ease of use. The maximum length of a file or folder path (including all subfolders) may be limited by the system; for example, Windows has a limit of 260 characters.

4. Using meaningful names

Use names that logically reflect the contents or purpose of the folder. This will help you and other developers navigate your project more easily.

5. Avoid reserved words

Avoid using operating system or Git reserved words (e.g. CON, PRN, AUX, NUL on Windows).

6. Avoiding different encodings

Avoiding different encodings Use UTF-8 for file and folder names to ensure maximum compatibility.

7. Features of working with Git

Git works best with ASCII characters, so it’s best to avoid non-ASCII characters (such as Cyrillic characters) to avoid potential problems with different systems or when collaborating with other developers.

Examples of Correct Folder Names:

  1. my_project
  2. src
  3. test-files
  4. config
  5. backup_2024
  6. docs
  7. scripts
  8. assets
  9. lib_v1
  10. user-data

Examples of Incorrect Folder Names:

  1. My Project (space between words)
  2. src#1 (special character #)
  3. test/files (character / is used as a path separator)
  4. con (reserved word in Windows)
  5. backup@2024 (special character @)
  6. Documents (incorrect use of Cyrillic)
  7. scripts! (special character !)
  8. assets% (special character %)
  9. lib\v1 (character \ is used as a path separator)
  10. user:data (colon : is a special character in many OSes)

Step 3 – Creating a New Project

After we have created the main project directory, we navigate to it from the command line:

npm init -y

This command will create a package.json file where the project settings will be stored.

Do You Need to Install Webpack Globally and Locally?


Global Webpack Installation (Optional and Rarely Needed):

Global installation installs Webpack on your computer in a way that makes it accessible from the command line in any directory.

npm install -g webpack webpack-cli

When is it Needed?

Developers may use global installation if they frequently create projects and want quick access to Webpack commands.
Cons: Using globally installed packages can lead to version conflicts, especially if different projects require different versions of Webpack. This can cause compatibility issues.

Step 4 – Local Installation

npm install webpack webpack-cli --save-dev

Installs Webpack in the project directory. This is generally considered the best practice because:

  • It ensures that a specific project uses the specific version of Webpack required for that project.
  • It allows other developers working on your project to have the same dependency versions without needing to install them globally.


Detailed explanations of other Webpack installation commands

npm install webpack webpack-cli --save-dev

This command installs both webpack and webpack-cli as development dependencies. It is recommended to use this command when installing Webpack locally in a project.

npm install --save-dev webpack

This command installs only webpack as a development dependency. It does not install webpack-cli, which is also required for working with Webpack via the command line. To use Webpack from the command line, you need to install webpack-cli as well. The command can be extended as follows: npm install --save-dev webpack webpack-cli.

npm install webpack webpack-cli

This command installs webpack and webpack-cli as dependencies, but by default in the "dependencies" section (production dependencies) of the package.json file. It is recommended to use --save-dev because Webpack is typically used only during development, not in production.

In our case, we install Webpack locally using the command:

npm install webpack webpack-cli --save-dev

This ensures that all dependencies (both webpack and webpack-cli) are installed for development and prevent compatibility issues between projects:

–save-dev: Specifies that the dependency is required only during development and adds it to “devDependencies”.
Without –save-dev: Specifies that the dependency is required both during development and production, and adds it to “dependencies”.

Step 5 – configuring Webpack to build your project

This is a pretty standard setup – styles are written in SCSS, which the MiniCssExtractPlugin converts to CSS and outputs into the dist folder. The CopyWebpackPlugin copies the reset.css file from src to dist without modifying it.

In the root directory of your project, create webpack.config.js manually or via command line:

touch webpack.config.js

This file will contain all your Webpack settings:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/',
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader',
        ],
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'images/[name][ext]',
        },
      },
    ],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css',
    }),
    new CopyWebpackPlugin({
      patterns: [
        { from: 'src/images', to: 'images' },
        { from: 'src/css/reset.css', to: 'css/reset.css' },
      ],
    }),
  ],
  devServer: {
    static: {
      directory: path.join(__dirname, 'dist'),
    },
    compress: true,
    port: 9000,
    open: true,
    hot: true,
    devMiddleware: {
      writeToDisk: true,
    },
  },
  mode: 'development',
};

Configuration explained:

const path = require('path');
  • Description: Imports the Node.js module path, which provides utilities for file and directory paths.
  • Purpose: Used to build absolute paths to files and folders on your file system, preventing errors from using relative paths.
const HtmlWebpackPlugin = require('html-webpack-plugin');
  • Description: Imports the html-webpack-plugin for Webpack.
  • Purpose: Automatically generates an HTML file in your build directory (dist) and injects all compiled scripts and styles. It automates including JS and CSS files in your HTML.
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
  • Description: Imports the clean-webpack-plugin.
  • Purpose: Cleans (removes) all files in the build directory (dist) before each new build to avoid leftover or unused files.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  • Description: Imports the mini-css-extract-plugin.
  • Purpose: Extracts CSS from your JavaScript modules into separate CSS files, improving site performance by loading styles independently of scripts.
const CopyWebpackPlugin = require('copy-webpack-plugin');
  • Description: Imports the copy-webpack-plugin.
  • Purpose: Copies files or entire folders from the src directory into dist (or another build folder), preserving structure. Useful for static assets like images or CSS files (e.g. reset styles) that don’t require Webpack processing.

Explanation of each key in the config

The code block module.exports = { ... }; exports an object as the Webpack configuration. This object contains all settings Webpack uses to build your project. Let’s go through each key and explain its purpose.

entry: './src/index.js',
  • Description: Connects the copy-webpack-plugin plugin.
  • Purpose: This plugin copies files or entire folders from the src directory to the dist directory (or another build folder), preserving their structure. It is useful for copying static files that do not need to be processed by Webpack, such as images or CSS files used as style resets.
output: {
  filename: 'bundle.js',
  path: path.resolve(__dirname, 'dist'),
  publicPath: '/',
},
  • Description: Configures where Webpack should emit the output files.
  • filename: Name of the output file(s). Here, it’s bundle.js.
  • path: Absolute path to the output directory. path.resolve(__dirname, 'dist') uses Node’s path module to point Webpack to dist.
  • publicPath: Base URL for all assets (images, fonts, etc.). Here it’s the root (/).
module: {
  rules: [
    {
      test: /\.scss$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        'sass-loader',
      ],
    },
    {
      test: /\.css$/,
      use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
      ],
    },
    {
      test: /\.(png|svg|jpg|jpeg|gif)$/i,
      type: 'asset/resource',
      generator: {
        filename: 'images/[name][ext]',
      },
    },
  ],
},
  • Description: Configures how different file types (JavaScript, CSS, images, etc.) should be handled during the build process. rules: An array of rules where each rule specifies how to handle a particular file type.
  • Each rule contains:
  • test: A regular expression (RegExp) that defines the type of files to which the rule applies. For example, /\.scss$/ matches all files ending in .scss.
  • use: An array of loaders that will be applied to files that match the test.
  • MiniCssExtractPlugin.loader: Extracts CSS into separate files.
  • css-loader: Processes CSS files and adds them to JavaScript.
  • sass-loader: Compiles SCSS into CSS.
  • type: The type of file processing. asset/resource processes files as resources (copies them to the output directory).
  • generator: Allows you to customize the name and path for the generated files. In the example, the images will be stored in the images folder in the output directory.Description: Connects the copy-webpack-plugin.
  • Purpose: This plugin copies files or entire folders from the src directory to the dist directory (or another build folder), preserving their structure. It is useful for copying static files that do not need to be processed by Webpack, such as images or CSS files used as style resets.
plugins: [
  new CleanWebpackPlugin(),
  new HtmlWebpackPlugin({
    template: './src/index.html',
  }),
  new MiniCssExtractPlugin({
    filename: 'css/[name].css',
  }),
  new CopyWebpackPlugin({
    patterns: [
      { from: 'src/images', to: 'images' },
      { from: 'src/css/reset.css', to: 'css/reset.css' },
    ],
  }),
],
  • Description: An array of plugins that add additional functionality to the build process.CleanWebpackPlugin: Cleans up the source directory (dist) before a new build.
  • HtmlWebpackPlugin: Automatically generates an HTML file and adds all the collected scripts and styles to it.
  • MiniCssExtractPlugin: Extracts CSS into separate files and saves them in the css folder.
  • CopyWebpackPlugin: Copies files or folders from src to dist without modification.Cleans the output directory (dist) before a new build.
  • HtmlWebpackPlugin: Automatically generates an HTML file and adds all the collected scripts and styles to it.
  • MiniCssExtractPlugin: Extracts CSS into separate files and saves them in the css folder.
devServer: {
  static: {
    directory: path.join(__dirname, 'dist'),
  },
  compress: true,
  port: 9000,
  open: true,
  hot: true,
  devMiddleware: {
    writeToDisk: true,
  },
},
  • Description: Configuration for Webpack DevServer – a local development server that simplifies the dev process.
  • static: Specifies the directory to serve static files from (in this case, dist).
  • compress: Enables gzip compression to reduce response size and improve load times.
  • port: Defines the port the server runs on (9000).
  • open: Automatically opens the browser after the server starts.
  • hot: Enables Hot Module Replacement (HMR) – updates changed modules without a full page reload.
  • devMiddleware: Additional settings for the dev middleware.
  • writeToDisk: Allows writing files to disk – useful for debugging.
mode: 'development',
  • Description: Defines the Webpack operating mode.
  • Purpose: mode can be 'development' or 'production'. In development mode, Webpack generates unminified files with source maps for easier debugging. In production mode, Webpack optimizes and minimizes files for faster loading.

Step 6 – installing dependencies

Install all necessary dependencies used in your Webpack config file – including Webpack itself, plugins, and loaders:

npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save-dev html-webpack-plugin clean-webpack-plugin mini-css-extract-plugin copy-webpack-plugin
npm install --save-dev css-loader sass-loader style-loader
npm install --save-dev @babel/core @babel/preset-env babel-loader

Here we’re installing:

  • Webpack and webpack-cli: the core packages to run Webpack.
  • webpack-dev-server: for running a local development server.
  • html-webpack-plugin, clean-webpack-plugin, mini-css-extract-plugin, copy-webpack-plugin: plugins used in the configuration.
  • css-loader, sass-loader, style-loader: loaders for handling CSS and SCSS files.
  • babel-loader, @babel/core, @babel/preset-env: for transpiling modern JavaScript to more compatible code.

Step 7 – verifying required project files

Create the necessary folder and file structure for your project if it doesn’t exist yet, for example:

mkdir src
touch src/index.js
touch src/index.html
mkdir src/css
touch src/css/styles.scss
mkdir src/images
  • src/: Directory for the project’s source files.
  • src/index.js: Main JavaScript file (entry point).
  • src/index.html: HTML template file for HtmlWebpackPlugin.
  • src/css/styles.scss: SCSS file for styles.
  • src/images: Directory for storing image assets.

It is very important to place files correctly in folders so that the paths in the config file resolve properly – otherwise, the build will fail.

If the project includes JavaScript – you need to configure Babel

If you’re going to use modern JavaScript (ES6+), you need to configure Babel. Create a file named .babelrc in your project’s root:

{
  "presets": ["@babel/preset-env"]
}

This allows Babel to transpile modern JavaScript into code compatible with most browsers.

Step 8 – configuring npm scripts

In your package.json file, add scripts to run Webpack in development or production mode:

 "scripts": {
    "clean": "rm -rf dist",
    "build": "webpack --mode production",
    "start": "webpack serve --mode development"
  },

Step 9 – build control commands

Developing the project

After setting up everything, you can start development. Use the command npm start to launch the local dev server:

npm start

Webpack DevServer will start the server, build the project in memory, and open your browser for preview. All changes in your files (JavaScript or SCSS) will be reflected automatically in the browser thanks to Hot Module Replacement (HMR).

Production build

When your project is ready to deploy, build it in production mode using this command:

npm run build

This command will generate optimized files in the dist directory (or other specified build folder), ready for deployment to a server.

Verification and optimization

Check your project after building to ensure all resources are correctly linked and working. Optimize the final output if needed (e.g. compressing images or JS files).

Step 10 – deploying the project

After development and testing, the generated project can be deployed to any web server or hosting platform. Copy all files from the dist folder to your server, or use deployment methods like FTP, Git, CI/CD, etc.

Summary

After configuring the Webpack config file, the next steps are initializing the project, installing dependencies, creating required files and folders, configuring Babel (if needed), setting up npm scripts, running the dev mode, building for production, testing, optimizing, and deploying the project to a server.

Official Webpack documentation: https://webpack.js.org/guides/getting-started/#basic-setup

Victoriia Hladka
Victoriia Hladka
https://victoriaweb.me