Schwerer Gustav / Angular CLI?

So ng-conf happened with a lot’s of news from our beloved Angular world. One of the things that received big kudos from community, was undoubtedly Angular CLI. Mike Brocchi ( core contributor ) did a great talk at ng-conf about CLI capabilities, I highly recommend to watch it, to get a broad overview.

I was indeed curious to try it on some project, although I’m not very keen on using big CLI tools to control my life (“development workflow”). Also I’d like to point out, that when I hear “CLI”, it always puts a quote, from my good friend and high skilled developer Viliam Elischer, on my mind:

The best CLI tool in your project, is no CLI

Nevertheless, I wanted to give it a try. So there was this hackathon happening last weekend (Angular Attack), which was a perfect opportunity to try all those latest and greatest tools.

Our team had 4 members ( me, Viliam Elischer, Mario Vejlupek, @Puigcerber )

Tech stack used:

Angular 2 + Typescript

Firebase + Angular Fire 2

Angular Material 2

ngRx for state management

Angular CLI

Starting the project, was no brainer, thanks to CLI, just

npm install -g angular-cli ng new aattack-project cd aattack-project ng serve open http://localhost:4200

Immediately, you get everything up and running, and your project pops within your browsers. Just like this!

ng serve, boom

Well that’s not entirely true.

“npm i angular-cli”, is the thing, which will install all the internet… Yes it’s one time cataclysmic event, but it’s there and happening. From the time taken to download all it’s dependencies and seeing all those things pop up in your terminal, you can guess that it’s really huge(that’s why the intro picture == schwerer gustav, just trolling ) “package”. Yes, indeed it is :)

All right, let’s forget about how huge it is for the moment… Let’s start real app development with it.

Thanks to CLI we got Angular 2 / RxJS / Typescript with unit tests and E2E setup with ease. Ok, let’s add 3rd party dependencies.

Adding 3rd party dependencies

There should be an Angular CLI command for that right?! right?! Well, nope… :(

Fortunately there is a section on Angular CLI github wiki page about adding 3rd party dependencies. Cool, let’s add Angular Material shall we. We wanna use all the material components for our project, so we install it via npm:

npm install --save @angular2-material/core @angular2-material/checkbox @angular2-material/radio @angular2-material/input @angular2-material/toolbar ....

And now we can start using it within our project thanks to CLI right? Well that’s not entirely true. We need to configure the CLI tool and SystemJS, like described in the wiki:

Ok, let’s do it.

include material 2 into angular-cli-build.js

set up your SystemJS configuration

Note the comment in “system-config.ts” // And so on…

You have to do this for every 3rd party package, not only material, or you can be clever and start “programming” within your build tool.

Programming you say?

Cool isn’t it? Well not really, at least for beginner (which I’m not btw :D)…

Ok, that was kind of “easy”… Let’s add ngRx/store, that should be straightforward...

Well it isn’t, no angular-cli docs on their site, so you have to go to your projects node_modules, to figure out, which is the right file to add to systemJs config.

So after some digging, it turns out, that index.js is the “root”

'@ngrx/store': {

format: 'cjs',

main: 'index.js'

}

Next step adding Firebase and AngularFire.

Fortunately it’s documented on their github wiki, so easy peasy.

Cool so let’s run again “ng serve”, hop backt to the browser, and everything is set and working.

Project scaffold

Angular CLI enforces angular styleguide folder structure, which is cool if you really want it. In our use case, we wanted to go with Redux style powered by ngRx/store, so dissecting things into “containers” “reducers” “components” and “models” subfolders.

Thankfully CLI is user friendly in this case, and you just tell it where you want to generate stuff(component,service) and it will do it for you ( except the reducers… )

ng g c -is -it containers/user-list

ok, cool.

What is not cool, you may ask.

Well, when you create your files without the CLI, you have to manually add it to “system-config.ts” config, which in our case wasn’t so hard, because the only thing that we didn’t generate with CLI, were reducers, but as always YMMV for your particular project.

CSS Preprocessor

Huh, that was quite a journey so far! Let’s add support for Sass shall we ?

CLI help us! After skimming the terminal after “ng help” output for something related to css preprocessors, I found nothing. Ok whatever, there should be something in the docs, right? yes there is!

Angular CLI supports sass, compass, less and stylus.

To use one just install for example “npm install node-sass” and rename “.css” files in your project to “.scss” or “.sass”. They will be compiled automatically.

Wow that’s nice right! I like magic in devstack! Actually I don’t.

So how is this magic possible you may ask? Let’s dig into the source code. There is a method “_buildTree()” within “lib/broccoli/angular2-app.js” which contains:

_buildTree() {

// ... some broccoli trees related code ...



var buildTrees = [assetTree, tsTree, indexTree, vendorNpmTree];



// Add available and supported CSS plugins.

for (const suffix of ['sass', 'less', 'stylus', 'compass']) {

const plugin = require(`./angular-broccoli-${suffix}`);

const tree = plugin.makeBroccoliTree(

this._inputNode,this._options[`${suffix}Compiler`]

);

// ... some more logic

}

// ... some more logic

}

Important is the “for of” loop “for (const suffix of [‘sass’, ‘less’, ‘stylus’, ‘compass’])” which is responsible for adding support for preprocessors.

Hmm hard coded strings, sounds like fun…

Cool right?! hmm, so I wanna use postCSS + Sass. What now? I dunno, probably I should go to broccoli docs and learn how it works + write a plugin or some addon if there is none.

You know what? Forget about postCss and let’s stay rather just with Sass for this project…

So now everything is ready after “easy” setup and finally we can start writing our app.

Fast Development

Generating all those files in the right folders was super cool and big productivity boost.

What was not cool, was the “page refresh/app load time”.

This is DevTools Network panel from our starting app ( no custom code yet )

Loading time with SystemJS

Load of bare bone app takes 3.3 seconds!

Whoa, that’s unfortunate! This is not “fast” development at all. That number will increase when you’ll add more and more files to your app…

Why is this happening?

Under the hood Angular CLI uses ember-cli (which uses broccoli ), so those are the workhorses in terms of live reloading and other build stuff.

So you are saying that Angular CLI is slow? NOPE!

Well as I’ve mentioned, Angular CLI uses SystemJS as module loader/bundler, which may become a standard one day in our browsers (that’s also one of the main reasons why Angular Team pushes it forward)…

This long loading time is not Angular CLI’s fault at all, that’s SystemJS doing, because every one file is loaded dynamically ( kind of same technique under the hood like RequireJS uses ).

Can you spot the similarities between SystemJs/RequireJS ?

configure all dependencies ( exactly specify type of module system, main entry point etc…)

long waiting time on page reload

Updating dev dependencies

Let’s say you wanna have your stack under control in terms of keeping your 3rd party npm dependencies up and date ( which you should ! ). With Angular-CLI, you are not in full control, you have to rely on CLI updates as the time progresses. This can get pretty hairy in your dev stack. For example, let’s say you wanna use some newer version of broccoli or ember-cli or some other related plugin that Angular CLI uses. Well, you can’t and you just have to wait ‘till Angular CLI updates those.

Also if Angular 2 changes some API’s, you will just have to wait until somebody updates the blueprints for particular file and releases new version of CLI, but that’s a global issue with any generator tool out there.

Devstack Plugins versatility

AFAIK broccoli/ember-cli has not so huge ecosystem in comparison with webpack for instance. The same applies for SystemJS.

Webpack to the rescue?

Yes I’m webpack positive, not because it’s cool to use it, it’s because it makes your devstack small, robust, efficient and highly maintainable.

I’m not that kind of person which is choosing things based on cool factor.

Last year we migrated from “gulp” nonsense to pure npm scripts and webpack. The reasoning behind this decision was quite similar as Cory House wrote down in his superb article. Before migration, we did thorough analysis of existing solutions.

There were 3 options:

webpack + npm scripts

jspm + npm scripts

SystemJs + Gulp

SystemJs + Gulp was no go zone for us (because Gulp unnecessary abstractions, complicated configuration like mentioned previously, etc…).

jspm was looking good, but why reinvent the wheel and use another new package manager when we already have npm. Plus jspm uses SystemJS under the hood, which was not feasible, because various migration problems ( that’s topic for separate article )…

So we went with webpack and npm script. Just look at the webpack config files. There is no imperative logic, no if-else etc, just statements

Webpack and 3rd party libraries

Because webpack uses same methodology as Node and commonjs, you just

npm install -S your-library

and you are good to go, no configuration needed for adding 3rd party dependencies.

Webpack and CSS Preprocessor

no brainer, just install loader of your choosing and chain it as you please within “webpack.config.js” Done.

Sass + PostCss:

{

loaders: [{

test: /\.sass$/,

loaders: ['style-loader','postcss-loader','sass-loader']

}]

}

Webpack and fast development

It’s really fast. With webpack and webpack-dev-server you got the same live reload behaviour like with Angular CLI, with one important difference. Webpack-dev-server compiles all the stuff in the memory and everything is bundled within one optimised file(or chunks, depends how you want it), so the reload is really fast. You can also use hot-reloading feature which makes things even faster.

Here is the same app with webpack and AngularClass starter setup:

Loading time with Webpack

Load of bare bone app with webpack takes 0.8 seconds!

Nice, so webpack is awesome right? For sure there must be an option to opt in for webpack instead of SystemJS/broccoli with Angular CLI.

Well, nope :(

There aren’t any plans for webpack right now, I believe. The build process is tightly tied into broccoli since that is what ember-cli uses.

You can follow the whole issue thread here

Webpack and updating dev dependencies

You are in full control, just “npm i -S your-lib@latest” whatever you want ( I recommend using greenkeeper for this )

Webpack Devstack Plugins versatility

Lot’s of loaders, plugins and huge mature community!

Conclusion

Angular CLI is really awesome for following use cases:

trying out Angular 2

good for teaching purposes (workshops, meetups, demos … )

starting new project without zero knowledge about devstack

kind of ok for small personal projects if you are ok with long page refreshes

Where it falls short:

real development productivity ( SystemJS )

adding 3rd party resources ( SystemJS )

build customisations

keeping dev dependencies up to date

tightly coupled to SystemJS, broccoli + ember-cli

And maybe I can ask myself:

Would you use it for real app development and production? NOPE.

I would also like to mention that Angular CLI is still in Beta, so maybe mentioned “problems” with adding 3rd party dependencies and other customisations will be solved. What will not change for sure, is the tight coupled dependency on ember-cli( + broccoli ).

Anyway, kudos to everyone involved in CLI, I really like that I can generate files by hitting one command from my terminal and start playing with ng2 immediately !

Hmm, but wait a moment. I’ve already seen this somewhere!

Yes it was Yeoman, which came first with generating stuff for you. So why Angular team decided to go with tightly coupled “generator” to broccoli and ember-cli remains a mystery to me, when there is already existing and kind of better solution IMHO.

So I’ve just got this crazy idea, after real development experience with Angular CLI. Why not build own Angular CLI based on Yeoman and awesome angular class ng2 webpack starter and keep it really lightweight and un-opinionated? Would you be interested? Lemme know I can use your help!

That’s it. Cheers!

P.S. Also if you are more curious why Webpack is better option for real life development, listen to this Angular Adventures Podcast. Thx Juri Strumpflohner for pointing this out!