The feeling, when you react, script and pack.
At the time of writing this article, the popularity of React has already shot off the roof, that of Typescript is on the rise and it is safe to say that Webpack is the most preferred modern module bundler for an application. However, there is still an underlying dearth of a good example of the best possible way to start a project in React with Typescript and Webpack. Having said that, there are good resources out there if you want to use create-react-app cli or any other react starter kit out there. But there are very few ones if you want to have control over the configurations of your application.
The downside of using a cli like create-react-app are that you have to rely on the following tools the same way create-react-app relies on
If you strongly dislike any one of the above, you are going to have a hard time accepting it. create-react-app lives upto its promise of ‘no build configuration’ because you simply cannot configure this tool. It provides a way of ejecting the tooling where you can let go of create-react-app if you want to extend the configuration further but why should I? Wouldn’t it be much more easier if I would have handled the configuration from the beginning in the first place? Moreover, once you eject, there is going to be an increase in the dependencies of your project, half of which you might not even need. Having said all that, it is probably the best react toolkit out there to get your project started if you are looking for one as a beginner or for a small to medium level project.
You may find this article helpful if you want to set up a project with the following things:
Before we begin, make an empty folder somewhere in your drive to begin afresh. If you are using a windows machine, go to your command line terminal and type the following three commands.
mkdir react-ts-webpackcd react-ts-webpackcode .
the last command will open the recently created empty folder as a project in Visual Studio Code, a fairly popular editor and you are most likely to have it. Feel free to open it in your favorite editor if you do not have it.
So, as per popular tradition when you create a new project, initialize the npm in our project by typing the following line in the terminal.
npm init -y
Now we are going to create a few files and folders that are required to set up the project. So, on the root of your folder create the following files/folders.
So the folder structure of the application looks something like this
|-src|-app|-components|-Hello.tsx|-App.tsx|-index.html|-package.json|-package-lock.json|-server.js|-tsconfig.json|-webpack.config.js
Now we are going to download our production and development dependencies.
npm i react react-dom express typescript --save
npm i @types/react @types/react-dom webpack webpack-cli ts-loader webpack-dev-middleware webpack-hot-middleware html-webpack-plugin source-map-loader -D
Congratulations! we are almost halfway there without writing a single piece of code.
So, here are the contents of the files you just created. You can paste them onto your relative project from here (gist link is embedded in the title of the file) or type along.
Let us write a typical react component, after all this is the code that you will and should be concentrating on after you have completed the set up.
So, either you can write along or paste the code as you like.
Hello.tsx:
import * as React from 'react';
interface IProps {compiler: string,framework: string,bundler: string}
export class Hello extends React.Component<IProps, {}> {render() {
return <h1>This is a {this.props.framework} application using {this.props.compiler} with {this.props.bundler}</h1>}}
App.tsx:
import * as React from 'react';import * as ReactDOM from 'react-dom';import { Hello } from './components/Hello';
ReactDOM.render(<Hello compiler="Typescript" framework="React" bundler="Webpack" />,
document.getElementById('root'));
In case you are not familiar with webpack, a brief about the options is provided below. Feel free to skip it in case you are already aware of this stuff.
import { Hello } from './components/Hello';
You can now actually manually build your application. We will get to building automatically before running our server later. but for now if you want to take a look at your efforts until now, just add a ‘build’ script to your package.json file and execute the webpack command.
package.json:
...scripts: {..."build": "./node_modules/.bin/webpack",...}...
If you go to the terminal and run this command, you can look at your bundled application in the dist folder.
Run this in your terminal:
npm run build
Output in the terminal:
npm run build
bundled code
If you do not want to use express to run a server for you react application to be served, you can use webpack-dev-server which takes care of it and you do not have to write a server yourself but if you want to have the flexibility of a custom server for you to write middlewares, handle routes and modify requests and responses then it is recommended that you write your own server. At the time of writing this article, webpack-dev-server has no new features planned and is in maintenance only mode.
https://www.npmjs.com/package/webpack-dev-server
server.js:
const path = require('path'),express = require('express'),webpack = require('webpack'),webpackConfig = require('./webpack.config.js'),app = express(),port = process.env.PORT || 3000;
app.listen(port, () => { console.log(`App is listening on port ${port}`) });
app.get('/', (req, res) => {res.sendFile(path.resolve(__dirname, 'dist', 'index.html'));});
let compiler = webpack(webpackConfig);app.use(require('webpack-dev-middleware')(compiler, {noInfo: true, publicPath: webpackConfig.output.publicPath, stats: { colors: true }}));app.use(require('webpack-hot-middleware')(compiler));app.use(express.static(path.resolve(__dirname, 'dist')));
Now you can go to your package.json and add the start script
"start": "npm run build && node server.js"
Once you run the server by running ‘npm start’ in the terminal, the webpack-dev-middleware and webpack-hot-middleware should take care of hot module replacement but that is not the case.
You may notice that after you make a change, webpack duly compiles and emits the changed code but it only takes effect when you refresh your browser. That is not what we signed up for. The browser should have refreshed after re-building the changed component.
HMR in action
In order to fix this, we need to change our ‘App.tsx’ a bit
import * as React from 'react';import * as ReactDOM from 'react-dom';import { Hello } from './components/Hello';declare let module: any
ReactDOM.render(<Hello compiler="Typescript" framework="React..." bundler="Webpack" />,document.getElementById('root'));
if (module.hot) {module.hot.accept();}
So basically we are saying our app to accept the hot reloaded changes made by webpack. The declaration part is needed because ‘hot’ property is not present by default on the ‘module’ object and we need to ask typescript to allow it.
Once you restart your server after this change, it works as expected.
HMR Fixed
In case you want to view the complete boiler plate create. You can clone/download from this repository
saurabhpati/react-ts-webpack-boilerplate_react-ts-webpack-boilerplate - This is the ultimate lightweight boilerplate needed for a React application using…_github.com
I will try to add code splitting to further increase the efficiency of the build process and will be happy to receive any feedback regarding this post.