Webpack has become one of the most important tools for modern web development and yet, it is a blackbox to many developers. In this tutorial, we are going to setup our own basic Webpack 4 configuration from scratch for React with Typescript.

If you just want to try something or build a simple side project, you should use the create-react-app with Typescript. There is no configuration needed, you can focus on coding.

Webpack’s core concepts

At its core, Webpack is a static module bundler for modern JavaScript applications. When Webpack processes your application, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles.

— Webpack’s documentation

To get started with Webpack, we only need to understand the following core concepts:

Entry

Output

Loaders

Plugins

The entry is which file, or module, should Webpack use to start resolving the dependencies. The default value in Webpack 4 is ./src/index.js .

The output property tells Webpack how to name the bundle files and where it should output them. The default value in Webpack 4 is the ./dist folder.

The loaders allow Webpack to process different types of imported files other than Javascript. Without loaders, Webpack only knows how to process Javascript files. Loaders allow you to create rules in your configuration file telling webpack to use a specific loader when it encounters a specific type of file.

Plugins allow you to extend Webpack’s capabilities like: bundle optimization, assets management, etc. There are many plugins that Webpack provides out-of-box.

Now that you know the basics, let’s install and configure Webpack.

Installing Webpack

First, let’s create a new project folder and initialize it:

mkdir react-typescript-webpack-tutorial cd react-typescript-webpack-tutorial npm init –y

Let’s now install Webpack and the Webpack CLI as dev-dependencies:

yarn add webpack webpack-cli --dev npm i webpack webpack-cli --save-dev

Webpack 4 has two modes: development and production . The bundle will be minimized on production mode only.

Let’s add two npm scripts to our package.json to run Webpack:

"scripts" : { "start" : "webpack --mode development" , "build" : "webpack --mode production" }

If we create an index.js file inside an src folder (default entry point in Webpack 4), we can run Webpack without any configuration.

Let’s create the src/index.js file with dummy code:

console . log ( 'hello' )

And then run npm start to generate our Javascript bundle file named main.js inside the dist folder.

Configuring Webpack

Let’s configure Webpack to better fit our needs.

First, we need to create Webpack’s configuration file named webpack.config.js in the root of our project. The basic configuration looks like this:

const path = require ( "path" ) module . exports = { entry : "./src/index.js" , output : { path : path . join ( __dirname , "/dist" ) , filename : "index_bundle.js" } }

We specified src/index.js as the entry point

as the entry point We told Webpack to output the bundle into the dist folder with the name index_bundle.js

Next, let’s add Typescript.

Adding Typescript

First, we need to install the dependencies:

yarn add typescript awesome-typescript-loader --dev npm i --save-dev typescript awesome-typescript-loader

awesome-typescript-loader will help Webpack compile our Typescript code and generate sourcemaps.

Adding a Typescript configuration file

Now we need to create a tsconfig.json file at the root of our project, which will contain all the compilation settings:

{ "compilerOptions" : { "outDir" : "./dist/" , "sourceMap" : true , "noImplicitAny" : true , "module" : "commonjs" , "target" : "es5" , "jsx" : "react" } , "include" : [ "./src/**/*" ] }

You can learn more about the tsconfig.json file here.

Configuring Webpack for Typescript

We need to tell Webpack to use our awesome-typescript-loader for Typescript files. Let’s update our webpack.config.js file, explanations are in comments:

const path = require ( "path" ) module . exports = { entry : "./src/index.tsx" , devtool : "source-map" , resolve : { extensions : [ ".ts" , ".tsx" , ".js" , ".json" ] } , output : { path : path . join ( __dirname , "/dist" ) , filename : "index_bundle.js" } , module : { rules : [ { test : /\.tsx?$/ , loader : "awesome-typescript-loader" } ] } }

Testing the configuration

To test our configuration, we first need to change the extension of our index.js file to index.tsx and then add simple Typescript code inside it:

type Message = { body : string , from : string } let message : Message = { from : 'Max' , body : 'Hi!' } console . log ( `New message from ${ message . from } : ${ message . body } ` )

If we run npm start , you will see in the dist folder that Webpack transformed our Typescript code and also generated a sourcemap file.

Adding React

Let’s now add React and ReactDOM, along with their declaration files, as dependencies:

yarn add react react-dom @types/react @types/react-dom npm i react react-dom @types/react @types/react-dom

And create a simple Message.tsx React component in the src/components folder:

import * as React from 'react' class Message extends React . Component < MessageProps > { render ( ) { return ( < div > { `You got a new message from ${ this . props . from } : ${ this . props . body } ` } </ div > ) } } interface MessageProps { body : string from : string } export default Message

And modify the index.tsx file to import React and ReactDOM and make it render our new Message component:

import * as React from "react" ; import * as ReactDOM from "react-dom" ; import Message from "./components/Message" ; ReactDOM . render ( < Message from = ' Max ' body = ' Hi ! ' /> , document . getElementById ( "root" ) ) ;

Now if we run npm start , Webpack should be able to tranform and bundle our React code!

Adding HTML

I voluntarily didn’t create an HTML file yet, because we are going to use a Webpack plugin called html-webpack-plugin for that. This plugin will generate an HTML file using a template that we are going to give him, and automatically include our Webpack bundles inside the body:

yarn add html-webpack-plugin --dev npm i --save-dev html-webpack-plugin

After having installed the plugin, we need to add it to our Webpack config’s plugins section:

const path = require ( "path" ) const HtmlWebpackPlugin = require ( "html-webpack-plugin" ) module . exports = { entry : "./src/index.tsx" , devtool : "source-map" , resolve : { extensions : [ ".ts" , ".tsx" , ".js" , ".json" ] } , output : { path : path . join ( __dirname , "/dist" ) , filename : "index_bundle.js" } , module : { rules : [ { test : /\.tsx?$/ , loader : "awesome-typescript-loader" } ] } , plugins : [ new HtmlWebpackPlugin ( { template : "./src/index.html" } ) ] }

Now let’s create a simple index.html template in the src folder:

<!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 > TypeScript + React </ title > </ head > < body > < div id = " root " > </ div > </ body > </ html >

Running npm start will now generate our Javascript bundle and an HTML file with our bundle already included with a script tag inside the body.

Setting up a development server

Finally, we are going to setup a development server that will provide us live reloading using the webpack-dev-server module.

First, we need to install the module:

yarn add webpack-dev-server --dev npm i webpack-dev-server --save-dev

And then change the start script in our package.json file to:

"scripts" : { "start" : "webpack-dev-server --mode development --open --hot" , "build" : "webpack --mode production" }

We are telling Webpack DevServer to run on development mode while watching for changes.

The --hot option enables Webpack’s Hot Module Replacement .

option enables Webpack’s . The --open option will open our default browser when we run npm start .

For more options, check out the DevServer section in the Webpack documentation

Conclusion

We can now run npm start to start a development server with hot reloading and npm build to have a minimized bundle for production.

This is only a basic configuration of Webpack for a React project in Typescript. This article is already long so I didn’t add other features, but you should definitely push it further by adding other loaders, plugins and optimizing the configuration.

If you have any question or suggestion, please leave a comment below.