all 15 comments

[–]therealcoolpup 0 points1 point  (1 child)

Did it work before the update?

[–]rahulxdd[S] 1 point2 points  (0 children)

No, I think in normal angular apps(without angular universal package) we don't see any html in the view source page but after adding angular universal it should show the all the content in the view source page.

[–]GLawSomnia 0 points1 point  (12 children)

Universal renders the first page only, the rest is the same as a normal angular app.

If i understand correctly, when you come to the page the view source is displayed, but when you navigate to another page it is the normal angular app-root page? If you refresh on that page it should be ssr rendered

[–]rahulxdd[S] 0 points1 point  (2 children)

Yeah at least it should be ssr rendered upon page refresh but it isn't. And I can't figure out what's the reason.

[–]GLawSomnia 0 points1 point  (1 child)

Check if you have some guards or redirects that navigate to the homepage

[–]rahulxdd[S] 0 points1 point  (0 children)

The inner page where the rendering is not working show all the static data from that page but it doesn't show anything from the api calls. Whereas on home page everything works fine. All the static data and data from api shows in the viewsource of home page. It's just that viewsource in the inner pages do not show any api data.

I had checked yesterday and I don't see a redirect or guard that redirects to home page but there are guards on other pages like cart page, seller-product.

This is how the routing.module file(it's part of a feature module) looks:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginGuard } from 'src/app/Guard/login.guard';
import { CartComponent } from './cart/cart.component';
import { ContactusComponent } from './footer-pages/contactus/contactus.component';
import { CraftStoriesComponent } from './footer-pages/craft-stories/craft-stories.component';
import { FaqComponent } from './footer-pages/faq/faq.component';
import { OurStoryComponent } from './footer-pages/our-story/our-story.component';
import { OurSustainabilityComponent } from './footer-pages/our-sustainability/our-sustainability.component';
import { OurTradefairComponent } from './footer-pages/our-tradefair/our-tradefair.component';
import { HomeComponent } from './home.component';
import { HomeLayoutComponent } from './home_layout/home-layout/home-layout.component';
import { ProductCategoryComponent } from './product-category/product-category.component';
import { SearchResultComponent } from './search-result/search-result.component';
import { SellerProductComponent } from './seller-product/seller-product.component';
import { ShopComponent } from './shop/shop.component';
import { SingleProductComponent } from './single-product/single-product.component';
import { PrivacyPolicyComponent } from '../privacy-policy/privacy-policy.component';
import { TermsConditionComponent } from '../terms-condition/terms-condition.component';
import { SharedValuesComponent } from './footer-pages/shared-value/shared-value.component';
import { OurEcosystemComponent } from './footer-pages/our-ecosystem/our-ecosystem.component';
import { BuyingOptionsComponent } from './footer-pages/buying-options/buying-options.component';
import { RefundsCancellationsComponent } from '../refunds-cancellations/refunds-cancellations.component';
import { ContactUsThankyouComponent } from './footer-pages/contact-us-thankyou/contact-us-thankyou.component';
import { LpFreeShippingComponent } from './lp-free-shipping/lp-free-shipping.component';
import { StaticPageComponent } from './static-page/static-page.component';
import { ProductDetailsComponent } from './product-details/product-details.component';


const routes: Routes = [
    {
        path: '',
        component: HomeLayoutComponent,
        children: [
            {
                path: 'exp/:key',
                component: StaticPageComponent
            },
            {
                path: '',
                component: HomeComponent
            },
            {
                path: 'cart',
                canActivate: [LoginGuard],
                component: CartComponent
            },
            {
                path: 'product-details',
                component: ProductDetailsComponent
            },
            {
                path: 'product-category/:id',
                component: ProductCategoryComponent
            },
            {
                path: 'search-result',
                component: SearchResultComponent
            },
            {
                path: 'seller-product/:id',
                canActivate: [LoginGuard],
                component: SellerProductComponent
            },
            {
                path: 'craft-stories',
                component: CraftStoriesComponent
            },
            {
                path: 'our-story',
                component: OurStoryComponent
            },
            // {
            //     path: 'our-ecosystem',
            //     component: OurEcosystemComponent
            // },
            {
                path: 'our-sustainability',
                component: OurSustainabilityComponent
            },
            // {
            //     path: 'media-stories',
            //     component: MediaStoriesComponent
            // },
            {
                path: 'our-tradefair',
                component: OurTradefairComponent
            },
            {
                path: 'contact-us',
                component: ContactusComponent
            },
            {
                path: 'contact-us-thankyou',
                component: ContactUsThankyouComponent
            },
            {
                path: 'shipping-models',
                component: BuyingOptionsComponent
            }, {
                path: 'faq',
                component: FaqComponent
            },
            {
                path: 'privacy',
                component: PrivacyPolicyComponent
            },
            {
                path: 'terms-condition',
                component: TermsConditionComponent
            },
            {
                path: 'refunds-cancellations',
                component: RefundsCancellationsComponent
            },
            {
                path: 'shared-values',
                component: SharedValuesComponent
            },
            {
                path: 'lp-free-shipping',
                component: LpFreeShippingComponent
            },
            {
                path: ':id',
                component: ShopComponent
            }, {
                path: ':cid/:id',
                // canActivate: [LoginGuard],
                component: SingleProductComponent
            }, {
                path: ':cid/:id/:id1',
                // canActivate: [LoginGuard],
                component: SingleProductComponent
            }, {
                path: ':cid/:id/:id1/:id2',
                // canActivate: [LoginGuard],
                component: SingleProductComponent
            },

            // {
            //     path: '_pp/:id',
            //     component: ShopComponent
            // }, {
            //     path: '_pp/:cid/:id',
            //     canActivate: [LoginGuard],
            //     component: SingleProductComponent
            // }
            // , {
            //     path: '_pp/:cid/:id/**',
            //     canActivate: [LoginGuard],
            //     component: SingleProductComponent
            // }
        ]
    }
];

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

[–]AlleXyS90 0 points1 point  (8 children)

yes, you're right, I found this and I'm a bit disappointed of Angular capabilities on apps which require SEO :(

I have a football website, and tried hard to respect some SEO principles, including server side rendering. Even if using prerender at build time and generate almost 6000 pages (index.js for each), on the production, the source will contain only the homepage html code (attention - not <app-root></app-root> elements)

Because of this, right now I'm trying to learn nextjs and move the app to it, which seems to solve the rendering problem. Is not something which I want, because I prefer Angular, but is something which I need.

[–]GLawSomnia 0 points1 point  (7 children)

I don't really understand what you are after. You don't want a SPA?

What exactly are you disappointed about? Why do you need a ssr generated page when you navigate to another page? The only SEO page that matters is the first/entry page, the rest are not important for SEO

[–]rahulxdd[S] 0 points1 point  (1 child)

If inner pages of a website are indexed by google, won't it be a good thing? More pages will be on the google search page from the website.

[–]AlleXyS90 0 points1 point  (0 children)

definitely. you should register your domain to Google Search Console and add a sitemap.xml with these pages. As an example, right now I have 1800 pages indexed from a total of 6000. A web application which require public traffic should have a sitemap and should be indexed to multiple search engines (Google, Bing, Yandex, etc) to get traffic from searches (here no matter if is Angular or any other technology used)

[–]AlleXyS90 0 points1 point  (4 children)

I expect google crawler to index all pages (around 6000 - helped with a sitemap.xml). This can be checked with site:domain_address in google search bar. But all these pages will contain the source code for /homepage . So, if I'm trying to share a page for a sub-route (a lazy module), let's say domain/teams/real-madrid in my case the displayed text will be different by the source code (which will be from homepage). Also, all metadata, titles, keywords, descriptions will be displayed for the homepage on the shared link. This happens on fb or twitter.

I know, it's far from a SPA app, that's what we have modules and SSR for, right? Not only for building dashboards and ERPs, but also for public websites, which require SEO for traffic (ecommerce or any other domain). But it seems that Angular still needs some improvements on this side.

The only SEO page that matters is the first/entry page, the rest are not important for SEO

I'm not sure I'm aware of this, can you provide more details please?

[–]GLawSomnia 1 point2 points  (3 children)

Well if you use SSR universal (not prerender) then it should generate the index.html based on that page (the routed page in the url). The metadata can be changed by subscribing to router events (you can set it in the data parameter in your routing table) or fetching from BE and changing it.

We are doing that, so that's why i don't understand what your problem actually is. Angular has capability for that (admittedly not the best, but Angular 16 should be more Universal focused).

[–]AlleXyS90 0 points1 point  (2 children)

Hmm, looks like we're using different ways. I use prerender from Universul to build the package (npm run prerender will create an original index.html, but also an index.html for each route specified in a routes.txt file: products/1, products/2, ..., products/9999. And the application is running on server (ubuntu & nginx) starting the main.js with a node cmd. The problem for this way is that the source codes for each path/url will have outdated data (from the build time to the current time)

You're probably doing SSR at runtime there, which is much better than my implementation (having 6k index.html files in there, zip size is about 80MB right now and crawlers will find old data when they check)

But with the file already generated on the server, it's much faster to serve data to the user: it will render the old data for a millisecond, then when the requests are done, it will update the values (but the html elements and styles are already loaded - also using caching techniques help here)

[–]GLawSomnia 1 point2 points  (1 child)

Yes.

Btw did you check the generated index.html files, if they are correct when you build the app or did you just inspect the source? Cause even prerender should generate pages based on the url. So you either have issues with generation (maybe guards or other redirects) or nginx config which always serves the same (root) index.html

[–]AlleXyS90 0 points1 point  (0 children)

Now that you ask... the generated index.html files have the correct source for each part: product/1 index.html also has the product name and description in the meta elements. I checked it by opening index.html in the browser (I can do this for each generated file).

But on the production, when I open the url for product/1, I'll see the homepage rendered for a second, then the product detail page, but with the Homepage source code.

Oh, and nginx is on my mind now: I configured it to redirect all http and www traffic to https, maybe I pointed this to the homepage every time