All Posts

Let's Build: HTML5 Development Server & Build Tool With Webpack - Initial Setup with Web Server

Welcome everyone to the first part of this tutorial series. Today, our main objective is to be able to create the web server that will show us the webpages that we are working on and create our first page.

Requirements

Before we start getting into development, here is a list of requirements for you to check before we proceed:

  1. Development environment

    1. NodeJS - At least version 12 lts.
    2. NPM - At least version 6.4
    3. Text Editor - Any text editor of your choosing. I use VSCode.
    4. Bash terminal
  2. A basic understanding of what Webpack is.

Note: I recommend using NVM(Node version manager) for installing NodeJS on your computer.

Project directory creation and initial setup

Now that we have everything we need to get started, let us get started.

  1. Open the terminal of your choosing, create the the project directory and get inside your project directory.
mkdir your_project_dir
cd your_project_dir
  1. Using your terminal, create package.json.
npm init -y

Creating the Webpack configuration file

Now, we need to create the Webpack configuration file which will contain the settings that will help us achieve our main goal today.

  1. Using your terminal, install Webpack.
npm install --save-dev webpack 
  1. Create the Webpack configuration file. You can do this either using your text editor, or, using the terminal.
touch webpack.config.js

Initial Webpack configuration and entry point

With webpack.config.js in place, let us now create the code that will be the foundation of our development tool.

  1. Using your text editor, open webpack.config.js and add the following lines in your webpack.config.js.
module.exports = {
  mode: 'development'
}
  1. Inside the object assigned to module.exports, let us start by adding the entry point of our Webpack configuration.
module.exports = {
  mode: 'development',
  entry: {
    index: './src/pages/index/index.js'
  }
}

This entry object is Webpack’s way of determining the entry points in the form of key-value pairs. In this example, our first entry point is index which points to ./src/pages/index/index.js. This will be the entry point for our homepage dependencies in the future. For now we will leave this and we will get back to this when we start declaring the dependencies of our homepage.

  1. Since we declared in our index entry point, let’s create the index.js file. You may use your text editor to create the directory structure ./src/pages/index. For this example I will be using the terminal to accomplish that.
mkdir -p ./src/pages/index
touch ./src/pages/index/index.js

For now we’ll be leaving ./src/pages/index/index.js blank. We will be getting back to this file in the future.

Webpack loaders and adding latest Javascript syntax support

After creating the entry point for our Webpack configuration, the next thing that we are going to do now is to add loaders. Loaders is Webpack’s way of processing various types of files that we declare inside our entry point, including the file that we define as our entry point which is index.js.

For now, the first loader that we’re going to add is the Babel Loader. This loader allows us to be able to use latest Javascript (ES2015+).

  1. Open your terminal and install npm packages to add Babel Loader.
npm install babel-loader @babel/core @babel/preset-env --save-dev
  1. Let’s add the code to add Babel Loader in our Webpack configuration.
module.exports = {
  //...after the last line of the `entry` object
  module: {
    rules: [
      {
        test: /\.m?js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },
}

In the future parts of this series, I will be showing to you how babel loader enables us to use modern Javascript syntax on the projects that will be using this development and build tool that we are building.

Source Map

Since we are using loaders like Babel Loader to process our Javascript, when it churns out the compiled code in our development server, it is usually drastically different from our source code. Given that, adding source map support to our webpack configuration helps us, specially when there’s an error, by pointing out the source file that corresponds to the compiled code that was executed.

We can do this by adding the following line of code:

module.exports = {
  //...after the last line of the `module` object
  devtool: 'inline-source-map',
}

Plugins and adding HTML support

Because one our goals today is to be able to view a webpage through our development server, we now need to add an HTML support to make this happen.

For this section, we are going to use Webpack plugins. I learned that for our servers to serve HTML files(which will contain the output that’s a result of our entry points), we will be needing a Webpack plugin called HTMLWebpackPlugin. To add HTMLWebpackPlugin into our Webpack configuration, we must do the following:

  1. Open your terminal and install npm packages to add Babel Loader.
npm install html-webpack-plugin --save-dev
  1. Let’s add the code to add Babel Loader in our Webpack configuration.
//Add this code on the top most part of webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  //...after the `inline-source-map`
  plugins: [
    new HtmlWebpackPlugin({
      //'index' refers to the index entry point
      // later on, the output bundle of 'index' entry point will be declared
      // as a dependency when index.html gets served in the browser
      chunks: ['index'], 
      inject: false,
      filename: 'index.html',
      template: 'src/pages/index/index.html',
    }),
  ],
}
  1. Using your text editor, add the index.html file inside ./src/pages/index. Using terminal, run the following command:
touch ./src/pages/index/index.html
  1. Open index.html and add the following HTML:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HTML5 Development Server & Build Tool With Webpack</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- This is where the CSS tags go from the output of the chunks defined in "new HTMLWebpackPlugin" -->
    <%= htmlWebpackPlugin.tags.headTags %>
  </head>
  <body class="home">
    Hello World! This is the home page!
    
    <!-- This is where the JS tags go from the output of the chunks defined in "new HTMLWebpackPlugin" -->
    <%= htmlWebpackPlugin.tags.bodyTags %>
  </body>
</html>

Webpack “Output”

Earlier, we have an “entry” point. Now we also need to have an exit/output. The output property in the webpack configuration simply tells webpack where to create the bundles that are a result of the dependencies defined in your entry point.

Our output as of the moment seems meaningless as our objective today is just to create the development server and serve our first webpage. But for us to complete today’s tutorial, let us add the following lines of code to give the output bundle of our entry point a file name, as well as the publicPath which will be used later.

module.exports = {
  //...after the last line of the `plugins` object
  output: {
    filename: '[name].bundle.js',
    publicPath: '/'
  },
}

Webpack development server

Now that we’re done with our webpack configuration. The approach that we will take for this development server that we are building will be with the help of NodeJS and Express. For us to setup the development server that will serve our web pages, do the following:

  1. Create server.js which will contain the code that will serve the webpack development server.
touch server.js
  1. Open your terminal and install packages required to build the development server.
npm install express webpack-dev-middleware --save-dev
  1. Add the following NodeJS code using Express that serves the output of our webpack configuration with webpackDevMiddleware
const express = require("express")
const webpack = require("webpack")
const webpackDevMiddleware = require("webpack-dev-middleware")
const app = express()
const config = require("./webpack.config.js")
const compiler = webpack(config)


app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

app.listen(3000, function() {
  console.log("Webpack dev server now listening on port 3000!\n")
})
  1. Lastly, inside the package.json file that was generated when we ran npm init -y, add an entry to the scripts configuration object.
  //...
  "scripts": {
    //Remove this
    "test": "echo \"Error: no test specified\" && exit 1",
    //Add this
    "start": "node server.js"
  },

Run the server

Now that we have completed the configuration, we can now run the development server. For us to do that, go to your terminal and run:

npm run start

You should be seeing a message in your terminal saying Webpack dev server now listening on port 3000!.

Viewing the webpage

Now that the web server is running, open up your browser and go to http://localhost:3000/. You should be seeing something similar to the screenshot below:

Output Image

Just to satisfy the curiousity for you who wonders about what happens upon creating the output configuration we had earlier, here is a screenshot showing where index.bundle.js goes to:

Output Image

Conclusion

That wraps up our part 1 of this series. We now have a working web server that serves our first web page. What’s next for us to continue building on top of today’s output and in no time, we’ll be having a complete development server. For the complete source code of this tutorial, please visit this github link.

Next week, I will be sharing to you how to add CSS support to our development server by implementing implementing CSS, PostCSS and TailwindCSS support.

Have a great weekend everyone!


Hi! If you have any questions, suggestions, corrections, or constructive feedback about this post, please let me know. I will greatly appreciate it!💯