BACK

First coding week

5 min read

The first week of GSoC 2016 coding period has ended. I started upgrading Jangouts from Angular 1.x to Angular 2. I completed all tasks within the deadline and hope to maintain this pace next week.

I'm following the upgrade guide from official Angular docs, which has two main blocks:

  • Preparation
  • Upgrading with The Upgrade Adapter

I just finished the preparation block. Fortunately, the Jangouts code is clear and already follows two key preparation requirements: the Angular style guide and component directives. This left me only two tasks: switch from <script> tags to a module loader, and migrate from JavaScript to TypeScript. I reversed the order, migrating to TypeScript first and then switching to a module loader. This sequence felt more natural for this project.

Migrating to TypeScript

Jangouts has a working gulp build system, so I did not need to worry about script loading. I focused first on migrating files to TypeScript, then leveraged the import syntax of TypeScript/ES6.

Migrating code from JavaScript to TypeScript is straightforward: change the extension from .js to .ts. The existing gulp system does not work with these changes, so run tsc --watch src/**/*.ts alongside gulp. This command shows many errors, but if the JavaScript code is correct, these errors relate only to TypeScript's type checking.

During this migration, I also made the code more modular. Jangouts had all components registered in a single Angular module janusHangouts. From previous projects, I learned this causes trouble with unit testing. I now define a separate module for each component (janusHangouts.componentName) and make it a dependency of the main module. This has two advantages: easier testing, and potentially loading components on demand with a module loader.

As mentioned earlier, compiling JavaScript code with tsc shows many errors. One common error is:

error TS7006: Parameter '$state' implicitly has an 'any' type.

The TypeScript compiler requires a type for all variables. To allow implicit any types for untyped variables, disable noImplicitAny in tsconfig.json.

Another error we can find when working with HTML elements is:

error TS2339: Property 'muted' does not exist on type 'HTMLElement'.

This error is produced from a code like that:

var video = $("video", element)[0];
video.muted = true;

TypeScript is type safe: $('video', element)[0] returns HTMLElement, which lacks the muted property. The subtype HTMLVideoElement contains muted. Cast the result to HTMLVideoElement:

var video = <HTMLVideoElement>$('video', element)[0];
video.muted = true;

Finally, another common error is:

error TS2339: Property 'id' does not exist on type '{}'.

TypeScript's type validation causes this error in code like:

var room = {};
// Some code here...
function isRoom(room) {
return room.id == roomId;
}

Define an interface for the room object to fix this and reduce errors:

interface Room {
id?: number; // ? makes the attribute optional
}
// Some code here ...
var room: Room = {};
// Some code here...
function isRoom(room: Room) {
return room.id == roomId;
}

Using a Module Loader

Why use a module loader? The Angular site explains:

Using a module loader such as SystemJS, Webpack, or Browserify allows us to use the built-in module systems of the TypeScript or ES2015 languages in our apps. We can use the import and export features that explicitly specify what code can and will be shared between different parts of the application. [...]

When we then take our applications into production, module loaders also make it easier to package them all up into production bundles with batteries included.

I discarded Browserify due to past bad experiences and tried only SystemJS and Webpack.

SystemJS

SystemJS looks clean and simple. Define an entry point (typically the main application file) and the import syntax handles the rest. With correct import statements, everything works.

However, this solution requires keeping gulp since SystemJS only handles imports. This means adding the TypeScript compiler to gulp and disabling auto script injection in HTML.

Before rewriting the gulp configuration, I wanted to try Webpack first.

Webpack

Webpack configuration is more complex than SystemJS, but replaces gulp entirely. Like SystemJS, we define an entry point and specify where index.html is located for JavaScript file inclusion.

I had initial troubles, but after studying examples, I got a functional version. Exploring Webpack further, I found what made me choose it: we can import or require non-JavaScript files. We can require an Angular directive template, and the build process includes it as a string variable inside the component. Styles work the same way. This improves performance by bundling all files a component needs into its JavaScript file, without complicating development.

One more thing

This summer looks exciting with everything I will learn through GSoC. Follow my progress on this blog or through my GitHub contributions. I also published a Trello board with the project planning and tasks (still being updated).