Sunday 4 June 2017

Build & Deploy Angular 4 Projects

In January, this year, I was dealing with the migration from AngularJS to Angular 2. In the meantime the current version of Angular is 4. I decided to skip Angular 2 and continue with Angular 4.

I'm still working on a Windows 10 workstation using the Atom Editor, Eclipse STS, NodeJs (7.10) and Java 8 (131); but some times I change to a Ubuntu 1604 notebook. The good news is the application can be compiled on both systems without any change.

Angular CLI

The CLI is now reliable and the debugging works. It is really simple to generate a new project and to start programming and debugging. Migrate a complex application is a much bigger task because it is necessary to understand how the CLI works and how it may support all the required technical use cases.

The generated project template has very simple structure; a complex application requires some more organization. I start with two modules home and share. The module home is responsible for the homepage. The module share is a container for the reusable part of the code.
prompt > ng generate module about
prompt > ng generate component about
prompt > ng generate module home
prompt > ng generate component home
prompt > ng generate module shared

The routing is something which may lead to confusion if not properly organized from the beginning. I will have a central routing module to support e.g. lazy loading and dedicated module routes for features. I add manually an the central module: I place the app-routing into the app root folder.
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [
    RouterModule.forRoot([
      /* define app module routes here, e.g., to lazily load a module
         (do not place feature module routes here, use an own -routing.module.ts in the feature instead)
       */
    ])
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

The AppModule has to be changed accordingly:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { AppRoutingModule} from './app-routing.module';
import { HomeModule }      from './home/home.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    AppRoutingModule,
    BrowserModule,
    FormsModule,
    HomeModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

The home component need also a own routing module:
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HomeComponent } from './home.component';

@NgModule({
  imports: [
    RouterModule.forChild([
      { path: '', component: HomeComponent }
    ])
  ],
  exports: [RouterModule]
})
export class HomeRoutingModule { }

The HomeModule has to be changed accordingly:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HomeComponent } from './home.component';
import { HomeRoutingModule } from './home-routing.module';

@NgModule({
  imports: [
    CommonModule,
    HomeRoutingModule
  ],
  declarations: [HomeComponent],
  exports: [HomeComponent]
})
export class HomeModule { }

The routing setup is now completed by changing the HTML code of the app component:
<router-outlet></router-outlet>

Now, after typing at the prompt ng serve, the application is available calling the URL http://localhost:4200. The application may be build using ng build; the result is placed into the build folder. I copied all the files into the static folder of my Springboot application: it works.

Electron

At this point I was wondering if my application would also work for GitHub Electron. It took some times to collect all information but, at the end, it is quite easy.

The first step is to add electron to the development dependencies (the following snippet is for Windows):
. . .
  "scripts": {
   . . .,
   "build-electron": "ng build --base-href . && copy src\\electron\\* dist",
   "electron": "npm run build-electron && electron dist\\electron.js",
  },
  . . .,
  "devDependencies": {
    . . .,
    "codelyzer": "~2.0.0",
    "electron": "1.6.6",
    "jasmine-core": "~2.5.2",
    . . .
  }
  . . .
The next step is to install electron using npm install at the prompt. Now I have to add the electron code to the project:
// src/electron/electron.js

const {app, BrowserWindow} = require('electron')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  win.loadURL(`file://${__dirname}/index.html`)

  // Open the DevTools.
  win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
{
  "name" : "myproject-electron",
  "version" : "1.0.0",
  "main"    : "electron.js"
}
The last action is to change the base TAG of the index.html file: href="/" --> href="./" Now, typing npm electron the application starts as a desktop application. The very last step would be to pack the electron build in a self-installing package for Windows, MAC and Linux. This will be the argument of one of the next articles.

Credits

The integration of Electron is base on a the post Package an Angular CLI Application into Electron published by Bruno d'Auria.

No comments:

Post a Comment