Angular 2: Musing on the potential of Hot Module Replacement and the power of @ngrx/store

If you're just getting started, this link might be helpful: understanding the purpose of HMR.

When it comes to managing and designing large projects, I'm still in the early stages and haven't grown a wise beard yet. So, I'm seeking advice from experienced individuals like yourself.

Exploring the Seed

I've been exploring the Angular 2 seed project and wondering if implementing HMR is a feasible option for developing a large application effectively.

These are just my initial thoughts, and I'm eager to have a discussion with others to make an informed decision. Learning from each other's experiences is crucial :-)

Data Structure Discussion

Considering the example below:

 (component code snippet) 

Utilizing appState allows components to be dynamically reloaded and data injected. However, should we rely on objects like localState within components? Is this practice manageable in large applications?

On the other hand, utilizing localStorage solely for tracking data required by HMR seems like a straightforward approach.

Data Storage and @ngrx/store

In terms of storage, I also utilize @ngrx/store as a Redux implementation where the state serves as the application's localStorage. While this setup sounds promising, integrating @ngrx/store with HMR poses some challenges given that existing connectors may be outdated.

Aligning Angular services with reducers and finding ways to update HMR's state presents further considerations.

While @ngrx/store and HMR are recognized technologies within the Angular community, resources on combining them are limited. Therefore, I seek insights based on practical experiences and potential pitfalls that may not be immediately evident.

Final Thoughts

  • Is HMR deployment-ready for production environments?
  • Is storing substantial information within @ngrx/store advisable?
  • A crucial question: How well do these technologies integrate?

These inquiries echo similar discussions found at this link.

Answer №1

In Summary - HMR is primarily a development tool that helps speed up the process without requiring you to fully understand its inner workings. If issues arise, simply refresh the page. In the long run, it will save you time...

Building Angular apps can be time-consuming due to their size (a few megabytes). HMR is utilized during development to reduce compilation times, allowing you to see changes instantly without delay. It operates by leveraging existing loaders like webpack and systemjs. Most likely, this information isn't new to you (;

I recently developed a personalized HMR solution based on Systemjs (using systemjs-hmr). The fundamental principle involves: notifying the loader of code changes and reloading those changes. Additional adjustments are necessary to ensure your app remains functional...

The core features of my HMR include:

  • reloading modified app code (components, services, pipes...),
  • recreating <app-root>, as depicted here,
  • disposing of the previous app with NgModuleRef.destory(),
  • bootstrapping the new app using:
    platformBrowserDynamic().bootstrapModule(AppModule).then(module => window['__HMR__'] = module)
  • obtaining the initial value of @ngrx/store

This is the script I implemented:

import { Store } from '@ngrx/store';
export function get__HMR__state() {
  let state = {};
  if (window['__HMR__']) {
    const module = window['__HMR__'];
    const store = module.injector.get(Store);
    store.take(1).subscribe(s => state = s);
  }
  return state;
}

@NgModule({
  imports: [
    StoreModule.provideStore(AppReducer, get__HMR__state())
  ]
})

I refrain from storing unnecessary data in my app's AppState (ngrx/store). Input values and attributes should be managed more effectively like this.

The functionality works efficiently; after initiating my custom gulp build workflow at the beginning of the day, I rarely encounter issues thereafter (; An occasional hiccup may occur, especially when adjusting project structure and dependencies, but a quick F5 resolves the problem. Reloading promptly functions well when editing templates and styles, which significantly reduces downtime.

For "project management," I rely on angular-cli, and while using its ng serve feature (powered by webpack), the rebuild time ranges between 3-8 seconds + 2-4 seconds for the reload with each code alteration. Conversely, with Gulp+HMR (implemented on the same cli project), the rebuild time diminishes to 50-400ms + 200-500ms reload. That disparity prompted me to develop a tailored build solution (; Should complications arise, pressing F5 ensures the app runs smoothly within 2-4 seconds.

In conclusion, I highly recommend incorporating HMR for individuals spending several hours per day coding (; While it may not be flawless, no tool is, yet it ultimately saves substantial time in the grand scheme. Nevertheless, do not adjust your app solely to accommodate the tool. Write code as you normally would without HMR. Custom enhancements are possible if additional functionalities are required since, essentially, it's just JavaScript (;

Answer №2

Upon exploring this repository, I found it to be incredibly insightful.

The codebase utilizes Angular 2, HMR, @ngrx/store, and more. Through reviewing the code, I have gained valuable knowledge. The approach of using @ngrx/effects alongside @ngrx/store and HMR is impressively straightforward, especially evident in the app.module.ts. Thanks to AngularClass/hmr-loader, everything is conveniently consolidated here:

hmrOnInit(store) {
    if (!store || !store.rootState) return;

    // restore state by dispatching a SET_ROOT_STATE action
    if (store.rootState) {
      this._store.dispatch({
        type: 'SET_ROOT_STATE',
        payload: store.rootState
      });
    }

    if ('restoreInputValues' in store) { store.restoreInputValues(); }
    this.appRef.tick();
    Object.keys(store).forEach(prop => delete store[prop]);
  }
  hmrOnDestroy(store) {
    const cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
    this._store.take(1).subscribe(s => store.rootState = s);
    store.disposeOldHosts = createNewHosts(cmpLocation);
    store.restoreInputValues = createInputTransfer();
    removeNgStyles();
  }
  hmrAfterDestroy(store) {
    store.disposeOldHosts();
    delete store.disposeOldHosts;
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for effectively managing index positions within a dual ngFor loop in Angular

I'm working on a feedback form that includes multiple questions with the same set of multiple choice answers. Here's how I've set it up: options: string[] = ['Excellent', 'Fair', 'Good', 'Poor']; q ...

React router loader is not functioning correctly when trying to fetch data

My attempt to fetch an array of data from an API is resulting in an empty response within the application. However, when I try the same call in a swagger, it returns the correct array. HomePage.tsx: const HomePage = () => { const books = useLoaderDat ...

What is the best way to format this DateTime for a more visually appealing appearance within an Angular Material <mat-card-subtitle>?

My date looks like this: 2000-12-16T00:00:00 When displayed in Material code (as the publish_date): <mat-card *ngFor="let book of bookItems"> <mat-card-header > <mat-card-title>{{book.title | titlecase}}</mat-card-title> ...

Establishing the Redux state using an Express backend

Currently pondering on updating a redux state using an express backend. For instance: When a user triggers an API endpoint in my express backend, the "API CALLED" counter in the Redux state of my application frontend should increment by o ...

Conceal the Froala editor when blur events occur

Currently, I am utilizing Forala with the specific setting: initOnClick: true, Everything is running smoothly, but is there a way to accomplish the "opposite" I'm looking to hide the editor upon blur? I have searched through the documentation, but d ...

The property 'value' is not recognized on the Element type

I am currently working on a project where I need to calculate the total sum of values entered in a specific column within a mat-table. The setup involves creating a table with three columns: Account Id, Account Description, and Value. Additionally, I have ...

Unable to retrieve JSON data in Angular2 as expected

I am encountering an issue while attempting to retrieve data from a JSON file stored in my assets folder within Angular 2. The data is not displaying as expected despite my efforts. The JSON file I am trying to access is named: test.json [ "{'id ...

What steps can be taken to eliminate repeat categories and prevent the accumulation of endless iterations?

Analysis I designed an interface that takes two type parameters, with the second parameter being optional and defaulting to void. Additionally, I created a utility type called CommandReturnType which employs conditional typing to ensure that void is not r ...

The MSI installer for electron-builder is rejecting the asar file due to its excessive

My Angular application requires an MSI installer, but I encountered an error while trying to create one for the electron app I developed using `npm run electron`. The error message states: Error LGHT0263 : 'C:...\release\win-unpacked&bsol ...

Tips for writing unit tests for clipboard copy functionality in an Angular application

How can we monitor the behavior of the clipboard.copy method? For const clipboard = TestBed.inject(Clipboard); spyOn(clipboard, 'copy').and.returnValue(true); An error warning pops up indicating that Argument of type '"copy"' ...

What is the reason why the [active] attribute does not function properly in <a mat-tab-link> in Angular?

<div class="d-flex d-column themed-tab-nav"> <nav mat-tab-nav-bar color="primary" [tabPanel]="tabPanel" mat-stretch-tabs="false" mat-align-tabs="start"> <a mat-tab-l ...

Issue with Angular project: View not being updated when using behaviorSubjects

Within my Angular project, I am retrieving data from an API using a service and storing the data within a BehaviorSubject as shown below private categorySubject = new BehaviorSubject<number | null>(null); apiBehavior = new ReplaySubject<ApiRes ...

Ways to update the component's state externally

I'm new to Next.js (and React) and I'm attempting to update the state of a component from outside the component. Essentially, I am conditionally rendering HTML in the component and have a button inside the component that triggers a function to se ...

Unit testing of an expired JWT token fails due to the incorrect setting of the "options.expiresIn" parameter, as the payload already contains an "exp" property

I am having trouble generating an expired JWT token for testing purposes and need some guidance on how to approach it. How do you handle expiration times in unit tests? This is what I have attempted so far : it('should return a new token if expired& ...

Exploring Angular's Implementation of D3 Force Simulation

Looking to incorporate a d3 force simulation in my Angular app. I have a run method that initializes and sets simulation options, as well as a ticked method that updates the simulation on each tick. However, I've encountered a few problems with this s ...

Angular2 - Leveraging data to dynamically control radio buttons

I am looking to implement radio buttons in a form using Angular 2 with a data-driven approach. In my component, I have set up a form as follows: import { Component } from '@angular/core'; import {FormControl, FormGroup, Validators} from '@a ...

Best Practices for Variable Initialization in Stencil.js

Having just started working with Stencil, I find myself curious about the best practice for initializing variables. In my assessment, there seem to be three potential approaches: 1) @State() private page: Boolean = true; 2) constructor() { this.p ...

Use Typescript in combination with React/Redux to showcase a dynamic table on the

Looking to create a React TypeScript Redux application that showcases a table using an API endpoint provided at https://example.com/users The goal is to construct a table with 4 columns: Name, Email, City, and Company, utilizing the API response to popula ...

Enabling cookie communication between NestJS server and Next.js frontend

I seem to be encountering challenges when trying to set cookies from a NestJS backend into my Next.js app. My NestJS application is running on port 3001 and here is my bootstrap setup: async function bootstrap() { const app = await NestFactory.create(Ap ...

What is the process of registering custom pipes in Angular 17?

Recently, I developed a custom Pipe and usually I would register it in app.module.ts. However, with Angular 17, we no longer have that file. Can someone please guide me on how to register it now? Thanks in advance. I attempted to import it into the import ...