Creating PWA with Angular 5. Part 1: Getting started with framework, creating an application, hosting it on github-pages.

Nastya Smirnova
Nov 29, 2017 · 8 min read
Image for post
Image for post

I’ve been delaying my acquaintance with new Angular framework for too long time. As a big fan of AngularJS v1.x, I didn’t get the necessity of so radical changes came with new versions of it.

My eyes were opened during GDG DevFest Ukraine 2017. Tired and hungry by the end of the day 1, I’ve charged my final reserve force on the speech named “Web goes Native: Progressive Web Apps with Angular” by Shmuela Jacobs. And that was it! Inspiring, productive, fast and easy. I couldn’t believe that ‘progressifying’ of the web application can be just that simple.

A month later, when the new Angular 5 was announced and released, I decided to deal with it at all costs and create my first progressive web application. My experiment was successful, and now I am glad to share with you my steps and results.

Step 1. Getting started with Angular.io

npm install -g @angular/cli

❗️Check your cli version. 1.5.x is not working properly in some cases, so make sure you are using the 1.6 or higher. My current is 1.6.0-rc.0.

Time to generate a new project. Choose a nice, recognizable name for it. Following my instructions, you are going to create an app, that generates a new cute photo of a cat every time you visit it. Let it be PWCat (abbr. for Progressive Web Cat 😺 )

ng new PWCat

It can take a couple of minutes to set up a new project — nice chance to make a cup off coffee ☕️. Cheers!

Good news. We do not need any local web server for deployment. Just run in your terminal:

cd PWCat
ng serve --open

Last command will open a new tab in your browser (make sure that it’s Chrome!) on the http://localhost:4200/, serving your application with some default content. If everything is ok, you will see:

Image for post
Image for post

Open PWCat project in your favorite IDE. I’ve chosen the Visual Studio Code, ‘cause it supports the Typescripts without any additional installable packages. Take some time enjoying how many code you have already written 😄. You can read about all that generated files here.

To change the visible name of our application, let’s go to the app.component.ts file and change it’s title property:

// src/app/app.component.ts...export class AppComponent {
title = 'Progressive Web Cat';
}

Step 2. Adding Angular Material framework

npm install --save @angular/material @angular/cdk

Choose one of pre-built themes for our app. Import it in styles.css file

/* src/styles.css */@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

Also we can add normalize.css module to prettify default html styling. In terminal:

npm install --save normalize.css

In styles.css:

/* src/styles.css */@import '~normalize.css/normalize.css';
@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

Now we can add material designed modules to our app. To begin with, let’s import the tool bar component. Open the app.module.ts file. You need to add only two lines of code:

// src/app/app.module.tsimport { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MatToolbarModule } from '@angular/material';import { AppComponent } from './app.component';@NgModule({
declarations: [ AppComponent ],
imports: [
BrowserModule,
MatToolbarModule
],
providers: [],
bootstrap: [ AppComponent ]
})
export class AppModule { }

❗️Don’t forget to include MatToolBarModule to ngModule decorator.

Now we can use toolbar in any place of our app. Go to the app.component.html, and remove all generated content with following lines:

<!-- src/app/app.component.html --><mat-toolbar color="primary">
{{ title }}
</mat-toolbar>

By setting the color of element to be ‘primary’ we make it use the main theme color. If everything was done correctly, our app will show us a pretty enough header:

Image for post
Image for post

Step 3. Our first Angular component

ng generate component img-card

As a result you can see that angular has generated a new folder for you with all necessary files. Also take a look at app.module.ts. New component has been imported automatically.

// src/app/app.module.ts...import { AppComponent } from './app.component';
import { ImgCardComponent } from './img-card/img-card.component';
@NgModule({
declarations: [
AppComponent,
ImgCardComponent
],
...

To use new component in application just put it’s selector in the necessary place.

<!-- src/app/app.component.html --><mat-toolbar color="primary">
{{title}}
</mat-toolbar>
<app-img-card></app-img-card>

And again let’s use material outlook for our card.

// src/app/app.module.ts...import { 
MatToolbarModule,
MatCardModule
} from '@angular/material';
...@NgModule({
...
imports: [
BrowserModule,
MatToolbarModule,
MatCardModule
],
...
})

Due to angular material docs, card template should look like:

// src/app/img-card/img-card.component.html<mat-card>
<img
src="https://cataas.com/cat/says/Progressive%20Web%20Cat"
alt="Cute cat"
mat-card-image>
</mat-card>

As a source for cat images we will use awesome free service called cataas.com, which api is quite straightforward.

Also, it would be nice to have some ‘Refresh’ button to get new cat pictures if we want to. Try to add MatButtonModule by yourself.

Time to write some code

// src/app/img-card/img-card.component.ts...class CatImage {
message: string;
api: string;
fontsize: number;
}
...

Now we can add a private property image of type CatImage for ImgCardComponent. The property src should be public and of type string. Take a look on the way we use that properties in the ngOnInit method:

// src/app/img-card/img-card.component.ts...export class ImgCardComponent implements OnInit {

private image: CatImage = {
message: 'Progressive Web Cat',
api: 'https://cataas.com/cat/says/',
fontsize: 40
};
public src: string; ngOnInit() {
this.src = this.image.api + this.image.message;
}
...

To make our button alive we should create a new function (public method), that will make some magic for us. I called mine generateSrc:

ngOnInit() {
this.generateSrc();
}
generateSrc(): void {
this.src = this.image.api + this.image.message +
'?size=' + this.image.fontsize;
}

Keyword void shows that our function has nothing to return.
Size is one of the image options provided by cataas.com api.

Time to make some changes in img-card markup. Replace long hard-coded source url with component property {{ src }}. To add event listener to the card button, use (click) attribute.

// src/app/img-card/img-card.component.html<mat-card>
<mat-card-actions>
<button
color="primary"
(click)="generateSrc()" // parentheses are important!
mat-button
mat-raised-button>
Give me another cat
</button>
</mat-card-actions>
<img
src="{{ src }}"
alt="Cute cat"
mat-card-image>
</mat-card>

Unfortunately, the image is not updating when we click on our Generate button, because actually the value of src stays unchanged. Let’s fix that by adding a fake query param with a timestamp in it.

// src/app/img-card/img-card.component.ts...public generateSrc(): void {
this.src = this.image.api + this.image.message +
'?size=' + this.image.fontsize +
'&ts=' + Date.now();
}

After adding some custom styles…

// src/app/img-card/img-card.component.css.mat-card {
width: 400px;
margin: 2rem auto;
}
.mat-card .mat-card-actions {
padding-top: 0;
}
.mat-card .mat-button {
margin: 0 auto;
display: block;
}

… we will finally get our working app. Enjoy your cats!

Image for post
Image for post

Step 4. Hosting our app on GitHub

4.1 Creating a new repository

Image for post
Image for post

Go to the terminal and run the following:

git add .
git commit -m "Upload project to github"
git remote add origin git@github.com:{username}/{repo name}.git
git push --set-upstream origin master

And that’s it! Reload repository page to see your code on github.

4.2 Build a production version of application

ng build --prod --base-href "/PWCat/"

As a result, we can see a new ‘/dist’ folder with our bundled app.

4.3 GH-pages

To begin with, let’s create a new branch for it. In terminal:

git checkout -b "gh-pages"
git push --set-upstream origin gh-pages
git checkout master

Go the the Settings tab of your repo, scroll down a little bit and find a ‘GitHub Pages’ section. Make sure that gh-pages branch is set as a source.

Image for post
Image for post

Although our site is finally published and available on the provided link, unfortunately we see only a content of README.md file. The problem is that github doesn’t see the index.html file in our root folder, and doesn’t understand that it needs a ‘/dist’ one.

To fix that, we can push to the gh-pages branch only a content from the ‘dist’ folder. To help us, saint people created an angular-cli-ghpages module for that.

npm i -g angular-cli-ghpage
ngh

If everything was done correctly, you will see the ‘Successfully published!’ message. Refresh gh-url of your app and enjoy that moment of glory!

You can find source code of my application here. Live app is available here.

See you in the Part 2.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store