ionic-team / ionicons

Premium hand-crafted icons built by Ionic, for Ionic apps and web apps everywhere 🌎
http://ionicons.com
MIT License
17.51k stars 2.06k forks source link

SSR loading svg elements #886

Open agustinhaller opened 3 years ago

agustinhaller commented 3 years ago

I'm working in a @ionic/angular app with @ionic/angular-server. I have tried both in a blank project following this tutorial and my existing code base.

In both cases when I disable javascript in the dev tools to test the SSR scenario, none ion-icon element gets rendered.

Digging into the source files I noticed you do this on purpose.

I know SSR has its limitations, but I was wondering if you believe there's a way of rendering the svg elements in the server so the icons work for server side rendered pages.

@elylucas can you point me in the right direction?

elylucas commented 3 years ago

Hmm, IIRC we did that with the sole purpose of getting SSR working without crashing, but not realizing it would not populate the icon without JS turned on. We will take a look into a better way of doing so.

Thanks for the issue and the pointer to where it's at.

agustinhaller commented 3 years ago

Cool, thanks for taking the time to look at this issue.

... Maybe for named icons (the ones included in the ionicons library) it is possible to extract the svg contents at build time and store them in a simple js file. That way, in the SSR scenario you only need to set the inner html of the ion-icon to that string.

zwacky commented 3 years ago

I landed on this issue as well. @agustinhaller, I was wondering if you have made any progress or found any workarounds for this?

smlamod commented 3 years ago

This along side ion menu were not in working properly in ssr. It may not be ideal but since we only needed it for seo/bots i just made it available for those user agents.

sean118 commented 3 years ago

As a quick workaround I ended up creating my own little CustomIcon-Component, that loads the hosted SVG from an absolute URL. Maybe it helps someone.

I use it like this, where assetsPath returns the absolute URL, if not running in the browser (based on isPlatformBrowser()).

<app-custom-icon [src]="assetsPath('svg/play-circle.svg')"></app-custom-icon>

import { Component, OnInit, Input, ViewEncapsulation } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-custom-icon',
  encapsulation: ViewEncapsulation.None,
  template: `<div class="custom-icon" [innerHTML]="svg"></div>`,
  styles: [`.custom-icon {
    display: inline-block;
    color: inherit;
    width: 1em;
    height: 1em;
    contain: strict;
    fill: currentcolor;
    box-sizing: content-box;
    svg {
      display: block;
      stroke: currentcolor;
      height: 100%;
      width: 100%;
    }
  }`]
})
export class CustomIconComponent implements OnInit {

  @Input() src: string;
  public svg: any;

  constructor(
    private sanitizer: DomSanitizer,
    private httpClient: HttpClient,
  ) { }

  ngOnInit() {
    this.httpClient.get(this.src, { responseType: "text" })
      .subscribe(resp => {
        this.svg = this.sanitizer.bypassSecurityTrustHtml(resp);
      })
  }

}
WDrzewiecki commented 1 year ago

Hi, any updates on this?

muchbetterug commented 1 year ago

Any updates? Would be nice to have icons in SSR