Up: Integrate front-end framework   [Contents]

28.1 React + Typescript

It is strongly recommended to use Typescript to replace Javascript. And Typescript transpiler is licensed with Apache-2.0 which is compatible with GPL. Although Typescript was dismissed because of the size and little slower performance, the rubustness should be more important in the development.

Here is an example for Hello World.

We assume that you’re already using Node.js with npm.

For example, you have an Artanis application:

art create my-test
cd my-test

However, the node_modules directory can’t be put in the toplevel position. You have to initialize your NPM in pub directory:

# In my-test directory
cd pub
npm init

You’ll be given a series of prompts, but you can feel free to use the defaults. You can always go back and change these in the package.json file that’s been generated for you. If you want to skip those prompts, just type:

# In *pub* directory
npm init -y

Let’s now add React and React-DOM, along with their declaration files, as dependencies to your package.json file:

# In *pub* directory
npm install --save react react-dom @types/react @types/react-dom

Next, we’ll install Webpack and the Webpack CLI as dev-dependencies, add development-time dependencies on awesome-typescript-loader and source-map-loader.

npm install --save-dev webpack webpack-cli typescript awesome-typescript-loader source-map-loader

Create and edit tsconfig.json file under pub directory:

{
    "compilerOptions": {
        "outDir": "./pub/dist/",
        "sourceMap": true,
        "noImplicitAny": true,
        "module": "commonjs",
        "target": "es6",
        "jsx": "react"
    },
    "include": [
        "./pub/js/ts/**/*"
    ],
    "exclude": ["node_modules"]
}

Create and edit webpack.config.js file under pub directory:

module.exports = {
    mode: 'production',
    watch: true,
    entry: "./js/ts/index.tsx",
    output: {
        filename: "bundle.js",
        path: __dirname + "/dist"
    },

    // Enable sourcemaps for debugging webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: [".ts", ".tsx", ".js", ".json"]
    },

    module: {
        rules: [
            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
            { test: /\.tsx?$/, loader: "awesome-typescript-loader" },

            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
        ]
    },

    // When importing a module whose path matches one of the following, just
    // assume a corresponding global variable exists and use that instead.
    // This is important because it allows us to avoid bundling all of our
    // dependencies, which allows browsers to cache those libraries between builds.
    externals: {
        "react": "React",
        "react-dom": "ReactDOM"
    }
};

Create index.html under pub directory:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
  </head>
  <body>
    <div id="example"></div>

    <!-- Dependencies -->
    <script src="./node_modules/react/umd/react.development.js"></script>
    <script src="./node_modules/react-dom/umd/react-dom.development.js"></script>

    <!-- Main -->
    <script src="./dist/bundle.js"></script>
  </body>
</html>

Create js/ts/index.tsx under pub directory:

import * as React from "react";
import * as ReactDOM from "react-dom";

import { Hello } from "./components/Hello";

ReactDOM.render(
        <Hello compiler="TypeScript" framework="React" />,
    document.getElementById("example")
);

Create js/ts/components/Hello.tsx under pub directory:

import * as React from "react";

export interface HelloProps {
    compiler: string;
    framework: string;
}

export const Hello = (props: HelloProps) =>
    <h1>Hello from {props.compiler} and {props.framework}!</h1>;

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"
  },

Now, everything is ready, we run webpack to compile Typescript code and pack necessary resources:

# Must be under "pub" directory
npm run build

So webpack is watching your code, anytime you change the code, webpack will automatically update it.

Then, under project folders, open a new terminal, and type:

art work

OK, now open http://localhost:3000/index.html to see your work.

It’s just a Hello World. Feel free to modify it for your cases.