Getting started with Webpack: TypeScript

If you're starting a new web project these days, someone on your team is probably pushing for Webpack and TypeScript. Let's kick off with a little what's what.

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.

Webpack is an open-source JavaScript module bundler.

Did you know that TypeScript can prevent about 15% of the bugs that end up in committed code? source

For this guide we'll be using Node v8.5, NPM v5.3, TypeScript v2.5, and Webpack v3.5. The following commands will tell you which versions you have installed. If they are not exact they may still work. TypeScript and Webpack will be installed a little further on.

$ node --version
v8.5.0

$ npm --version
5.3.0

Once you have the basic dependancies all setup let's get the app directory going. Create a directory pickle (because Instagram for pickles is going to be all the new rage). You'll also want to make the basic HTML, TS, and JS files.

mkdir pickle
cd pickle
touch index.html
touch index.ts
touch webpack.config.js

From within the pickle directory create an initial package.json file with:

$ npm init --force
Wrote to /Users/abraham/dev/pickle/package.json:
...

--force will use the defaults for the sake of brevity. You are welcome to flush out the details at a later time.

Next install TypeScript and Webpack as development dependancies. (http-server is included for easy development)

$ npm install --save-dev typescript ts-loader webpack http-server
+ typescript@2.5.2
+ ts-loader@2.3.7
+ webpack@3.6.0
+ http-server@0.10.0
added 394 packages in 17.115s

Time to get a basic tsconfig.json implemented. This will use the locally installed version of TypeScript. If you globally installed it you can use tsc --init instead.

$ ./node_modules/typescript/bin/tsc --init
message TS6071: Successfully created a tsconfig.json file.

There are a lot of options in tsconfig.json that can be configured but we're going to leave the defaults for now.

Let's config Webpack to glue everything together. In webpack.config.js, save the following.

const path = require('path');

module.exports = {
  entry: './index.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')
  }
};

The last bit of config will setting up a convenient build and serve commands with NPM. Change the package.json scripts to look like this:

{
  ...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "serve": "http-server"
  },
  ...
}

You can now be able to run the new build command and see output like this.

$ npm run build

> pickle@1.0.0 build /Users/abraham/dev/pickle
> webpack

ts-loader: Using typescript@2.5.2 and /Users/abraham/dev/pickle/tsconfig.json
Hash: 8b5d98f242aeda6844bb
Version: webpack 3.6.0
Time: 815ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.51 kB       0  [emitted]  main
   [0] ./index.ts 14 bytes {0} [built]

CODE! We need some! Fill out index.html and index.ts with the following:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Pickle</title>
</head>
<body>
  <h1>Welcome to Pickle</h1>

  <label for="color-picker">Select a new background color</label>
  <input id="color-picker" type="color" value="#2196F3">

  <script defer src="dist/bundle.js"></script>
</body>
</html>
class Pickle {
  constructor(private picker: Element, private background: HTMLElement) {
    picker.addEventListener('change', this.colorChange.bind(this), false);
    this.background = background;
  }

  colorChange(event: Event): void {
    // `<HTMLInputElement>` tells TypeScript what type `target` is so that it knows there is a `value` property available.
    let input = <HTMLInputElement>event.target;
    this.background.style.backgroundColor = input.value;
  }
}

let picker = document.querySelector('#color-picker');
// The if avoids TypeScript complaining that `picker` might be null.
if (picker) {
  new Pickle(picker, document.body);
}

Run the build command again and then start the development server.

$ npm run build
...
$ npm run serve
> http-server

Starting up http-server, serving ./
Available on:
  http://127.0.0.1:8080
  http://192.168.200.8:8080
Hit CTRL-C to stop the server

You can now go to http://127.0.0.1:8080 in a browser to view the end result. You should see something like this:

Sample output

Note that if you make changes to index.ts you will have to run npm run build again before it'll be available in the browser. Next time we'll go over some improvements that'll make the development flow nicer. Check out TypeScript in 5 minutes for a quick intro to TypeScript.

The color <input> tag is not supported in all browsers so you may need to try a different one if something's not working.

You can view the source for the progress so far on GitHub and check out the next article Getting started with Webpack: Dev Server.

Posts in this series

  • Getting started with Webpack: TypeScript
  • Getting started with Webpack: Dev Server
  • Getting started with Webpack: Source Maps

  • Category: Development