GoogleChrome / rendertron

A Headless Chrome rendering solution
https://render-tron.appspot.com/
Apache License 2.0
5.94k stars 809 forks source link

problem with rendering Angular 4 sample app Tour of Heroes #94

Closed hekod777 closed 7 years ago

hekod777 commented 7 years ago

Hi

When I tried to use rendertron and puppeteer to render the Angular 4 sample app Tours of Heroes, the angular 4 ngFor directives are ignored. All the content related to ngFor failed to render.

Due to the async request for heroes, Tour of Heroes actually has 2 stages of loading

  1. load everything except for the ngFor stuff
  2. load the ngFor stuff

It seems that rendertron thinks that after stage 1 of loading, the page has already finished loading. that's why it only renders the stuff without those ngFor async request content.

Since Sam was saying that rendertron can handle all those async requests during Polymer Summit, a fix would be nice~

thx!

samuelli commented 7 years ago

Hi @hekod777,

Can you please provide reproduction steps and/or minimized test cases? It is difficult for maintainers of open source projects to be able to help you without these.

Please provide a link to a broken case and what the expected/actual results are.

Thanks, Sam

hekod777 commented 7 years ago

Hello @samuelli

here are the steps to reproduce Angular 4 async request problem

  1. install angular CLI

npm install -g @angular/cli

  1. clone this repo

https://github.com/johnpapa/angular-tour-of-heroes

  1. cd into the repo

npm install

  1. serve the app

ng serve

  1. then go to

http://localhost:4200/heroes

this is what the site is supposed to show

  1. then start rendertron and enter the following to the input field

http://localhost:4200/heroes

  1. if we click the regular render, the render result will not have those heroes (ngFor)

  2. if we click the shady dom = true render, all the angular 4 components will not be rendered

  3. if we modify src/app/heroes.components.ts line 23 from

    
    getHeroes(): void {
     this.heroService
       .getHeroes()
       .then(heroes => this.heroes = heroes)
       .then(()=>console.log(this.heroes))
       .catch(error => this.error = error);
    }
to

getHeroes(): void { this.heroes = [{id:1, name:'kkk'},{id:2, name:'bbb'}]; }



rendertron's regular render can render the page just fine.

conclusion, rendertron failed to detect when the angular 4 page actually finished loading when there is an async request.

Please let me know if more details is needed.

thx!
Koddy
hekod777 commented 7 years ago

these are the steps for angular 4 + polymer 2.0

  1. clone this repo

https://github.com/hekod777/angular4poly2

  1. cd into the folder

npm install

  1. start the angular 4 app

ng serve

  1. there are three parts in this html page
  1. copy http://localhost:4200/ to the input field of rendertron

  2. if we use regular render, it will render all the angular 4 components while ignoring shadow doms

  3. if we use shadydom=true to render the page, all three parts mentioned above will be ignored.

Please let me know if more details is needed.

thx! Koddy

hekod777 commented 7 years ago

@samuelli

hmmmm all worked~

  1. Angular 4 async call problem

reason why the tour of heroes ngFor didn't was NOT because of async call. it's because it used InMemoryWebApiModule which is a fake async call for demos and tests. after replacing the fake call with a real async call, everything worked!

  1. Angular 4 + Polymer 2.0

I just do not know why rendertron failed to render my sample app. instead of using the sample app i built, I simply insert Polymer 2.0 elements into tour of heroes app. and everything worked! Even if I tried my best to mimic my sample app to tour of heroes, and still couldn't get it to work. I'd like to know what actually make the rendering failed.

Anyway, Rendertron is Awesome! If the first time rendering speed can be faster, then it will be perfect!

samuelli commented 7 years ago

Great to hear that you got it all working!

mpunit2530 commented 6 years ago

@hekod777 can you share the complete repo with Rendertron usage. I am also looking for server side rendering of angular 4 app.

hekod777 commented 6 years ago

@karunya2530 I am sorry that I am not allowed to share the repo. but it's pretty much the same as the official repo except I added redis for caching and added the setup for downgrading to Node 6 compatible.

other than the repo the AWS configuration was kind of tricky as well.

I am willing share any of my knowledge. Just let me know what kind of questions you have.

mpunit2530 commented 6 years ago

Okay. Thanks for the reply. What version on node are you using ? Secondly i have setup an instance of docker on my server with running rendertron on port 8080. Now in my angular app i have installed express middleware and define the index.js. So could you help me out how to define index.js and where to execute index.js on server? Also if i am accessing my site then how rendertron will work for rendering html structure and seo.

hekod777 commented 6 years ago

hmmmm....

  1. Due to the company policy, I am running rendertron in a docker container using node 6 base image.

  2. My understanding is that you have an express server for your angular app. Then all you need is to use the rendertron middleware in your server/index.js. For example:

    
    // if you want to overwrite the default bot list
    const botUserAgents = [
    'W3C_Validator',
    'baiduspider',
    'bingbot',
    'googlebot',
    ];

const botList = new RegExp(botUserAgents.join('|'), 'i');

app.use(rendertron.makeMiddleware({ // put in your rendertron endpoint proxyUrl: 'https://render-tron.appspot.com/render', userAgentPattern: botList, }));


3. rendertron middleware will figure out if a request is from a bot based on the user agent. If it's a bot on the bot list, then it will make a request to the rendertron endpoint and send back the SSR version of the page. 

ps: We are planning not to use rendertron middleware. Instead we want to use DNS to identify bots and redirect the request to rendertron endpoint. While letting the DNS to verify the true identity of a bot if possible. The pro is that this solution can be used for all kinds of different backends. 

pps: for googlebot you can read about this article written by Sam Li. https://medium.com/dev-channel/polymer-2-and-googlebot-2ad50c5727dd
sunnykreative commented 6 years ago

Can anyone share a working example of rendertron with existing angular project? What changes needs to be done?

If anyone can share a video it would be great. I have searched youtube and got various videos but those all asks for firebase. I want it without firebase.

hekod777 commented 6 years ago

I just watched the youtube video to deploy rendertron to firebase. This is what I felt.

  1. It didn't use rendertron middleware. Instead it kind of wrote its own rendertron middleware logic. I am not quite sure if it's needed since he was using express server anyway. Maybe that's because the way he handles caching.

  2. Back then we still haven't discovered the share memory size issue for rendertron running in a docker container. Simply the shared default memory size in a docker container is 64mb which is not enough for headless chrome. if it gets many requests the docker container will crash. To deploy rendertron docker container you should consider adding 1. shm-size flag and 2. -security-opt flag. you can find out more details in rendertron's readme.

Let's go back to your questions.

  1. There can be lots of different ways to use rendertron depending on the host, the way you handle cache, and the way you detect bots and make request to rendertron endpoint. Where do you want to deploy rendertron? How do you want to handle cache? How do you want to handle bot detection and making request to rendertron endpoints? If you can have answers for these questions, it should be easier for people to help you on the details on how to configure rendertron for your need.

  2. These are some of the changes and special configurations I have done for rendertron

The process might be very different if you are going for a different way of deploying rendertron.

It's a good idea to figure out what you are aiming for (the 3 questions above) first.

sunnykreative commented 6 years ago

Hi,

Just wanted to know what changes I should do on my angular project so it uses rendertron.

On Wed, Mar 21, 2018 at 11:52 AM, hekod777 notifications@github.com wrote:

I just watched the youtube video to deploy rendertron to firebase. This is what I felt.

1.

It didn't use rendertron middleware. Instead it kind of wrote its own rendertron middleware logic. I am not quite sure if it's needed since he was using express server anyway. Maybe that's because the way he handles caching. 2.

Back then we still haven't discovered the share memory size issue for rendertron running in a docker container. Simply the shared default memory size in a docker container is 64mb which is not enough for headless chrome. if it gets many requests the docker container will crash. To deploy rendertron docker container you should consider adding 1. shm-size flag and

  1. -security-opt flag. you can find out more details in rendertron's readme.

Let's go back to your questions.

1.

There can be lots of different ways to use rendertron depending on the host, the way you handle cache, and the way you detect bots and make request to rendertron endpoint. Where do you want to deploy rendertron? How do you want to handle cache? How do you want to handle bot detection and making request to rendertron endpoints? If you can have answers for these questions, it should be easier for people to help you on the details on how to configure rendertron for your need. 2.

These are some of the changes and special configurations I have done for rendertron

-

I am gonna deploy rendertron to AWS and use redis for caching

I wrote my own caching logic and use ioredis to handle redis related transactions.

I implemented babel to transpile rendertron to node 6 compatible and wrote a polyfill for a node 7 function. So that we can use our existing Node 6 base image for rendertron.

I modified the dockerfile to use our Node 6 base image

For AWS configuration, we set the docker container's default share memory size to 2GB because AWS docker configuration doesn't support --shm-size flag at the moment. And implemented --security-opt flag.

We are also working on the DNS configuration for bot detection and request redirection.

The process might be very different if you are going for a different way of deploying rendertron.

It's a good idea to figure out what you are aiming for (the 3 questions above) first.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/GoogleChrome/rendertron/issues/94#issuecomment-374843228, or mute the thread https://github.com/notifications/unsubscribe-auth/AVM2uSwZPZBzBiw-s4jFMk1x9LxVGmpQks5tgfGdgaJpZM4PKpsF .

-- Thanks and Regards, Sunny Bhagat Follow us on Facebook: https://www.facebook.com/kreativemachinez/

hekod777 commented 6 years ago

If you are using an express server for your angular app, you should add the rendertron middleware in your server/main.ts file. It will Identify bot requests and making requests to rendertron endpoints.

If you are using some other ways to identify bots and redirecting requests, then you don't need to make any changes to your angular 4 app.

AlnoorKhan commented 6 years ago

Can we use rendertron-middleware for angular 1.4. I am facing issue in rendering my page. ETIMEDOUT error fetching