Learn to Code via Tutorials on Repl.it

← Back to all posts
🚀 Using Webpack To Bootstrap A JS App (Webpack Dev Server)💎
h
eankeen (758)

🚀 Using Webpack To Bootstrap A JS App (Webpack Dev Server)💎

Webpack is an integral part of modern JavaScript tooling. It bundles all your JavaScript modules and has plugins for bundling CSS, JSX, and many other files. It's used for creating React and Vue single page applications and much more!

We're going to be manually configuring Webpack to work using the official webpack-dev-server!

Prerequisites

  • Intermediate experience with JavaScript
  • Understand basic Webpack concepts

Note that a few days ago I created a Webpack tutorial here, but I used Express among other middleware and tooling. After I made that tutorial, I realized that it's definitely possible after studying the config of an ejected create-react-app. So I would recommend using this approach as it is easier. I typically wouldn't be posting such a similar tutorial in a small amount of time, but this method is truly more flexible and less confusing.

Getting Started

Typically we create our projects (in development) using webpack-dev-server. We're going to be configuring and creating a quick Webpack development server.

Creating the Configuration

Let's start off with requiring the packages and configuration files we need.

// index.js
let path = require("path");
let webpack = require("webpack");
let webpackDevServer = require("webpack-dev-server");
let webpackConfig = require("./webpack.config");

Remember to add express and webpack-dev-server as a dependency.

Now, let's create that webpack.config.js configuration file. We're going to be including all the standard stuff. Be sure to add friendly-errors-webpack-plugin and html-webpack-plugin to your package.json. Most of this configuration is directly copied from the Express Webpack tutorial I posted recently.

// webpack.config.js
const path = require("path");
const webpack = require("webpack");
const FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development",
  devtool: "cheap-module-eval-source-map",
  entry: {
    main: path.resolve(process.cwd(), "src", "main.js")
  },
  output: {
    path: path.resolve(process.cwd(), "dist"),
    publicPath: "/"
  },
  watchOptions: {
    // ignored: /node_modules/,
    aggregateTimeout: 300, // After seeing an edit, wait .3 seconds to recompile
    poll: 500 // Check for edits every 5 seconds
  },
  plugins: [
    new FriendlyErrorsWebpackPlugin(),
    new webpack.ProgressPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(process.cwd(), "public", "index.html")
    })
  ]
}
  • friendly-errors-webpack-plugin outputs more helpful Webpack errors
  • html-webpack-plugin creates an HTML5 file and injects <script></script>tags with our Webpack bundles. Recall in our config we created a bundle called main, which is resolved to ./src/main.js(this is the Webpack bundle we're injecting). And, because we're adding a template property, it means that html-webpack-plugin will use our HTML file, then inject the script tags
  • the new webpack.ProgressPlugin(), inside plugins: [] gives Webpack's progress building your files (in the terminal)
  • I chose cheap-module-eval-source-map for the property devtool because it provides fast compilation with source maps. Read more in the documentation
  • watchOptions prevents Webpack from recompiling everything too much (and lagging your replit). See the inline comments and documentation for more info

Now, let's create our src/main.js and public/index.html that we referenced in the Webpack config!

Creating our entrypoints

For the index.html, I've included all the standard HTML boilerplate with the addition of a div with an id of app.

<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Simple Webpack Boilerplate</title>
</head>

<body>
	<div id="app"></div>
</body>

</html>

For the main.js I do some simple DOM manipulation and logging. This is where your application really starts.

// src/main.js
console.log("Juliett Kilo Lima");

document.getElementById("app").innerHTML = "Mike November Oscar";

Creating the Webpack Development Server

Now, this won't do anything if we don't create the Webpack development server or use our Webpack configuration. So let's do that.

First, we must create a configuration object for our webpack-dev-server. It's exactly the same as the devServer property on a typical webpack.config.js. I used the documentation to make a simple configuration.

let webpackDevServerOptions = {
  publicPath: "/",
  contentBase: path.join(process.cwd(), "dist"),
  historyApiFallback: true,
  hot: true,
  host: "0.0.0.0",
  allowedHosts: [
    ".repl.it",
    ".repl.co",
    ".repl.run"
  ]
};

Some things worth mentioning

  • historyApiFallback: true makes webpack-dev-server return your index.html where there would typically be a 404 error. (ex. if you try to access /other/route) It's very useful when creating a Single Page Application (SPA)
  • hot: true causes the website to automatically update right after you save your files
  • host: "0.0.0.0" makes the Webpack development server accessable locally, outside localhost
  • allowedHosts is a whitelist of sites that can access the dev server. A prepended . means all the subdomains of that particular domain are whitelisted

Second, we're going to use our Webpack configuration to create the dev server. I couldn't find any solid documentation on this, but you can find more example code related to this here.

webpackDevServer.addDevServerEntrypoints(webpackConfig, webpackDevServerOptions);
let webpackCompiler = webpack(webpackConfig);

let app = new webpackDevServer(webpackCompiler, webpackDevServerOptions);

Then, make the server listen on a port

let port = process.env.PORT || 3000;
app.listen(port, () => console.log(`App listening on ${port}`));

So, our final index.js should look like the following

let path = require("path");
let webpack = require("webpack");
let webpackDevServer = require("webpack-dev-server");
let webpackConfig = require("./webpack.config");

let webpackDevServerOptions = {
  publicPath: "/",
  contentBase: path.join(process.cwd(), "dist"),
  historyApiFallback: true,
  hot: true,
  host: "0.0.0.0",
  allowedHosts: [
    ".repl.it",
    ".repl.co",
    ".repl.run"
  ]
};

webpackDevServer.addDevServerEntrypoints(webpackConfig, webpackDevServerOptions);
let webpackCompiler = webpack(webpackConfig);

let app = new webpackDevServer(webpackCompiler, webpackDevServerOptions);

let port = process.env.PORT || 3000;
app.listen(port, () => console.log(`App listening on ${port}`));

And huzzah! After running, we get "Mike November Oscar" on the web page.

This is where the tutorial ends but where your Webpack application starts! Now you can use whatever plugins and loaders you need to create your applications!