Felix Astner
JavaScript, Magento and other Software
Felix Astner

Create a React Application with Webpack

This short article gives an introduction, how you can build a react application with the use of webpack, the transpiler babel and the the typesystem flow. You will see, how to configure webpack, run development and production builds and how you develope with flowjs.

Initialize Webpack

This application is - as expected a javascript application - so we need to create our npm package definitions and requirements. What we need is the following:

  • webpack (you guessed it) and the webpack-server package to easily develop applications without constantly rebuilding manually
  • flow - I prefer installing it in the used packages instead of installing it globally. So everytime I switch the development machine, I just need to hit npm install and do not have to search for any global dependecies
  • babel - off course; we need to strip flow types and transpile jsx to standard ES5 code
{
 "name": "felixastner-react-application",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
 "start": "webpack-dev-server",
 "flow": "flow"
  },
 "keywords": [],
 "author": "Felix Astner",
 "license": "MIT",
 "dependencies": {
 "react": "^16.4.1",
 "react-dom": "^16.4.1"
  },
 "devDependencies": {
 "babel-cli": "^6.26.0",
 "babel-core": "^6.26.3",
 "babel-loader": "^7.1.5",
 "babel-plugin-transform-async-to-generator": "^6.24.1",
 "babel-plugin-transform-class-properties": "^6.24.1",
 "babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
 "babel-plugin-transform-runtime": "^6.23.0",
 "babel-preset-env": "^1.7.0",
 "babel-preset-flow": "^6.23.0",
 "babel-preset-react": "^6.24.1",
 "babel-register": "^6.26.0",
 "file-loader": "^1.1.11",
 "flow-bin": "^0.92.1",
 "html-webpack-plugin": "^3.2.0",
 "webpack": "^4.16.1",
 "webpack-cli": "^3.0.8",
 "webpack-dev-middleware": "^3.1.3",
 "webpack-dev-server": "^3.1.4"
  }
}


After this, you can initialize flow by running the following command. Flow will generate an empty configuration:

npm run flow init

Now let's get into the webpack configuration:

// webpack.config.js


const process = require('process');
const path = require('path');
const {resolve} = path;




const HtmlWebpackPlugin = require('html-webpack-plugin');


module.exports = {
 'mode': (process.env.NODE_ENV === 'production' ? 'production' : 'development'),
 'entry': './src/index.js',
 'output': {
    'path': __dirname + '/static',
    'filename': '[name].[chunkhash:8].js',
        publicPath: '/'
     },
     devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 3000 
     },
 'devtool': 'source-map',
 'module': {
    'rules': [
        {
            'test': /\.(js|jsx)$/,
            'exclude': /node_modules/,
            'use': {
                    loader: 'babel-loader',
                    options: {}
             }
         },
     ]
  },
  'plugins': [
        new HtmlWebpackPlugin({
            title: 'Development'
        })
    ]
};

Last but not least, we create the webpack configuration. There are a few options, which I need to explain here:

  • mode: This handles the internal mode of webpack. It allows minifying and other production optimizations.
  • entry: This is the file, webpack starts its process with. You can even configure an array of entry files.
  • output: Defines the path, where webpack puts its bundles. If you have multiple entry points, the filename pattern describes the output filenames, where as name is the entry key. devServer applies some configuration for development, like the port, the application is running on.
  • devtool allows us to define which type of source map we want to use, and if we even want to use one
  • module.rules: This array lists a set of loaders. More on that later.
  • plugins: Fulfill a lot of different tasks. They can further optimize the resulting bundle, handle assets or - as in this case - create a new html file.

Webpack Loaders

As you see above, we use a loader called babel-loader. Babel is a Javascript transpiler, which transpiles new Javascript (ES6/7/8) and custom Javascript language extensions like JSX into standardized Javascript, even the Internet Explorer is able to understand, but can be configurated otherwise, off course.

To be able to execute this loader, babel requires some configuration (.babelrc):

{
 "retainLines": true,
 "presets": [
       "env",
       "react",
       "flow"
 ],
 "plugins": [
       "transform-es2015-arrow-functions",      
       "transform-runtime",
       "transform-async-to-generator",
       "transform-class-properties"
  ]
} 

The presets handle JSX and strip flow types. The plugins allow us to write a more understandable, beautiful code. That's all about it. We can now focus on the application code.

Writing the Application

This article is just an introduction, so we just create one react component:

// src/components/Application/Application.js
// @flow
import React, {Component} from 'react';


/**
 * Application has just one property: A title of type string
 */
export type ApplicationProps = {
    title: string
}


/**
 * Define the component Application.
 */
export default class Application extends React.Component<ApplicationProps> {
 render() {
    // use typesave props
    const {title} = this.props;


    return <div>
        Application: <b>{title}</b>
    </div>;
  }
}

The usage of the application component is as easy as follows.

// src/index.js
// @flow


import React from 'react';
import { render } from 'react-dom';
import Application from './components/Application/Application'


const root = document.createElement('div');
document.body.appendChild(root);


// use the Application component with its typesafe properties. 
render( <Application title="Example Application" /> ,
        root,
);



profile

Felix Astner

As a software developer, I bring a specialized focus in web technologies, enriched by my interests in C++, AI, and computer theory. If you're in need of any freelance services, expert training, or insightful consulting, I encourage you to connect with me.

HomePrivacyImpressum