Tuesday, January 10, 2017

My JavaScript Module experiments

Background

After I wrote my post about the selecting Angular 1 for my personal site when Angular 2 is out, I seriously started thinking about myself. Am I too joining the group who hate changes? As mentioned in that post, the main bottleneck is not the concept or syntax of ng2 nor it's performance and stability. The problem was around tools. What are those tools doing? They help us to write modularized JavaScript. They do transpilation, bundling, minification etc...

If we download standard ng2 project starter template, we will get pretty much a good running starter. The tools will be already configured. From there we can simply add our own functionalities. Unless we have crazy requirements, that configuration will work. We just need to add features. Then what is the trouble? The trouble, at least I had was that I am not getting how those tools are doing the magic. I checked with some other people who has problems with ng2. I could see they also have trouble understanding the tool chain. Its very difficult to move ahead in that magic setup especially, if we are coming from little old school who want to know exactly how the software works. For most of the newbies, it doesn't matter. As far as the setup/tool chain is working they can code new features.

Is there a way to survive in web development without knowing bundling? The answer is 'no' as that is the way forward to build huge apps.

So what is the solution. Learn the JavaScript module system from basics with simple samples than  starters which are configured to use features such as transpilation, source map, minification, unit testing, dev & prod  modes etc...

This post explains how I learned module system in my way, though there are tons of tutorials explaining the JavaScript module system. Most of the steps will be pointing to external sites to avoid duplicate content and of course they explain better than me.

What is JavaScript module system

If we have background in Java, it is the equivalent of Java package system. For .Net people, it can be compared to assemblies. Simple as that. But since the JavaScript engines don't have native support for modules, we have to rely on different tools which does the module implementation. To me its like workaround till the browsers or the JS engines know what is module. May be at least in the case of module loading. I am not expecting any JS execution environment will ever help us to create a bundle.

What is the relation to Angular 2 and these module system? Angular 2 uses these module concept and it is good to follow the same for our app as well. So if we download any Angular 2 sample or starter, we can see it uses SystemJS or Webpack. As mentioned earlier, either we can just download a starter and extend it without knowing how the magic works or learn what is the module system from the scratch.

Selecting WebPack

If we google for JavaScript module tools we will see many. Browserify, RequireJS, SystemJS, webpack to name few. We can debate which one is better for days and that itself require one separate post. So for the time being selecting webpack as it is selected by Angular-cli and at least it is not in beta.

NodeJS n NPM are everywhere

It is very difficult now a days to do web development without knowing node and its package management tool NPM. Though Node & NPM doesn't have any role inside browser they are used in tooling side. Webpack also comes as NPM package. So this post assumes reader has knowledge about NodeJS & NPM 

Step 1 Understand via simple ECMA 5

The first thing as JS developer unless we are born to ES6 is to learn how we can modularize ECMA5 or ES5 or simply the traditional JavaScript code. There is no need to write one more tutorial to understand how ES5 can leverage webpack. Just go to 'getting started' tutorial of webpack and try it.

Please try till Section "THE FIRST  LOADER" in the below 'getting started' link.

http://webpack.github.io/docs/tutorials/getting-started/

Before using loader, it is good to know something else. Obviously we should come back to loaders. Because loaders does magic. 

After trying the above, remove the .js extension from require and run. Sample below.

var content = require("./content.js");
to 
var content = require("./content");

We can see still it is working. The file extension is something optional.

Step 2 - webpack.config.js

If we go through any webpack tutorial, we can understand that most of the issues using webpack is because of wrong webpack.config.js. So it is important.

Minimum config

Lets see what is the minimum config required for this webpack.config.js file. Have a look at the below link starting from "Defining a config file" section where it is explained clearly. Read till the "Webpack loaders and preloaders".

Watch mode

This is a useful mode in development. This is explained in the above tutorial.

Dev Server & hot reload

These are again development time features where we can start a light web server which monitors the development changes and reloads for us. This save good amount of time in switching to command window and typing commands. Yet to see what will happen on performance, if there are 100s of files.

The feature is explained in the above tutorial.

Step 3 - Enter TypeScript

A big no to ES6 at this point only because it lacks compile time type system. This is again debatable. If we are dealing with small applications, it is better to be dynamic typed ie pure JavaScript. But for bigger apps, type checking is must. Otherwise it will take a good amount of time  ie time needed for finding out what are the members of objects and what a function accepts and returns.

In this section we are going to see how TypeScript and webpack works together.

The below article below explains TypeScript and how to use TypeScrpt with Webpack. Read from beginning till "Watch Support"
http://www.jbrantly.com/typescript-and-webpack/

Why till "Watch Support". Because it then includes jQuery. Our focus is to understand how webpack can be used to process TypeScript not with jQuery.

Now its time to clone my webpack repo given below. This will be used going forward in this post.
https://github.com/joymon/webpack-starters

It has a folder named ECMA5-TypeScript. Point command line to that folder and run webpack command. We could see it transpiles the logger.ts & tscomponent.ts and output bundle.js along with other ES5 modules. Running the index.html from disk will show some log statements.

"TypeScript Worked !!! - logger module loaded" - Means a ES5 module was able to load TS module.
"TS component which has dependency on JS component worked" - Hope it is self explanatory

Lets see how it worked

Loaders in webpack - ts-loader

Loaders help to process the file, if those are in different formats. For example, today browsers don't know how to read and execute the TypeScript. So the TypeScript needs to be transpiled to JavaScript. That can be done by using the webpack loader mechanism. In this "webpack-starters" repo, ts-loader is used for that purpose. The configuration is present in the webpack.config.js.

After loader does its job, the final bundle.js is created as usual. index.html only knows bundle.js.

TypeScript loading ES5 modules

If we need ES5 code to load a TS module it is easy. Since ES5 don't care about types, we can write any valid js and at runtime only it checks the objects. But if we want to use ES5 module in TS, the first thing is to tell, what is require() function. TypeScript as language don't know what is require(). So to tell TypeScript about require() we have to use nodejs typing. Node typing has the definition for require(). 

To add Node typing the sample is using a package called  @types/node. Refer package.json. 

Please note since this post is not aiming at teaching TypeScript language and what are typing files,  more details on @types/node are omitted.

Step 4 - TypeScript with AngularJS 1.x

Here we are going to next step of using AngularJS 1.x via webpack module mechanism. The sample is present in the TypeScript-Angular1 folder of the "webpack-starters" repo mentioned above. Sample just shows a simple Angular 1 application with one component.

Setting up ng1+TS+webpack from scratch involves multiple steps which are given below
  1. Initial setup of TypeScript+webpack
  2. Include the NPM package for Angular
  3. Include the @types/angular.
  4. A module where angular.module() is called to setup angular. In the sample refer to ngModule.ts
  5. An entry point(bootstrap.ts) module where we can call the above module and add other Angular constructs such as components, services, filters etc...Big sorry for directives for easy conversion to ng2.
  6. Index.html to use required Angular directives.Minimum ng-app.
  7. While adding components export them
Now have a look at the TypeScript-Angular1 folder of the "webpack-starters" if not done already. Below are some questions which might have popped up. The answers are also given along with questions,
  • Why ngmodule.ts? 
    • This is just a class for wrapping the original angular object. This gives us a common place for registering the angular object such as registering components, filters, services etc...This is optional. Just make sure the code which is executing angular.module and other registration functions are getting called.
  • Why bootstrap.ts
    • This acts as entry point for the application. It imports all the other modules which contains the app is ngmodule and all the angular constructs. For simplicity the sample only includes a simple component.
  • How did the require("angular") worked? Who exported the angular library for webpack?
    • This is done by the node_modules\angular\index.js .It exports as angular. If we change this we can see the module is not found.
  • Why webpack-dev-server is needed. Can't we double click and run from the disk?
    • For just ng-app to work, there is no need of web server. But for angular to locate and load the html template, it requires app to be served via url not just from disk. We can even use IIS to serve the folder. Only requirement is to navigate via http protocol.
Any new questions can be asked in the comments which will be included into the post later with answers?

More

This post shows the tip of iceberg. There are many more things which are required to setup a professional application for development and production. With this basic understanding of module system, learning those will be easy.

Some links are given below which are related to JavaScript modules and bundling

1 comment:

Sindhuja Ravi said...
This comment has been removed by a blog administrator.