How to Build TypeScript App and Deploy it on GitHub Pages

Quick Summary

In this post, I will show you how to easily build and deploy a simple TicksToDate time web app like this: https://zubialevich.github.io/ticks-to-datetime.

Requirements

  1. Text Editor (Visual Studio Code was used)
  2. Node.js (I've used v8.12.0 and higher)
  3. Yarn (I've used v1.9.4)
  4. TypeScript (2.9.2 and higher)

Introduction

TypeScript is a superset of JavaScript and adds optional static typing to the language. TypeScript is designed for development of large applications and transcompiles to JavaScript. In this tutorial, we will learn how easily build a simple web app with a TypeScript and deploy it on a GitHub Pages, free static website hosting.

So let's do this!

Ticks To DateTime

We will build an app that converts ticks to a date time string. A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond or 10 million ticks in a second. The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001, in the Gregorian calendar). Ticks is a good way to store DateTime data with a high level of precision in some data store.

Setup

Create a folder for your project, for example, "ticks-to-datetime". Inside this folder create another one called "src" where we will store all our .ts, .html and .css files.
Let's start with first file "index.html":
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Ticks to DateTime</title>
</head>

<body>
    <div id="container">
        <h1>[ Ticks to DateTime ]</h1>
        <form>
            <div class="input">
                <input type="text" placeholder="Ticks" id="ticks" size="17" autofocus="autofocus" />
            </div>
        </form>
        <div id="datetime" class="item"></div>
    </div>
    <script src="./index.ts"></script>
</body>

</html>
Here we specify on input field "ticks", where we will put the value of ticks. And an empty div "datetime" where we will output normal date string.

Now let's create a file with the logic for our app. Inside /src folder create file index.ts. Your /src folder now should look like this:

After the main window is loaded we should add some handlers that will listen to changes in "ticks" input. To do this add this in the index.ts file:
var possibleEvents = new Set(["input", "onpropertychange", "keyup", "change", "paste"]);

window.onload = () => {
    var ticksInput = document.getElementById("ticks") as HTMLInputElement;
    possibleEvents.forEach((eventName: string) => {
        ticksInput.addEventListener(eventName, (ev: Event) => {
            var inputElement = ev.target as HTMLInputElement;
            var handler = new TickInputHandler();
            handler.showResult(inputElement);
        })
    });
};
Here we specify the list of events for ticks input that we will listen: input, onpropertychhange, keyup, change, paste. Names are pretty informative. Inside the addEventListener, we get variable "ev" of type Event. Event is the base ts type for all HTML event which we then try to convert to the desired type of HTMLInputElement, which will store the value of our input.

Also inside the handler, we create an object of type TickInputHandler and call on it method showResult. This method will get the value from the input, convert it to DateTime string and show it in the "datetime" div.

Your file index.ts should look like this:
var possibleEvents = new Set(["input", "onpropertychange", "keyup", "change", "paste"]);

window.onload = () => {
    var ticksInput = document.getElementById("ticks") as HTMLInputElement;
    possibleEvents.forEach((eventName: string) => {
        ticksInput.addEventListener(eventName, (ev: Event) => {
            var inputElement = ev.target as HTMLInputElement;
            var handler = new TickInputHandler();
            handler.showResult(inputElement);
        })
    });
};

class TickInputHandler {
    // Ticks value for date 01-01-1970
    static epochTicks: number = 621355968000000000;
    static ticksPerMillisecond: number = 10000;
    // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1
    static maxDateMilliseconds: number = 8640000000000000;

    public showResult(inputElement: HTMLInputElement) {
        // Get value from the input and try to convert it to type Number
        var valueStr = inputElement.value;
        var ticks = Number(valueStr);

        var dateString = String();
        // If we were not able to parse input as a Number - show empty DateTimeString
        if (isNaN(ticks)) {
            dateString = "____-__-__T__:__:__.____Z";
        }

        // convert the ticks into something typescript understands
        var ticksSinceEpoch = ticks - TickInputHandler.epochTicks;
        var millisecondsSinceEpoch = ticksSinceEpoch / TickInputHandler.ticksPerMillisecond;
        // If the value of the input is more than max value - show special DateTime string for this case
        if (millisecondsSinceEpoch > TickInputHandler.maxDateMilliseconds) {
            dateString = "9999-99-99T99:99:99:9999Z";
        }

        // output the result in something the human understands
        var date = new Date(millisecondsSinceEpoch);
        return date.toISOString();
        var dateTimeOutput = document.getElementById("datetime");
        dateTimeOutput.innerHTML = dateString;
    }
}
Here inside showResult method we get the value from ticks input and convert it to DateTime string. Comments in the code should add some light on what's happening there.

Build and Deploy Setup

After we've built our app, we want now to run it on our local machine and then will be nice to deploy it somewhere on the internet. To do this we need to set up the required dependencies and for these add in the root directory of your project (not /src folder) two empty files: package.json and tsconfig.json.

File package.json will describe required dependencies and 3 useful scripts that we will use in future.
{
    "files": [
        "src/"
    ],
    "scripts": {
        "start": "parcel serve src/index.html",
        "build": "cross-env NODE_ENV=production parcel build src/index.html --public-url .",
        "deploy": "gh-pages -d dist"
    },
    "devDependencies": {
        "cross-env": "^5.2.0",
        "gh-pages": "^1.2.0",
        "parcel-bundler": "^1.9.7",
        "typescript": "^2.9.2"
    }
}
Here we add dependencies that our project will require. The most interesting packages are gh-pages and parcel-bundler.

Package gh-pages publish files to a "gh-pages" branch on GitHub. From this branch, GitHub will create a GitHub Page for you like https://{github-account-name}.github.io/{repo-name}.

Package parcel-bundler is a web application bundler that will help to build, deploy and run locally our app without any configs.

File tsconfig.json will look next way:
{
    "compilerOptions": {
        "module": "commonjs",
        "moduleResolution": "node",
        "newLine": "LF",
        "outDir": "./lib/",
        "target": "es5",
        "sourceMap": true,
        "declaration": true,
        "jsx": "preserve",
        "lib": [
            "es2017",
            "dom"
        ],
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        ".git",
        "node_modules"
    ]
}
After this changes your project folder will look like this:

Run Locally

Now open your favorite command line tool (cmd, bash, etc) and navigate to the folder with your project. Before the start, we should install all dependencies. Run next command:
$ yarn install
This can take some time as it will download and install all dependencies required to build and deploy our app.
After finish, run command:
$ yarn start

It will run a local web server on the URL http://localhost:1234. If you will open it in a browser you will see your running site. If everything was correct - congratulations! Now you have your site up and running.

To build your app run command:
$ yarn build
It will build your app and put resulted files in folder /dist. This files you can deploy on any web server or put it on GitHub Pages.

Deploy on GitHub Pages

Before deploying on GitHub Pages you should create a repository for your project and push your code there. You can read how to do this here. After you have your repository on GitHub, run next command from the command line tool:
$ yarn deploy
It will build your project and push resulted files in the gh-pages branch. After success, if open URL https://{github-account-name}.github.io/{repo-name}. In my case it was https://zubialevich.github.io/ticks-to-datetime.

Note that all yarn commands (exept yarn install) are calling scripts that we've added in the package.json file in section scripts.

Summary

Now you have learned how easily and fast create a small web app with TypeScript and put it on GitHub Pages. In this tutorial, I've skipped a part with styles and additional checks, so if you want to see how does the code for final project looks like, feel free to visit my GitHub repo.

Comments

Popular posts from this blog

Caching strategies

Just another way of fixing bugs