System is not defined with Router Parameter - Angular 2 - node.js

I am trying to implement routing with id parameter on the url such as localhost:1000/register/id
Using that path will always trigger system is not defined while other urls without parameters are working fine. I even tried following the guide from angular.io's routing format doesn't seems to fix the problem. What am I missing in my code?
app.routing.ts
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { RegisterComponent } from './registration/register.component';
import { CodeComponent } from './registration/code.component';
const appRoutes: Routes = [
{
path: 'register/:id',
component: RegisterComponent
},
{
path: '',
component: CodeComponent
}
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import { FormsModule } from '#angular/forms';
import { routing } from './app.routing';
import { AppComponent } from './app.component';
import { CodeComponent } from './registration/code.component';
import { RegisterComponent } from './registration/register.component';
#NgModule({
imports: [BrowserModule, HttpModule, FormsModule, routing],
declarations: [AppComponent, CodeComponent, RegisterComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
server.js
var express = require('express'),
app = express(),
mongoose = require('mongoose'),
bodyParser = require('body-parser'),
path = require('path'),
passport = require('passport'),
session = require('express-session'),
port = process.env.PORT || 1000;
db = require('./config/db');
mongoose.Promise = global.Promise;
mongoose.connect(db.url);
app.use(session({
secret: 'test',
saveUninitialized: true,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
require('./config/passport')(passport);
require('./routes/main')(app, passport);
app.use(express.static(path.join(__dirname)));
app.use('/node_modules', express.static(path.join(__dirname+ '/node_modules')));
console.log(path.join(__dirname+ '/node_modules'))
app.all('/*', function (req, res, next) {
res.sendFile('/view/index.html', { root: __dirname });
});
app.listen(port);
console.log('Magic happens on port ' + port);
UPDATE:
By using this.router.navigate(['/register', '1']); works perfectly, but by typing on the url localhost:1000/register/1 is not working
From the picture above, there is mouse hover showing the url to be
localhost:1000/register/node_modules/core-js....
- I think there is something I've missed in my server NodeJS side.
I've also added
app.use('/node_modules', express.static(__dirname + '/node_modules'));
But no changes
Note:
Server side (NodeJS,Express)

Related

Angular Universal Server Side Rendering (SSR) res.render not loading

I am trying to add SSR to my web site but the content is not loaded. I am using Angular Universal, I followed this guide for the initial configuration. http://localhost:4200/ it is not finishing loading and no errors been shown. http://localhost:4200/index.html is returning a empty view.
The build process successfully.
server.ts
import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '#nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
const path = require('path');
const fs = require('fs');
const domino = require('domino');
const templateA = fs.readFileSync(path.join('dist/web/browser', 'index.html')).toString();
const win = domino.createWindow(templateA);
global['window'] = win;
global['document'] = win.document;
// Express server
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/web/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index.html';
// 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, res) => {
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';
tsconfig.server.json
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "./out-tsc/server",
"target": "es2016",
"types": [
"node"
],
"module": "commonjs"
},
"files": [
"src/main.server.ts",
"server.ts"
],
"angularCompilerOptions": {
"entryModule": "./src/app/app.server.module#AppServerModule"
}
}
I found a solución.
I followed this steps to realize what was wrong:
Comment all imports and routings from app.module.ts, I just leve the app.component.html with a simple tag just to show something. In this step the view start loading.
Add module per module and see where stops loading.
Where stops I comment line per line to see where is the mistake.
The main mistakes that I found was the order of the routing imports on app.module.ts and sub-modules,
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
FormsModule,
ReactiveFormsModule,
BrowserAnimationsModule,
HttpClientModule,
AppRoutingModule, // <-- here
],
providers: [{ provide: HTTP_INTERCEPTORS, useClass: RequestInterceptorService, multi: true }],
bootstrap: [AppComponent]
})
export class AppModule {}
another was that in some constructor components I was doing an api call but fails because the authentication. So I need to add a validation for only do it if is a platform browser:
constructor(#Inject(PLATFORM_ID) private platformId: Object) {
if (isPlatformBrowser(this.platformId)) {
// api call
}
}
Fortunately my project it isn't very big yet.

Error: ENOENT: no such file or directory, open 'dist/index.html'

So, I've been trying for days to get a angular universal app running but I keep getting this issue when I try to run the server like
npm run dev:ssr
I have set my server.ts file as in the below link
https://github.com/Angular-RU/angular-universal-starter/blob/master/server.ts
My server.ts file is as below
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';
// ssr DOM
const domino = require('domino');
const fs = require('fs');
const path = require('path');
// index from browser build!
const template = fs.readFileSync(path.join('.', 'dist', 'index.html')).toString();
// for mock global window by domino
const win = domino.createWindow(template);
// from server build
const files = fs.readdirSync(`${process.cwd()}/dist-server`);
// mock
global['window'] = win;
// not implemented property and functions
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});
// mock documnet
global['document'] = win.document;
// othres mock
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;
// The Express app is exported so that it can be used by serverless Functions.
export function app() {
const server = express();
const distFolder = join(process.cwd(), 'dist');
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, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
return server;
}
function run() {
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';
my 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 {}
I am using Angular 9 and at a stage where I am thinking of dropping the idea of using angular universal at all. Seems it its way too unstable to be used at the moment.
Contents of dist folder:
Does anyone here have a solution to this?
You incorrectly set the distFolder variable. The distFolder from server.ts must point to the files containing the client side app, which is dist\YourProjectName\browser in your app. Note that this configured in angular.json file.
To correct your error, try changing the distFolder path in your server.ts
const distFolder = join(process.cwd(), 'dist','YourProjectName', 'browser');

Express-sessions creating new session on every request

I have an express backend that uses express-sessions. I have an angular front-end that is unconnected to the backend. Everytime a my frontend makes a request express-sessions creates a new session. I cant figure out why. I think the issue might be angular not sending the cookie back. I dont see any cookies in req headers in the chrome network tab. I dont know why angular would be doing this or if its even the problem. Any help would be much appreciated!Below is all relevant code
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {NgbModule} from '#ng-bootstrap/ng-bootstrap';
import {HttpClientModule, HTTP_INTERCEPTORS} from '#angular/common/http';
import {FormsModule} from '#angular/forms';
import { NavbarComponent } from './navbar/navbar.component';
import { SignUpComponent } from './sign-up/sign-up.component';
import { LogInComponent } from './log-in/log-in.component';
import { WithCredentialsInterceptorService } from './with-credentials-interceptor.service';
#NgModule({
declarations: [
AppComponent,
NavbarComponent,
SignUpComponent,
LogInComponent
],
imports: [
BrowserModule,
AppRoutingModule,
NgbModule,
FormsModule,
HttpClientModule
],
providers: [{provide : HTTP_INTERCEPTORS, useClass : WithCredentialsInterceptorService,
multi : true}],
bootstrap: [AppComponent]
})
export class AppModule { }
angular interceptor
import { Injectable } from '#angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '#angular/common/http';
#Injectable()
export class WithCredentialsInterceptorService implements HttpInterceptor{
intercept(req : HttpRequest<any>, next : HttpHandler){
let modifiedReq = req.clone({headers : req.headers.set('withCredentials', 'true')});
console.log(req.headers.get('cookie'));
return next.handle(modifiedReq);
}
constructor() { }
}
app.js
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');
const corsOptions = {
credentials : true
};
const session = require('express-session');
const mongoDbStore = require('connect-mongodb-session')(session);
const store = new mongoDbStore({
uri : 'mongodb+srv://Shlomo:Shizam11192#cluster0-32bfg.mongodb.net/test?retryWrites=true&w=majority',
databaseName : 'test',
collection : 'sessions'
},error=>{
if(error){
console.log(error);
}
});
const authRoutes = require('./routes/authRoutes');
app.options('*', cors(corsOptions));
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(session({
secret : 'You are doing great Shlo!!!',
resave : false,
saveUninitialized : true,
cookie : {
maxAge : 3600000,
secure : false,
httpOnly : false
}
}));
app.use(authRoutes);
mongoose.connect('mongodb+srv://#cluster0-32bfg.mongodb.net/test?
retryWrites=true&w=majority')
.then(()=>{console.log('mongoose connected!')});
app.listen(process.env.PORT || 3000, ()=>{
console.log('Listening!!! Keep it up Shlo!!!');
});
auth routes
router.get('/', (req,res,next) =>{console.log(req.session.id);res.json({message :
'whatever'})});
˚
in the interceptor the code should be
req.clone({withCredentials : true});
for some reason the headers.set doesnt work

How do I use nunjucks template in nestjs framework?

How can I use nunjucks template under NestExpressApplication in right way?
For those who would want to use Nunjucks templating engine with NestJS framework and found this question, here is a minimal example:
import { NestFactory } from '#nestjs/core';
import { NestExpressApplication } from '#nestjs/platform-express';
import * as nunjucks from 'nunjucks';
import * as path from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
const express = app.getHttpAdapter().getInstance();
const assets = path.join(__dirname, '..', 'assets'); // Directory with static HTML/CSS/JS/other files
const views = path.join(__dirname, '..', 'views'); // Directory with *.njk templates
nunjucks.configure(views, { express });
app.useStaticAssets(assets);
app.setBaseViewsDir(views);
app.setViewEngine('njk');
await app.listen(3000);
}
bootstrap();
import { join } from "path";
import { NestFactory } from "#nestjs/core";
import { NestExpressApplication } from "#nestjs/platform-express";
import * as nunjucks from "nunjucks";
import * as helmet from "helmet";
import { ApplicationModule } from "./app.module";
async function bootstrap() {
let options: any = {};
if (process.env.NODE_ENV === "product") options.logger = false;
const app = await NestFactory.create<NestExpressApplication>(
ApplicationModule,
options
);
app.use(helmet());
// app.useGlobalPipes(
// new ValidationPipe({
// whitelist: true,
// validationError: { target: false, value: false },
// }),
// );
app.useStaticAssets(join(__dirname, "..", "public"), { prefix: "/static/" });
const environment = nunjucks.configure(
[
join(__dirname, "..", "template"),
join(__dirname, ".", "system_template")
],
{
autoescape: true,
throwOnUndefined: false,
trimBlocks: false,
lstripBlocks: false,
watch: true,
noCache: process.env.NODE_ENV === "local" ? true : false,
express: app
}
);
app.engine("njk", environment.render);
app.setViewEngine("njk");
app.set("view cache", true);
await app.listen(process.env.APP_PORT);
}
bootstrap();

Angular 4 Server Side Rendering ngx-bootstrap carousel makes response hang

So I'm trying to implement server side rendering on my angular 4 website and I think I'm pretty close. I have gotten all routes to render server side except for 1 specific route and the default route. The routes that do not work are /home, /anythingthatisntdefined, and (no route at all loads, but does not server side render the home page).
So the no route, just isn't getting picked up by my catch all route... the anything that isn't defined I'm assuming the server is not correctly processing the default route... and the /home route not loading, just doesn't make sense to me. Any tips?
Here is my server.ts
import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { platformServer, renderModuleFactory } from '#angular/platform-server';
import { enableProdMode } from '#angular/core';
import { AppServerModuleNgFactory } from '../dist/ngfactory/src/app/app.server.module.ngfactory';
import * as express from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';
const PORT = 4000;
enableProdMode();
const app = express();
let template = readFileSync(join(__dirname, '..', 'dist', 'index.html')).toString();
app.engine('html', (_, options, callback) => {
console.log('url: ', options.req.url);
const opts = { document: template, url: options.req.url };
renderModuleFactory(AppServerModuleNgFactory, opts)
.then(html => callback(null, html));
});
app.set('view engine', 'html');
app.set('views', 'src')
app.use(express.static(join(__dirname, '..', 'dist')));
app.get('*', (req, res) => {
console.log('caught by *');
res.render('../dist/index.html', {
req: req,
res: res
});
});
app.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}!`);
});
Here is my router
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { ServicesComponent } from './services/services.component';
import { ResourcesComponent } from './resources/resources.component';
import { ChurchesComponent } from './churches/churches.component';
import { GetAQuoteComponent } from './get-a-quote/get-a-quote.component';
const routes: Routes = [
{
path: 'home',
component: HomeComponent
},
{
path: 'services',
component: ServicesComponent
},
{
path: 'resources',
component: ResourcesComponent
},
{
path: 'about',
component: AboutComponent
},
{
path: 'churches',
component: ChurchesComponent
},
{
path: 'get-a-quote',
component: GetAQuoteComponent
},
{
path: '**',
component: HomeComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Good news, I figured out why the one route/ random routes weren't loading. The ngx-bootstrap carousel (which I had on my home route) has an interval that needs to be disabled server side. Otherwise the route will hang forever and never load.
Reference: https://github.com/valor-software/ngx-bootstrap/issues/1353
And last, the fact of the no route not working was because of my static assets route which was intercepting the request before my express.get was.

Resources