Application always serves '/' to express app - node.js

Have an angular 7 application and have implemented angular universal using node and express, and then deployed to firebase.
Having an issue when trying to load pages other than the root (/), which causes the server to return the html of the root (/) rather than the page the user requests.
Not sure from where the issue is originating (Angular, Angular Universal or Firebase).
This is my index.ts:
import * as functions from 'firebase-functions';
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 {readFileSync} from 'fs';
enableProdMode();
const app = express();
const indexHtml = readFileSync(__dirname + '/index-server.html', 'utf-8').toString();
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./main');
import {provideModuleMap} from '#nguniversal/module-map-ngfactory-loader';
app.engine('html', (_, options, callback) => {
// Always '/' (root path)
console.log('OPTIONS.REQ.URL', options.req.url);
renderModuleFactory(AppServerModuleNgFactory, {
// My index-server.html
document: indexHtml,
url: options.req.url,
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP)
]
}).then(html => {
callback(null, html);
});
});
app.set('view engine', 'html');
app.set('views', __dirname);
app.get('*.*', express.static(__dirname + '/dist', {
maxAge: '1y'
}));
app.get('*', (req, res) => {
res.render(__dirname + '/index-server.html', {req});
});
exports.ssrApp = functions.https.onRequest(app);
This is my app-routing.module.ts:
import {RouterModule, Routes} from '#angular/router';
import {NgModule} from '#angular/core';
import {HomePageComponent} from './home-page/home-page.component';
import {ToursComponent} from './tours/tours.component';
import {MaltaComponent} from './malta/malta.component';
import {AboutComponent} from './about/about.component';
import {ContactComponent} from './contact/contact.component';
import {TourComponent} from './tours/tour/tour.component';
import {ErrorComponent} from './error/error.component';
import {BlogComponent} from './blog/blog.component';
import {BlogPageComponent} from './blog/blog-page/blog-page.component';
import {PageResolver} from './services/pages/page-resolver.service';
const AppRoutes: Routes = [
{
path: 'home',
component: HomePageComponent,
data: {
state: 'home',
pageId: 'home'
},
resolve: {
page: PageResolver
}
},
{
path: 'tours',
component: ToursComponent,
data: {
state: 'tours',
pageId: 'tours'
},
resolve: {
page: PageResolver
}
},
{
path: 'tours/:id',
component: TourComponent,
data: {
state: 'tour'
}
},
{
path: 'blog',
component: BlogComponent,
data: {
state: 'blogs',
pageId: 'blog'
},
resolve: {
page: PageResolver
}
},
{
path: 'blog/:id',
component: BlogPageComponent,
data: {
state: 'blog'
}
},
{
path: 'malta',
component: MaltaComponent,
data: {
state: 'malta',
pageId: 'malta'
},
resolve: {
page: PageResolver
}
},
{
path: 'about',
component: AboutComponent,
data: {
state: 'about',
pageId: 'about'
},
resolve: {
page: PageResolver
}
},
{
path: 'contact',
component: ContactComponent,
data: {
state: 'contact',
pageId: 'contact'
},
resolve: {
page: PageResolver
}
},
{
path: 'something-went-wrong',
component: ErrorComponent,
data: {
state: 'error',
pageId: 'error'
}
},
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
},
{
path: '**',
redirectTo: '/something-went-wrong'
}
];
#NgModule({
imports: [
RouterModule.forRoot(AppRoutes, {
useHash: true,
scrollPositionRestoration: 'enabled',
initialNavigation: 'enabled'
})
],
exports: [RouterModule]
})
export class AppRoutingModule {
}
This is my firebase.json:
{
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"function": "ssrApp"
}
]
},
"functions": {
"predeploy": "npm --prefix \"$RESOURCE_DIR\" run build"
}
}
Would appreciate any help with this issue!

The issue is solved after removing useHash: true from the app-routing.module.ts.
Thanks to yeya for helping get to the solution.

Your issue is related to Browser URL styles
Based on this answer: Try change the rewrites from "function": "ssrApp" to "destination": "/index-server.html"
The requestindex-server.html will trigger the function.

Related

firebase authentication freezing edge and chrome browser

so just new with angular and firebase, i am trying to create authentication, the code is not throwing any error but when i try accessing it in the browser it freezes, i can't even click on anything. below are the authentication code.
import { Injectable, NgZone } from '#angular/core';
import { AngularFireAuth } from '#angular/fire/compat/auth';
import { AngularFirestore, AngularFirestoreDocument } from '#angular/fire/compat/firestore';
import { Router } from '#angular/router';
import * as auth from 'firebase/auth';
import { UserService } from '../users/user.service';
//import { User } from '../../models/users/user';
import { DataService } from '../database/data.service';
#Injectable({
providedIn: 'root'
})
export class AuthService {
loggedin = false;
// user$: Observable<any> | undefined;
// user: any;
userData: any;
constructor(
public firestore: AngularFirestore,
public fireauth: AngularFireAuth,
public userservice: UserService,
public router: Router,
public ngZone: NgZone,
public dataService: DataService,
) {
// this.fireauth.authState.subscribe((user) => {
// if (user){
// this.userData = user;
// this.dataService.addData('users', this.userData); // you can json stringify this if you want
// localStorage.setItem('user', JSON.stringify(this.userData));
// JSON.parse(localStorage.getItem('user') || '{}');
// }
// else {
// this.dataService.addData('users', null);
// localStorage.setItem('user', '');
// JSON.parse(localStorage.getItem('user') || '{}');
// }
// });
//this.loggedin = !!localStorage.getItem('user');
}
// Sign in with email/password
async loginUser(email: string, password: string) {
try {
const result = await this.fireauth
.signInWithEmailAndPassword(email, password);
this.SetUserData(result.user);
this.fireauth.authState.subscribe((user_1) => {
if (user_1) {
this.router.navigate(['dashboard']);
}
});
} catch (error) {
window.alert(error);
}
}
i have comment out eveery code int he login components but i still get this issue,
app.modules
#NgModule({
declarations: [
AppComponent,
LoginComponent,
OrderListComponent,
DashboardComponent,
ProfileGeneralComponent,
MenuComponent,
ProfileMenuComponent,
ProfileServicesComponent,
Dashboard2Component,
LineChartComponent,
],
imports: [
BrowserModule,
RouterModule,
FormsModule,
ReactiveFormsModule,
AppRoutingModule,
IonicStorageModule.forRoot(),
IonicModule.forRoot({
mode: 'ios'
}),
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
AngularFirestoreModule,
AngularFireStorageModule,
AngularFireDatabaseModule,
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAuth(() => getAuth()),
provideFirestore(() => getFirestore()),
provideStorage(() => getStorage()),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module
const routes: Routes = [
{ path: '', component: LoginComponent },
{
path: 'dashboard',
//canActivate: [AuthGuard],
component: DashboardComponent
},
{
path: 'overview-dashboard',
canActivate: [AuthGuard],
component: Dashboard2Component
},
{
path: 'profile',
canActivate: [AuthGuard],
component: ProfileGeneralComponent
},
{
path: 'profile-menu',
canActivate: [AuthGuard],
component: ProfileMenuComponent
},
{
path: 'profile-services',
canActivate: [AuthGuard],
component: ProfileServicesComponent
},
{
path: 'order-list',
canActivate: [AuthGuard],
component: OrderListComponent
},
{
path: 'login',
canActivate: [AuthGuard],
component: LoginComponent
},
{
path: 'line-chart',
canActivate: [AuthGuard],
component: LineChartComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
when i access other pages with nothing related to authentication they work.

How to reduce the number chunks using Vite?

Vite produces unreasonably small chunks (90% of all chunks are under 1KB with a few 300KB+).
Here is the full build log:
https://gist.github.com/gajus/0149233592085181331dde7076fc50b1
This is example website:
https://contra.com/p/gkOQlbLq-validating-postgre-sql-results-and-inferring-query-static-types
This is out Vite configuration:
import path from 'path';
import { default as react } from '#vitejs/plugin-react';
import { defineConfig } from 'vite';
import { default as ssr } from 'vite-plugin-ssr/plugin';
const { VITE_BASE_URL } = process.env;
export default defineConfig(({ ssrBuild }) => {
let build;
if (!ssrBuild) {
build = {
emptyOutDir: true,
manifest: true,
minify: true,
polyfillModulePreload: false,
rollupOptions: {
output: {
chunkFileNames: 'chunk-[name].[hash].js',
entryFileNames: 'entry-[name].[hash].js',
inlineDynamicImports: false,
sourcemap: true,
},
},
sourcemap: true,
};
}
return {
base: VITE_BASE_URL ?? '/static/',
build,
plugins: [
react({
babel: {
plugins: [
'babel-plugin-relay',
[
'babel-plugin-styled-components',
{
displayName: true,
fileName: false,
pure: true,
ssr: true,
},
],
],
},
}),
ssr(),
],
resolve: {
alias: {
'#': path.resolve(__dirname, './src/'),
},
},
};
});
If you try to inspect this page using Google tools, it doesn't even load – presumably because of 200 JavaScript chunks that that page needs to load.
https://search.google.com/test/mobile-friendly/result?id=ULZhtOfQfp1Gxj2wYhyCUw
How to reduce the number of chunks?

How to use TailwindCSS with NestJS?

I like using Tailwind CSS in my React and Laravel projects.
Now I've started learning NestJS and I want to use Tailwind CSS in my project, but I couldn't.
Since I couldn't find any results on Google, I'm asking you guys.
I would be grateful for any resource or your detailed answer.
The current state of my project is as follows. I don't know where I went wrong, TailwindCSS is not working.
Please note that I am just starting to learn NestJS.
main.ts
import { NestFactory } from '#nestjs/core';
import { NestExpressApplication } from '#nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useStaticAssets(join(__dirname, '..', 'public'));
app.setBaseViewsDir(join(__dirname, '..', 'views'));
app.setViewEngine('hbs');
await app.listen(3000);
console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();
app.controller.ts
import { Controller, Get, Render } from '#nestjs/common';
#Controller()
export class AppController {
#Get()
#Render('index')
root() {
return { message: 'Hello world!' };
}
}
app.module.ts
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
#Module({
imports: [],
controllers: [AppController],
providers: [],
})
export class AppModule {}
tailwind.config.js
module.exports = {
content: ['./views/*.hbs', './views/**/*.hbs'],
theme: {
extend: {},
},
plugins: [],
};
webpack-hmr.config.js
const nodeExternals = require('webpack-node-externals');
const { RunScriptWebpackPlugin } = require('run-script-webpack-plugin');
module.exports = function (options, webpack) {
return {
...options,
//entry: ['webpack/hot/poll?100', options.entry],
entry: './src/main.ts',
externals: [
nodeExternals({
allowlist: ['webpack/hot/poll?100'],
}),
],
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
{
test: /\.ts$/,
use: [{ loader: 'ts-loader' }],
},
],
},
plugins: [
...options.plugins,
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin({
paths: [/\.js$/, /\.d\.ts$/],
}),
new RunScriptWebpackPlugin({ name: options.output.filename }),
],
};
};
index.hbs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>NestJS App With TailwindCSS</title>
<link rel="stylesheet" href="/assets/css/tailwind.css">
</head>
<body>
<header class="w-full px-8 text-gray-700 bg-white flex">
<h1 class="bg-slate-200">
{{ message }}
</h1>
</header>
</body>
</html>
and script command
"start:dev": "nest build --webpack --webpackPath webpack-hmr.config.js --watch",

How to set up my routing that "pathMatch" and childRoutingModule work?

On the left-side menu I need to have the links highlighted when the user on them. Now it works but my root path 'li' of the menu is highlighted as well.
I cannot set up a child routing Module.
left-side-menu html
<ul class='side-menu'>
<li *ngFor='let item of menu' routerLinkActive='active-side-menu-item'><a routerLink='{{ item.link }}' class="menu-item-feed">{{ item.title }}</a></li>
</ul>
app.routing.module ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { FeedComponent } from './feed/feed.component';
const routes: Routes = [
{ path: '', pathMatch: 'full', component: FeedComponent },
{ path: 'shoes', pathMatch: 'full', component: FeedComponent },
{ path: 'coats', pathMatch: 'full', component: FeedComponent },
{ path: 'shirts', pathMatch: 'full', component: FeedComponent },
{ path: 'pants', pathMatch: 'full', component: FeedComponent },
{ path: 'item/:id', component: FeedComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
That's how I tried to implement my childRoutingModule but it throws the error in the console: core.js:15724 ERROR Error: Uncaught (in promise): TypeError: undefined is not a function
TypeError: undefined is not a function
at Array.map ()
app.routing.module
const routes: Routes = [
{ path: '', pathMatch: 'full', loadChildren: './feed/feed.module#FeedModule' }
];
feed-routing.module
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { FeedComponent } from './feed.component';
const routes: Routes = [
{ path: '', pathMatch: 'full', component: FeedComponent },
{ path: 'shoes', pathMatch: 'full', component: FeedComponent },
{ path: 'coats', pathMatch: 'full', component: FeedComponent },
{ path: 'shirts', pathMatch: 'full', component: FeedComponent },
{ path: 'pants', pathMatch: 'full', component: FeedComponent },
{ path: 'item/:id', component: FeedComponent },
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class FeedRoutingModule { }
I want to have a separate routing module for each gross section on the site and I need link react to the url and indicate which module is active at the moment.
I would appreciate any other hints and best practices!
To setup feature route you have to import FeedRoutingModule into the module you want to use thoose route.
Below is my example
I have app.routing.ts (Main route)
export const routes: Routes = [
{ path: "", redirectTo: "home", pathMatch: "full" },
{ path: "home", component: HomeComponent },
//{ path: "**", redirectTo: "account", pathMatch: "full" },
//lazy load feature module
{ path: "account", loadChildren: "./account/account.module#AccountModule" },
{ path: "portal", loadChildren: "./portal/portal.module#PortalModule", canActivate: [AuthGuardService] },
{ path: "**", redirectTo: "account", pathMatch: "full" },
];
and app.module.ts
#NgModule({
declarations: [],
imports: [
RouterModule.forRoot(routes)
],
providers: [],
bootstrap: []
})
export class AppModule {}
So when I define child route in my feature module I have to done the same like app.module but using RouterModule.forChild
export const accountRoutes: Routes = [
{
path: "",
component: AccountComponent,
children: [
{ path: "login", component: LoginComponent },
{ path: "register-account", component: RegisterComponent }
]
}
];
import { NgModule } from "#angular/core";
import { CommonModule } from "#angular/common";
import { FormsModule, ReactiveFormsModule } from "#angular/forms";
import { RouterModule } from "#angular/router";
import { RegisterComponent } from "./register/register.component";
import { LoginComponent } from "./login/login.component";
import { AccountComponent } from "./account/account.component";
import { accountRoutes } from "./account.routing";
#NgModule({
declarations: [],
imports: [
RouterModule.forChild(accountRoutes) // use forChild
],
exports: [],
providers: []
})
export class AccountModule {}
Your paranet component need have tag: < router-outlet>< /router-outlet> then he knows will have a child component + route;
Here a exemple where i management childRoutes.
{
path: 'utente',
component: CenterViewComponent,
children: [
YYY_ROUTE,
XXX_ROUTE
...
]
}
Hope help u!

I can not directly access an url in Angular

I have a problem with a simple application. I already have it in production, but when I access a URL directly, I get an error:
In firefox:
In chrome:
But if I access localhost:8080, it is redirected to /home correctly:
I am using the following code:
In app.routes.ts
import { RouterModule, Routes } from '#angular/router';
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';
import { HeroesComponent } from './components/heroes/heroes.component';
import { HeroeComponent } from './components/heroe/heroe.component';
import { BuscarComponent } from './components/buscar/buscar.component';
const ROUTES: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'about', component: AboutComponent },
{ path: 'heroes', component: HeroesComponent },
{ path: 'heroe/:id', component: HeroeComponent },
{ path: 'buscar/:palabra', component: BuscarComponent },
{ path: '**', pathMatch: 'full', redirectTo: 'home' }
];
export const APP_ROUTING = RouterModule.forRoot(ROUTES);
In app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { APP_ROUTING } from './app.routes';
import { HeroesService } from './servicios/heroes.service';
import { AppComponent } from './app.component';
import { NavbarComponent } from './components/shared/navbar/navbar.component';
import { HomeComponent } from './components/home/home.component';
import { AboutComponent } from './components/about/about.component';
import { HeroesComponent } from './components/heroes/heroes.component';
import { HeroeComponent } from './components/heroe/heroe.component';
import { BuscarComponent } from './components/buscar/buscar.component';
import { HeroeTarjetaComponent } from './components/heroe-tarjeta/heroe-tarjeta.component';
#NgModule({
declarations: [
AppComponent,
NavbarComponent,
HomeComponent,
AboutComponent,
HeroesComponent,
HeroeComponent,
BuscarComponent,
HeroeTarjetaComponent
],
imports: [
BrowserModule,
APP_ROUTING
],
providers: [
HeroesService
],
bootstrap: [AppComponent]
})
export class AppModule { }
I try to change { path: '**', pathMatch: 'full', redirectTo: 'home' } to { path: '', pathMatch: 'full', redirectTo: 'home' } or anything and nothing, not solve.
I tried the application with the NodeJS http-server module.

Resources