How To Run Angular 2 In Production after the Final Release ?
Have a look at the latest CLI, which is the Webpack Beta Preview version that was released together with final. Using it you can do the following with only a couple of commands:
- scaffold an Angular 2 Final project
- generate components, directives, etc. according to the style guide
- get a production bundle (tree-shaked and in the future ahead of time compiled)
- the bundle is also gzipped
Have a look at this demo of getting started with Angular 2 Final and the Angular CLI (remember that the CLI is still in Beta):
Check the bundle size that you get, and if this works well for your project, it would be a matter of keep updating the CLI version until it 1.0 lands.
The remainder of this post is deprecated since Angular 2 Final, but here it is in case somebody applied these temporary techniques.
This post details some of the techniques used to run an Angular 2 application in production (the Angular University website). Our actual setup is slightly different as the main site is an Angular Universal app (more on a future post).
Recently there where announcements that made clear that the Angular 2 final release is just around the corner. This could happen anytime now !
But that could be still a couple of months into the future, and there are many projects that either will start or are already ongoing between now and then. A question that gets asked a lot these days is: should I use Angular 2 or just stick to Angular 1?
Angular 2 is currently in Release Candidate, and even since Beta this means the following according to the official announcement:
...means we're now confident that most developers can be successful building large applications using Angular 2
Also we had a recently announcement that no breaking API changes will occur between now and Final.So the answer is yes, we should definitely use Angular 2 for projects starting today. But how?
Lets answer this and several other questions while going through the following topics:
- A strategy for putting an Angular 2 app in production
- choosing a package manager and a module loader
- Is the bundle size a real concern?
- The current state of the angular-cli
- Choosing a lightweight toolchain while waiting for angular-cli
- How to use Angular 2 with a minimal build
- How to handle HTML templates
- How to handle CSS
- How to handle internationalization
Current status of the Angular 2 composing parts
The Angular 2 core functionality which includes Components, Directives, Forms, Pipes, Dependency Injection and HTTP has been stable for several months and ready to go. The router is being rebuilt to support lazy-loading, but the API should not be very different from the currently functional
There are still some hoops to jump through, but those are the exception and not the rule.
So what is preventing us from using Angular 2 in production? There are several perceived reasons, one of them could be that the tooling around it is a work in progress.
The current state of the angular-cli
On the long term, one of the great advantages of Angular 2 is that we will have an opinionated way to setup and build a project, via the Angular Command Line Interface (CLI).
But most importantly, we will have a build system officially endorsed by the Angular 2 team that will take us from development to production.
The problem is that the angular-cli although already working and being used to build the Angular 2 Material widget library, its still currently still in Beta.
So its clear that on the long term we want our Angular 2 projects to be built using angular-cli, but that solution is still in its early stages.
Also related to the toolchain, there are more questions regarding how to setup our project.
Is there a recommended package manager and module loader ?
For one, which package manager and module loader should we choose? Our safest bet is is to align with what the CLI is currently using:
- Package manager: The package manager is npm, based on the existence of proposal documents for making npm more friendly for frontend development, and the fact that almost everything can be found in npm these days
- Module Loader: both the quick start tutorial and the initial version of angular-cli use SystemJs, although recently there was documentation section added on webpack.
Its important to bear in mind that this does not mean that the framework will not work in other package managers or module loaders, by the contrary all of them will be supported.
Besides the toolchain, there seems to be another main point that is being worked on: the overall bundle size.
Is the bundle size a real concern?
Without the offline template compiler, the current 115KB compressed and minified size of the main Angular 2 bundle might not be a concern depending on the type of application you are building:
- are you building an enterprise application that will run only on a company LAN? You probably have a very fast server connection, making the bundle size even less of a concern
- are you going to production in less than 2 months? By then the size of the bundle issue (if its an issue at all for your project) should have been fixed
- are you building a productivity single page app? One extra second of initial load time might not be an issue. For example users are used to wait over 5 seconds for Gmail to open
This means that we should be able to run an application in production today. Given this and all of the above, can we come up with a strategy to do so?
A strategy for running Angular 2 in production in the next few months
One way to do it is to choose a lightweight toolchain that can be put in place quickly but still is sufficient to put an app in production. At the same time we want to make sure that such toolchain can be easily replaced in a couple of months once angular-cli lands.
Once angular-cli is ready, we will then have all the functionality necessary to compile templates in a build step instead of at startup time. With that the compiler part of Angular will not need to be shipped to the browser and the bundle size will be drastically reduced.
What we want to avoid is to make a large investment in a complex toolchain that we already know upfront that will be obsolete in a matter of months.
So let's start choosing our toolchain and development practices, with an eye towards the present, but keeping it future-proof regarding a future migration to angular-cli.
Package Manager and Module Loader
Lets start with the simplest choices: its better to use npm as our package manager and SystemJs as module loader, as that seems to be the path of least friction.
Note that other package managers and module loaders would also work, but this is the choice that will likely be easier to migrate to angular-cli, and its the combination that angular-cli currently uses.
How to load Angular 2
For loading Angular in the app itself, a very straightforward way to do so is to simply use a CDN to get your scripts loaded. This gives the following immediate benefits:
- it allows the development to start right now
- it makes for a simpler initial build
- its easy to go back later once angular-cli is available and refactor this
- its actually a viable option to use in production (for many applications) as we will see next
Where to load Angular From
The best place to see how to load Angular 2 using script tags only is checking the official Angular 2 Plunkr updated to release candidate.
The plunkr makes uses of the NPM CDN, which contains all the bundles needed to run Angular 2. Let's have a look at the timings for application startup:
These are pretty acceptable timings ! We can actually run many productivity or enterprise desktop-like apps using this setup, with no problem at all.
But what about other things, like how should we handle our HTML or CSS in a way that its future proof and easy to migrate to angular-cli?
How to handle HTML templates
The main concern about HTML templates is that we want to make sure that we won't have to load them in separate HTTP requests in production, as this really slows down a lot the application startup.
In Angular 1 we would use a build step to pre-populate the template cache using plugins like gulp-ng-html2js.
This will be one of the tasks of the offline compiler, that will allow to build an ecosystem of tooling around templates. But right now, we have two ways to include templates in a component:
- inline templates: This consists on adding templates as inline strings directly in the component code. It has the advantage that at runtime there is no extra HTTP request, but this method might not scale well for large templates
- external templates: Templates can also be placed in external html files. This is cleaner and scales better specially in a team with designers and several developers editing the same code. But this will result in an extra HTTP request per template
As we can see none of the two solutions is ideal. Lets see if we can come up with a better way, but first let's see how templates will be handled in the future.
The solution for importing templates in the future
What we need is a mechanism to import a file in Typescript as a string. This already exists in SystemJs itself, but we are only using it to load scripts in the browser and not during Typescript compilation. It also exists in Webpack, via the text loader.
For out setup the ideal would be something like this:
And then we could use the template as a variable and pass it on to the component:
This functionality will be available in future versions of Typescript, see for example this Github issue. So there is no indication that importing templates will be handled by angular-cli, this will simply be a new feature language of Typescript (although angular-cli might provide an alternative, its currently not clear).
But what can we do while this is not available?
A way of handling HTML templates
If the template of the component is small, the option remains to keep it inline. If the template gets too big, its possible to externalize it in a separate Typescript file that exports a single string. In practice this looks like this:
Notice that the syntax highlighting and the autocompletion is still available even inside embedded strings. This is automatically the case in Webstorm. If by some reason Html is not detected, its possible to so manually using
Alt + Enter inside the template.
The template (named
test.html.ts) can then be imported via the following syntax, and simply used as a string:
This has the following advantages:
- this does not cause an extra HTTP request
- The template is an external file, this scales better for larger teams and projects
- Most of the IDE Html tooling works correctly in the external file
- this file can be easily migrated to a plain HTML file once Typescript "import file as string" functionality is in place
A simple way to bundle an Angular 2 application
Luckily since Typescript 1.8 there is a simple way: we can configure the compiler to output the compilation result to a single file instead of separate files. For that, we just need to adapt our
Notice the value of the outfile property, its a new compiler feature. With it its possible to generate SystemsJs and AMD bundles (currently CommonJs is not yet supported).
In our case this does not pose an issue, as we are using SystemJs. What we have with this is an output bundle of our whole application containing all the templates embedded inside it and ready to be loaded by SystemJs.
It would be just a matter of adding a simple gulp build to minify the file, cache bust the file name and inject it on our
But there are still a couple of loose strings to tie, and the biggest one is: how should we handle CSS in our application?
How to handle CSS
Shadow DOM is not available in all browsers, but we can still import styles at the component level using emulated mode. This will encapsulate the styles to make them affect only the component by prefixing the style with a high specificity selector. Have a look at this example:
The problem is that without the appropriate tooling for generating source maps, this currently cannot be debugged (but it will be so in the future).
A solution for handling CSS
One manageable way to manage a project with a large amount of CSS is to simply include it externally as a link tag, this has always worked and nothing in Angular 2 prevents us for using it.
But to keep it manageable, a solid choice is to use Sass like the Angular 2 Material (the new Angular 2 widget library) project is currently doing, and like the Angular 1 version of the material design widgets is doing too.
The current version of angular-cli has Sass support, and the Angular 2 material alpha is already using angular-cli to handle their Sass/Css.
There is a large chance that if you ever use Angular 2 material in the near future (note: the components can be used one by one), you might have to customize Sass files to adapt the widgets to your application theme.
The most future-proof path of handling Css is to adopt the same pre-processor as the official component suite: Sass.
Using Sass in a reasonable way
Sass is very powerful and there has been a movement (PostCSS) to instead componetize each extension to CSS separately in a plugin architecture. So for example, if we want a feature like Css file imports, variables or nested styles we can add those one by one.
One alternative is to simply use Sass but not abuse its many powerful features. For example, don't nest styles too deeply just for grouping them under a single component, it creates very long selectors. If inside another component you want to override the styles, you have to create a very long selector, with all the maintenance issues that it brings.
Doing CSS in a structured way
Complementing the use of Sass with a good CSS structuring methodology like Smacss is a good solution. The two are not exclusive, by the contrary its very convenient to implement Smacss using Sass.
Using Sass integrated with Angular 2
Its clear that further down the line it will be possible to use Sass easily with Angular, by simply importing
.scss files in our component.
Then a build step will transform the Sass into CSS and generate the appropriate source mappings that will allow to take advantage of the emulated encapsulated mode in a debuggable way.
But right now, a simple Sass build should get us going, knowing that in the future it will be easy to migrate it to the angular-cli pipeline.
How to handle internationalization
The final release of Angular will contain a working i18n solution, with an extended set of features. And that is the advised solution for i18n in the long term.
We are not sure what the i18n solution will look like, but the translations will very likelly be applied in a build step and multiple versions of the application will be generated.
But if you really need to write an application its better to add translations from the beginning using a version of ng-translate for Angular 2: ng2-translate.
This has the same set of features that ng-translate has, which has been used to translate a very large number of applications in Angular 1. ng2-translate will cover the large majority of the needs of your application.
With a couple of simple methods presented above, its totally possible to start developing an application and also have it running in production today.
By making our choices having in mind what the future will look like, its feasible to setup a build and development methods that suits our immediate needs, but still does not prevent us from easily migrating to angular-cli in the near future.
For another Angular 2 production testimonial, have a look at SherpaDesk triples perfomance with New Progressive Ionic 2 Web App.
Want to Get Started With Angular 2 ?
If you enjoyed this article, we invite you to subscribe to the Angular University Newsletter (see box bellow).
In case you are just getting started with Angular, but also if you have some experience with it, you might want to have a look at our course on Youtube which is under development:
On Template Transforms - https://youtu.be/bVI5gGTEQ_U?t=902
Looking for other Angular 2 Learning Resources ?
Check our top 10 list of Angular 2 Resources:
Other posts on Angular 2
If you enjoyed this post, here some other popular posts on our blog:
- Angular 2 Router - How To Build a Navigation Menu with Bootstrap 4 and Nested Routes
- Angular 2 Router - Extended Guided Tour, Avoid Common Pitfalls
- Angular 2 Components - The Fundamentals
- How to build Angular 2 apps using Observable Data Services - Pitfalls to avoid
- Introduction to Angular 2 Forms - Template Driven, Model Driven or In-Between
- Angular 2 ngFor - Learn all Features including trackBy, why is it not only for Arrays ?
- Angular Universal In Practice - How to build SEO Friendly Single Page Apps with Angular 2
- How does Angular 2 Change Detection Really Work ?