chrisvfritz / prerender-spa-plugin

Prerenders static HTML in a single-page application.
MIT License
7.33k stars 634 forks source link

ON refresh any route ,'/' routes component loads and then actual page loads #266

Open kdeeksha-zz opened 6 years ago

kdeeksha-zz commented 6 years ago

in webpack.prod.config : const PrerenderSPAPlugin = require('prerender-spa-plugin') const Renderer = PrerenderSPAPlugin.PuppeteerRenderer

plugins :[ new PrerenderSPAPlugin({ staticDir: config.build.assetsRoot, routes: ['/'], postProcess(context) { context.html = context.html.replace('id="app"', 'id="app" data-server-rendered="true"'); return context; }, renderer: new Renderer({ inject: 'head', renderAfterDocumentEvent: 'render-event' }), headless: true }) ]

in index.html :

i want to prerender '/' which has a search bar, links and button. when in sign-in or other route on refresh, '/' route page loads first and then corresponding route component.

ERROR : Reference Error : WebpackJsonp is not defined. CleverTap id is not defined

JoshTheDerf commented 6 years ago

I don't really understand the issue, but it sounds like a problem with CleverTap.

kdeeksha-zz commented 6 years ago

I have prerendered only one route i.e '/'. If I'm in '/signin' and hit reload button the '/' route component loads first(prerendered) and then '/signin' content appears (not only sigin for every other route as well)

kdeeksha-zz commented 6 years ago

@Tribex Any solution to this?

kdeeksha-zz commented 6 years ago

@tribex, I guess i can solve this by prerendrring all routes. I have few dynamic routes like /: contentNam/:id whil is a child route. How can i add this to prerender. When i add dynamic routes i get unable to prerender all routes error.

JoshTheDerf commented 6 years ago

@kdeeksha It's not possible to prerender dynamic routes, you'll need to do each one individually, such as contentNam/1, contentNam/2

kdeeksha-zz commented 6 years ago

@Tribex how can i set that? because they are dynamic and there may be hundreds of contents. Otherwise, is there a way where i prerender only '/' ?

JoshTheDerf commented 5 years ago

@kdeeksha Yes, to prerender only /, have only / in your routes: [] list.

willgdjones commented 5 years ago

Is there any update on this? It seems that if / is set to pre-render it tries to pre-render the homepage on all other routes that are not pre-rendered, before eventually rendering the correct page - causing a 'flicker'.

ccesare commented 5 years ago

This doesn't sound like it has to do with the plugin -- or at least I don't think the plugin directly causes this behavior. It sounds more like an artifact of how your web server decides to respond to requests and how your routes are structured in the app. How does a server respond to a GET request for a route like /not/rendered? The simplest (default?) thing to do is to look for /not/rendered/index.html. When it doesn't find it, what happens next? 404?

As an example, GitHub Pages don't natively support single-page apps, so you have to do some hacky things to make sure the routing is handled by your app. Single Page Apps for GitHub Pages is an example of a workaround for this that will cause exactly the behavior you're talking about (flash of the prerendered route closest in your routing hierarchy to the route you requested).

dsmurrell commented 5 years ago

EDIT: it seems like the below attempt has worked for us.

Hi @ccesare, I think you are right. We are using AWS S3 to serve the page.

We set up error responses like so (source https://medium.com/@P_Lessing/single-page-apps-on-aws-part-1-hosting-a-website-on-s3-3c9871f126)

Screenshot 2019-04-16 at 16 55 55 Screenshot 2019-04-16 at 16 56 01

Well we point it to / instead of /index.html

I'm wondering whether the answer provided here might help us solve this issue: https://stackoverflow.com/questions/51154224/vue-pre-render-spa-root-overwrites-template-file

where we change the / we have set for the error page path to /app.html

Let us know if you've dealt with S3 before and have a better approach!

ccesare commented 5 years ago

I've got no experience with S3 beyond serving a simple static Jekyll site, so I can't be much help with the particulars there.

There are two things in tension with one another. The first is that prerendering the base route (/) will yield snappier page loads. The second is that getting to other, non-prerendered routes requires loading the base route (since it contains the code that handles the routes).

I guess your solution attacks the second idea. Prerender / but handle all the other routing via a non-prerendered version of / served from /app.html. It makes sense, and I might try it with an SPA I'm working on. Am I right that this is roughly what you've done?

My only other idea for how to solve the flash problem would involve listening for DOM events and responding with style changes to the root div. Even there I'm not sure how to differentiate between a request that results from /not/rendered and one that results from /.

nikitaplanet commented 4 years ago

I have the same problem. But I need to render all pages not only "/" page. Does anyone have a good solution to solve this?