Skip to content

Setting up the Webpack Dev Server

Video Lecture

Setting up the Webpack Dev Server

Description

We will use the Webpack Development Server to run our Threejs code.

The Webpack Development Server has several features that make development an easier process. Such as Hot Module Reloading (HMR) which will auto refresh our browser when we make changes to our code,

and bundling all of our code dependencies into a single JavaScript file that will be loaded into the HTML.

We need to install several modules so that we can use Webpack effectively.

npm install webpack webpack-cli webpack-dev-server ts-loader --save-dev
  • webpack : Contains the core that will bundle our code into development and production versions.
  • webpack-cli : the command line tools that we use to run webpack.
  • webpack-dev-server : A HTML server that will load our code and provide the HMR functionality during the development phase.
  • webpack-merge : Now auto installed with latest webpack. webpack-merge is a library that allows splitting webpack configurations into several files.
  • ts-loader : A module rule for processing TypeScript files.

We will also need a local copy of TypeScript in the node_modules folder for use by the ts-loader

npm install typescript --save-dev

Now to add some Webpack configurations to our client.

./src/client/webpack.common.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
const path = require('path')

module.exports = {
  entry: './src/client/client.ts',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, '../../dist/client'),
  },
}

./src/client/webpack.dev.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
const path = require('path')

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-source-map',
  devServer: {
    static: {
      directory: path.join(__dirname, '../../dist/client'),
    },
    hot: true,
  },
})

We will add a webpack production configuration later on in the course.

./package.json

Now to add a script for starting the webpack dev server into package.json

Under the scripts node, add a new command for dev, see the highlighted line.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "name": "three.js-typescript-tutorial",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "dev": "webpack serve --config ./src/client/webpack.dev.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "@types/three": "^0.158.2",
    "three": "^0.158.0",
    "ts-loader": "^9.5.0",
    "typescript": "^5.2.2",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1"
  }
}

Now we can run our project and see a Threejs example running in the browser.

npm run dev

First Threejs examples

Troubleshooting

EADDRINUSE

If when starting, you see the error

...
events.js:174
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE: address already in use :::8080
... etc, and many more lines

This error means that port 8080 is already in use somewhere.

You probably have another project started on your PC somewhere using port 8080. Close that project and then try restarting again.

Unknown Property 'contentBase'

If when starting, you see the error

[webpack-cli] Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.

- options has an unknown property 'contentBase'. etc ...

When upgrading from Webpack 3 to Wepback 4, the devServer configuration now uses a static property indicating served directories in replace of the now deprecated contentBase property.

I.e., now use

...
    devServer: {
        static: {
            directory: path.join(__dirname, '../../dist/client'),
        },
...

instead of

...
    devServer: {
        contentBase: './dist/client',
...

Comments