2

I have small application that have only one module, the application is working fine but it's not rendering the component on page source.
The issue is when I'm starting the application with npm run dev:ssr everything is fine ( on page source you have the component that is loaded after the tag (home-component in my situation) you can see the meta tags so everything seems to works fine), on npm run serve:ssr is still the same, everything looks fine, seems like everything works.
But the problem is when I publish the application, on the server the home-component is missing after the tag.

Here is an image of npm run dev:ssr page source: enter image description here

Here is an image of the page source of published version: enter image description here

Here is the tsconfig.server.json

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "outDir": "./out-tsc/server",
    "target": "es2019",
    "types": [
      "node"
    ]
  },
  "files": [
    "src/main.server.ts",
    "server.ts"
  ],
  "angularCompilerOptions": {
    "entryModule": "./src/app/app.server.module#AppServerModule"
  }
}

Here is my server.ts file:

    import 'zone.js/dist/zone-node';

    import { ngExpressEngine } from '@nguniversal/express-engine';
    import * as express from 'express';
    import { join } from 'path';

    import { AppServerModule } from './src/main.server';
    import { APP_BASE_HREF } from '@angular/common';
    import { existsSync } from 'fs';

    // The Express app is exported so that it can be used by serverless Functions.
    export function app(): express.Express {
      const server = express();
      const distFolder = join(process.cwd(), 'dist/browser');
      const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

      // Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
      server.engine('html', ngExpressEngine({
        bootstrap: AppServerModule,
      }));

      server.set('view engine', 'html');
      server.set('views', distFolder);

      // Example Express Rest API endpoints
      // server.get('/api/**', (req, res) => { });
      // Serve static files from /browser
      server.get('*.*', express.static(distFolder, {
        maxAge: '1y'
      }));

      // All regular routes use the Universal engine
       server.get('*', (req: express.Request, res: express.Response) => {
        res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
      });

      return server;
    }

    function run(): void {
      const port = process.env.PORT || 4000;

      // Start up the Node server
      const server = app();
      server.listen(port, () => {
        console.log(`Node Express server listening on http://localhost:${port}`);
      });
    }

    // Webpack will replace 'require' with '__webpack_require__'
    // '__non_webpack_require__' is a proxy to Node 'require'
    // The below code is to ensure that the server is run only when not requiring the bundle.
    declare const __non_webpack_require__: NodeRequire;
    const mainModule = __non_webpack_require__.main;
    const moduleFilename = mainModule && mainModule.filename || '';
    if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
      run();
    }

    export * from './src/main.server';


<!-- end snippet -->

**Here is main.serve.ts file:**

    import '@angular/platform-server/init';

    import { enableProdMode } from '@angular/core';

    import { environment } from './environments/environment';

    if (environment.production) {
      enableProdMode();
    }

    export { AppServerModule } from './app/app.server.module';
    export { renderModule, renderModuleFactory } from '@angular/platform-server';

    export { AppServerModule } from './app/app.server.module';
    export { renderModule, renderModuleFactory } from '@angular/platform-server';
**Here is app.server.module.ts file:** <!-- begin snippet: js hide: false console: true babel: false --> <!-- language: lang-js --> import { NgModule } from '@angular/core'; import { ServerModule } from '@angular/platform-server'; import { AppModule } from './app.module'; import { AppComponent } from './app.component'; @NgModule({ imports: [ AppModule, ServerModule, ], bootstrap: [AppComponent], }) export class AppServerModule {}

And here is app.server.module.ts file:

import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';

import { AppModule } from './app.module';
import { AppComponent } from './app.component';

@NgModule({
  imports: [
    AppModule,
    ServerModule,
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {}

Here is app.module.ts file:

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'serverApp' }),
    HttpClientModule,
    RouterModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Here is my app-routing.module.ts file:

 import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';

    const routes: Routes = [
      {
        path        : '',
        redirectTo  : 'home',
        pathMatch   : 'full',
      },
      {
        path         : 'home',
        loadChildren : () => import('./home/home.module').then(m => m.HomeModule)  
      },
      {
        path        : '**',
        redirectTo  : '',
        pathMatch   : 'full',
      },
    ];

    @NgModule({
      imports: [
        RouterModule.forRoot(routes)
      ],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }

EDIT: The solution I currently found is to add module: commonjs in tsconfig.server.json file, the application is kinda slower than usual but it's doing it's job. If someone has better solution feel free to leave an answer.

Bobe
  • 46
  • 9
  • Are you using the angular service-worker/pwa? – Pieterjan Oct 12 '21 at 14:54
  • @Pieterjan No, I'm not using anything, I just created new application added @nguniversal/express-engine, added one module and make it lazy load, I've added meta tags in the component in that lazy loaded module and that was it, I didn't work anything else or added any other packages into the application. – Bobe Oct 13 '21 at 14:13
  • Did you find any solution? Same issue on my side. – Shakir Feb 17 '22 at 08:20
  • The solution is in the end of the post I've posted (in the Edit part). I've added module: commonjs in tsconfig.server.json file, the application is slower than usual but it's doing it's job. @Shakir – Bobe Feb 18 '22 at 09:19
  • can you share code of `tsconfig.server.json` – Shakir Feb 18 '22 at 09:22
  • Here you go @Shakir `{ "extends": "./tsconfig.app.json", "compilerOptions": { "outDir": "./out-tsc/server", "target": "es2016", "module" : "commonjs", "types": [ "node" ] }, "files": [ "src/main.server.ts", "server.ts" ], "angularCompilerOptions": { "entryModule": "./src/app/app.server.module#AppServerModule" } }` – Bobe Mar 02 '22 at 09:26
  • hi @Bobe I added commonjs module as you said but it still showing empty in my case. Could please share your whole project ? – Lê Thọ Jan 11 '23 at 03:39
  • Hi @LêThọ since I have contract I'm not able to share the code, on my side locally it was working, published version was not rendering the meta tags, I had only empty router-outlet, I guess I have some issue in the configurations, didn't try to change anything since it has so much work on it, it will be like this until I finish it... Try creating new app and add only angular universal with the default options, if it works like that try adding one by one component ( or exclude all modules for now and try it ) maybe some of the modules are bugging the universal if it's not the configs... – Bobe Feb 15 '23 at 23:33

1 Answers1

-1

You are missing the initialNavigation property which is required by Angular Universal.

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    initialNavigation: 'enabled'
})],
  exports: [RouterModule],
})
export class AppRoutingModule {}
Lukasz Gawrys
  • 1,234
  • 2
  • 8
  • If I add initialNavigation: 'enabled' it's not opening my deployed application at all, it just have spinner on the tab that is loading the app but it's not opening at all. – Bobe Oct 09 '21 at 14:50
  • 1
    Also @LukaszGawrys, initialNavigation: 'enabled' is 1:1 replaceable with enabledBlocking after Angular v11 [link](https://angular.io/api/router/InitialNavigation) – Bobe Oct 21 '21 at 15:04