2
votes

Was trying to convert simple angular application to universal supported application.

Did all the required changes like added check on all DOM elements such as window, navigator, settimeout, etc.

Once I run the command npm run build:ssr && npm run serve:ssr it will build the bundle successfully and showing in terminal

Node Express server listening on http://localhost:4000

But on loading in browser on port 4000, It keep loading for ages.

Tried adding console at almost every step which seems to be working fine.

Server.ts

// These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';

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

import * as express from 'express';
import { join } from 'path';

// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();

// Express server
const app = express();

global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Event'] = null;

const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main');

// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

app.engine('html', ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [
        provideModuleMap(LAZY_MODULE_MAP)
    ]
}));

app.set('view engine', 'html');
app.set('views', DIST_FOLDER);

// Server static files from /assets
app.get('*.*', express.static(DIST_FOLDER, {
  maxAge: '1y'
}));

// All regular routes use the Universal engine
app.get('*', (req, res) => {
    res.render('index', { req });
});

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

webpack.server.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
    entry: { server: './server.ts' },
    resolve: {
        extensions: ['.js', '.ts'],
        mainFields: ['main']
    },
    target: 'node',
    mode: 'none',
    // this makes sure we include node_modules and other 3rd party libraries
    externals: [/node_modules/],
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    module: {
        rules: [{ test: /\.ts$/, loader: 'ts-loader' }, {
            test: /\.(ts|js)$/,
            loader: 'regexp-replace-loader',
            options: {
                match: {
                    pattern: '\\[(Mouse|Keyboard)Event\\]',
                    flags: 'g'
                },
                replaceWith: '[]',

            }
        }]
    },
    plugins: [
        // Temporary Fix for issue: https://github.com/angular/angular/issues/11580
        // for 'WARNING Critical dependency: the request of a dependency is an expression'
        new webpack.ContextReplacementPlugin(
            /(.+)?angular(\\|\/)core(.+)?/,
            path.join(__dirname, 'src'), // location of your src
            {} // a map of your routes
        ),
        new webpack.ContextReplacementPlugin(
            /(.+)?express(\\|\/)(.+)?/,
            path.join(__dirname, 'src'), {}
        )
    ]
};

I am using angular v6.1.0.

Stuck from so long can anyone please help me out.

PS: Tried on fresh application/project there its working fine. so probably error is in my server.ts file.

3

3 Answers

1
votes

For me it was an issue with rxjs. I tracked it down by commenting out component by component until i found the problem one. I ended up finding out that rxjs's interval was causing the issue. Hope that helps!

0
votes

In my case it looks like some pages loading and other stuck with blank screen. I found out that if I do something not awaited on Server Side while page is being constracted, page got stuck. For example it was setTimeout in ngOnInit. (looks like Server don't know what to do with - it's logical). When I move setTimeout to page's controls events (like (change)) - page start works correctly!

0
votes

A good way to debug this is to go to your app.component.html and your app.component.ts. Comment out every line loading another component... then work your way internally to each component module until you figure out what was causing it. I particularly had some issues with the new @angular/fire module, and had to comment out my way through my documents to find it.

Also, have items that you use | async multiple times in your template, make sure to use shareReplay() like this:

    this.user$ = this.afAuth.authState
      .pipe(
        shareReplay(),
        switchMap(user => {

As an example...