Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular routes pushed to array after creation not working in production

I've created a github repository which has a perfect example of my issue.

https://github.com/rjriel/dynamic-route-example

The important part of the code in this repo is in app.module.ts

let mainRoutes: Routes = [{
  path: "first",
  component: FirstComponent
}]

mainRoutes.push({
  path: "second",
  component: SecondComponent
})

@NgModule({
...
  imports: [
    RouterModule.forRoot(mainRoutes),

When running this code in development (ie. ng serve) both routes navigate correctly. However, when running this code in production (ie. ng serve --prod) the second route that was added through mainRoutes.push results in the following error:

ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL 
Segment: 'second'
Error: Cannot match any routes. URL Segment: 'second'
    at t.BkNc.t.noMatchError (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.selector (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at t.BkNc.t.noMatchError (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.selector (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e.error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.T14+.e._error (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at u (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at u (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at polyfills.8c1e4b56978ce6347832.bundle.js:1
    at e.invokeTask (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at Object.onInvokeTask (vendor.0828fd59ec5e6a599e72.bundle.js:1)
    at e.invokeTask (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at r.runTask (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at o (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at t.invokeTask [as invoke] (polyfills.8c1e4b56978ce6347832.bundle.js:1)
    at h (polyfills.8c1e4b56978ce6347832.bundle.js:1)

Would anybody happen to know why compiling for production would produce this error while it works completely fine in development? Or at least a better way to debug?

Edit:

The real life implementation of what I'm doing here is that I have multiple pages on a site with the same layout of information, so I created a json file that is an object where each key is the route and value is the information for the route. Then I load the json and add the routes, as shown here:

import * as PageLayouts from '../page-layouts.json'
import { MainLayoutComponent } from './main-layout/main-layout.component'

Object.keys(PageLayouts).forEach(key => {
  mainRoutes.push({
    path: key,
    component: MainLayoutComponent
  })
})

I do a console.log(mainRoutes) after the above forEach and see all the routes in the array as expected. Also for clarification, this forEach loop is done before the @NgModule declaration, as shown in the example code. This all works totally fine with JiT compilation for development, but has the issues addressed above with AoT compilation for production.

like image 659
flamebaud Avatar asked Aug 20 '17 02:08

flamebaud


People also ask

How do I enable Angular routing?

Add the AppRoutingModule link. In Angular, the best practice is to load and configure the router in a separate, top-level module. The router is dedicated to routing and imported by the root AppModule . By convention, the module class name is AppRoutingModule and it belongs in the app-routing.

What is the correct way to add a basic route in Angular?

First, add links to the two components. Assign the anchor tag that you want to add the route to the routerLink attribute. Set the value of the attribute to the component to show when a user clicks on each link. Next, update your component template to include <router-outlet> .

How many instance of the router service should a routed Angular application have?

A routed Angular application has one singleton instance of the Router service. When the browser's URL changes, that router looks for a corresponding Route from which it can determine the component to display.

How does Angular determine active routes?

Show activity on this post. You can check the current route by injecting the Location object into your controller and checking the path() , like so: class MyController { constructor(private location:Location) {} ...


1 Answers

The short answer is that when you compile for production, it uses the Ahead of Time (AOT) process instead of the Just in Time (JiT) process. That is why you are seeing different results.

You can read more about AOT here: https://angular.io/guide/aot-compiler

And this article may be helpful: http://blog.mgechev.com/2016/08/14/ahead-of-time-compilation-angular-offline-precompilation/

Just guessing here ... but is it possible that this code is not actually executing when it is compiled with the AOT compiler?

mainRoutes.push({
  path: "second",
  component: SecondComponent
})

It does not appear to be within any Angular component or service.

Could you be more explicit about what you are trying to accomplish with this code? Are you trying to load dynamic components?

like image 109
DeborahK Avatar answered Nov 15 '22 18:11

DeborahK