I have implemented Angular Universal for Angular 5. Everything has compiled well enough. The only places where I see the universal work ( html with content in view source) is in static pages i.e where no data is fetched from the server. Views having data fetched from resolve or any other means is not shown in the view source of the page. I am not quite sure what I am missing. Can you please help.
Below is the screen shot of the view source of page having data from server.
Can anyone look into this issue. Have been stuck in this for past week. No results.
Below are my files .
1. angular-cli.json
{
"$schema":"./node_modules/@angular/cli/lib/config/schema.json",
"project":{
"name":"project"
},
"apps":[
{
"root":"src",
"outDir":"dist/browser",
"assets":[
"assets",
"favicon.ico"
],
"index":"index.html",
"main":"main.ts",
"polyfills":"polyfills.ts",
"test":"test.ts",
"tsconfig":"tsconfig.app.json",
"testTsconfig":"tsconfig.spec.json",
"prefix":"app",
"styles":[
],
"scripts":[
],
"environmentSource":"environments/environment.ts",
"environments":{
"dev":"environments/environment.ts",
"stag":"environments/environment.stag.ts",
"prod":"environments/environment.prod.ts"
}
},
{
"platform":"server",
"root":"src",
"outDir":"dist/server",
"assets":[
"assets",
"favicon.ico"
],
"index":"index.html",
"main":"main.server.ts",
"test":"test.ts",
"tsconfig":"tsconfig.server.json",
"testTsconfig":"tsconfig.spec.json",
"prefix":"app",
"styles":[
"styles.css"
],
"scripts":[
],
"environmentSource":"environments/environment.ts",
"environments":{
"dev":"environments/environment.ts",
"stag":"environments/environment.stag.ts",
"prod":"environments/environment.prod.ts"
}
}
]
}
2. server.ts
import "zone.js/dist/zone-node";
import "reflect-metadata";
import {
renderModuleFactory
} from "@angular/platform-server";
import {
enableProdMode
} from "@angular/core";
import * as express from "express";
import {
join
} from "path";
import {
readFileSync
} from "fs";
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), "dist");
// Our index.html we'll use as our template
const template = readFileSync(
join(DIST_FOLDER, "browser", "index.html")
).toString();
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {
AppServerModuleNgFactory,
LAZY_MODULE_MAP
} = require("./dist/server/main.bundle");
// Express Engine
import {
ngExpressEngine
} from "@nguniversal/express-engine";
// Import module map for lazy loading
import {
provideModuleMap
} from "@nguniversal/module-map-ngfactory-loader";
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine(
"html",
ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [provideModuleMap(LAZY_MODULE_MAP)]
})
);
app.set("view engine", "html");
app.set("views", join(DIST_FOLDER, "browser"));
/* - Example Express Rest API endpoints -
app.get('/api/**', (req, res) => { });
*/
// Server static files from /browser
app.get(
"*.*",
express.static(join(DIST_FOLDER, "browser"), {
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}`);
});
3. prerender.ts
// Load zone.js for the server.
import "zone.js/dist/zone-node";
import "reflect-metadata";
import {
readFileSync,
writeFileSync,
existsSync,
mkdirSync
} from "fs";
import {
join
} from "path";
import {
chdir
} from "process";
import {
enableProdMode
} from "@angular/core";
const domino = require("domino");
const fs = require("fs");
const path = require("path");
const templateA = fs
.readFileSync(path.join("..", "dist/browser", "index.html"))
.toString();
const win = domino.createWindow(templateA);
win.Object = Object;
win.Math = Math;
global["window"] = win;
global["document"] = win.document;
global["branch"] = null;
global["object"] = win.object;
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express Engine
import {
ngExpressEngine
} from "@nguniversal/express-engine";
// Import module map for lazy loading
import {
provideModuleMap
} from "@nguniversal/module-map-ngfactory-loader";
import {
renderModuleFactory
} from "@angular/platform-server";
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {
AppServerModuleNgFactory,
LAZY_MODULE_MAP
} = require("./dist/server/main.bundle");
// Get route paths to prerender only static pages
const PATHS = require("./static.paths");
const BROWSER_FOLDER = join(process.cwd(), "browser");
// Load the index.html file containing referances to your application bundle.
const index = readFileSync(join("browser", "index.html"), "utf8");
let prom = Promise.resolve();
// Iterate each route path
PATHS.forEach(function(route) {
// Changes current directory to ./dist/browser
chdir(BROWSER_FOLDER);
// Creates new directories (if not exists) and changes current directory for the nested one
route
.split("/")
.filter(val => val !== "")
.forEach(function(dir) {
if(!existsSync(dir)) {
mkdirSync(dir);
}
chdir(dir);
});
// Writes rendered HTML to index.html, replacing the file if it already exists.
prom = prom
.then(_ =>
renderModuleFactory(AppServerModuleNgFactory, {
document: index,
url: route,
extraProviders: [
[provideModuleMap(LAZY_MODULE_MAP)]
]
})
)
.then(html =>
writeFileSync(join(BROWSER_FOLDER, route, "index.html"), html)
);
});
4. package.json
{
"name":"sirved",
"version":"0.0.0",
"license":"MIT",
"scripts":{
"ng":"ng",
"start":"ng serve",
"build":"ng build --prod",
"test":"ng test",
"lint":"ng lint",
"e2e":"ng e2e",
"build:client-and-server-bundles":"ng build --prod && ng build --prod --app 1 --output-hashing=false",
"build:static":"npm run build:client-and-server-bundles && npm run webpack:server && npm run generate:static",
"build:dynamic":"npm run build:client-and-server-bundles && npm run webpack:server",
"generate:static":"cd dist && node prerender",
"webpack:server":"webpack --config webpack.server.config.js --progress --colors",
"serve:static":"cd dist/browser && http-server",
"serve:dynamic":"node dist/server"
},
"private":true,
"dependencies":{
"@agm/core":"^1.0.0-beta.3",
"@angular/animations":"^5.2.11",
"@angular/common":"^5.2.0",
"@angular/compiler":"^5.2.0",
"@angular/core":"^5.2.0",
"@angular/forms":"^5.2.0",
"@angular/http":"^5.2.0",
"@angular/platform-browser":"^5.2.0",
"@angular/platform-browser-dynamic":"^5.2.0",
"@angular/platform-server":"^5.2.0",
"@angular/router":"^5.2.0",
"@nguniversal/express-engine":"^5.0.0-beta.1",
"@nguniversal/module-map-ngfactory-loader":"^5.0.0-beta.1",
"@types/jquery":"^3.3.4",
"core-js":"^2.4.1",
"zone.js":"^0.8.19"
},
"devDependencies":{
"@angular/cli":"~1.7.4",
"@angular/compiler-cli":"^5.2.0",
"@angular/language-service":"^5.2.0",
"@types/googlemaps":"^3.30.11",
"@types/jasmine":"~2.8.3",
"@types/jasminewd2":"~2.0.2",
"@types/node":"~6.0.60",
"codelyzer":"^4.0.1",
"jasmine-core":"~2.8.0",
"jasmine-spec-reporter":"~4.2.1",
"karma":"~2.0.0",
"karma-chrome-launcher":"~2.2.0",
"karma-coverage-istanbul-reporter":"^1.2.1",
"karma-jasmine":"~1.1.0",
"karma-jasmine-html-reporter":"^0.2.2",
"protractor":"~5.1.2",
"ts-node":"~4.1.0",
"tslint":"~5.9.1",
"typescript":"~2.5.3",
"ts-loader":"^2.3.7"
}
}
I have done exactly same as the angular universal starter project is done but I am not getting the required results. Could anyone please look into this!
