Recently I was tasked with developing a custom Angular widget on the latest release of Liferay DXP 7.3. This widget was developed to act as a reference architecture of an Angular SPA running in a Liferay portal environment.
The specific widget I developed was a Lead Management widget, a basic CRUD application that communicates via RESTful services to an external back-end system for managing sales leads. The reference architecture allows the back-end REST services to be easily mocked or simulated via tools like Strapi. We used a Strapi server to implement a lightweight, simple Leads management REST API to develop our widget against.
Our Lead Management widget was initially created following the Developing Angular Applications guide from Liferay.
With an update to Angular 10.1.x and some other added libs, our Angular widget project had a final package.json file with the following dependencies:
If we build our application with the default liferay-npm-bundler config scripts, all of our dependencies are added to the final bundle file. When an oversized bundle is deployed to Liferay, we immediately experience some noticeable performance issues. The default build scripts for the liferay-npm-bundler are:
The first noticeable performance issue was the blank white screen displayed for an extended period while the widget initially loads the application. The overall widget load time was unacceptable.
The final bundled application created with the liferay-npm-bundler was extremely large, with a file size of around 281 MB. Wow!
We needed a quick solution to solve this performance problem for our customer pilot project. Based on the file size, it appears that the default configuration of liferay-npm-bundler does not perform any type of Front End Optimizations (FEO) such as production builds, tree shaking, minimization, etc. It performs a custom Liferay packaging, and that’s it.
Front End Optimization
Tree shaking is a form of dead code elimination. It comes from the mental model of your application and its dependencies as tree-like structures. Each node in the tree represents a dependency that provides distinct functionality for your app. In modern apps, these dependencies are brought in via the static structure of ES2015 module syntax’s static structure, i.e., import and export. The name Tree Shaking and related concepts have been popularized by the ES2015 module bundler Rollup and are also included in Webpack.
Angular CLI is a command-line interface tool for initializing, developing, scaffolding, and maintaining Angular applications directly from a command shell. It is a very powerful tool that goes way beyond the simple bundler or generator.
- It has Webpack under the hood, already pre-configured, so you enjoy the benefits without the hassle of configuration.
- It’s very easy to use with a set of CLI commands.
- It comes with a code generator – you can use it to create skeletons of the most common ones (Components, Directives, Services, and Pipes) by simply using the CLI command ng g <type>.
Additional benefits of the Angular CLI tool include application environments and production-optimized builds. If we build our Lead Management widget as a native Angular CLI project, we can benefit from these built-in FEO features of Angular. So, we refactored the Lead Management widget project as described in this tutorial.
The final bundled application created with the Lead Management project’s adapted version was much smaller, around 2 MB in size.
This made a huge difference! The reduced file size of the Angular CLI production build alleviated the performance problems we experienced when using just the liferay-npm-bundler alone.
Application performance is a crucial element of your architecture. FEO helps fine-tune your website to make it more browser-friendly and load quicker. Broadly speaking, FEO focuses on reducing file sizes and minimizing the number of requests needed for a given page to load.
Utilizing the native Angular CLI and the liferay-npm-bundler allowed us to take advantage of the FEO build that the native Angular tool produces. Liferay-npm-bundler can then take this optimized bundle and adapt it at build time to be deployable to Liferay, greatly improving the widget’s overall performance in the portal.
If you have questions on how you can best leverage Angular with Liferay DXP or want to know how to configure FEO builds in liferay-npm-bundler, or just need help with your Liferay DXP implementation, please engage with us via comments on this blog post, or reach out to us at here.