redwoodjs / redwood

The App Framework for Startups
https://redwoodjs.com
MIT License
17.32k stars 993 forks source link

Prerender (SSG functionality): Testers Wanted #217

Closed tomByrer closed 3 years ago

tomByrer commented 4 years ago


Moderator Edit: Prerender support is now ready for testing and feedback. See this comment below to get started 🚀

Hi, seems like a neat project! I'm just here looking for SSG for SEO, cheaper hosting, etc, in your toolchain.... TIA :)

chris-hailstorm commented 4 years ago

I'm loving Redwood, but for true static sites you can't go wrong with something like Gatsby.

cannikin commented 4 years ago

Hey @tomByrer see @mojombo 's reply to a previous issue: https://github.com/redwoodjs/redwood/issues/18

mckelveygreg commented 4 years ago

Would this be able to integrate with something like Gatsby? For example, I love their Image processing (not the api per say, but at least the result!)

chris-hailstorm commented 4 years ago

@mckelveygreg the easy way is to use Gatsby for the static parts of your site and Redwood for the dynamic parts. The great thing about a static site is, you don't need a server or any kind of hosting -- e.g. with Gatsby, you can publish static files to an AWS S3 bucket and be done. Add a DNS name that points to that static file location and you have a very simple solution.

So maybe www.whatever.com is in Gatsby, and app.whatever.com is in Redwood. You can share React components, styling etc. between sites using normal JS tools if that makes sense.

tomByrer commented 4 years ago

use Gatsby for the static parts of your site and Redwood for the dynamic parts

That seems like far too much cognitive overload; Gatsby is complex & flexable enough by itself TYVM.

@cannikin

but for now Redwood is client-rendered only

Ah, thanks. Feel free to close if too 'out of scope', or keep open as you wish since I'm sure I won't be the only one asking ;)

zwl1619 commented 4 years ago

I need SEO too. There are many static pages, I can not generate them manually with Gatsby.

chris-hailstorm commented 4 years ago

Gatsby can generate static pages in bulk from various data sources. Static doesn’t mean hand-crafted. Basically with Gatsby you have a database connection at build time; with Redwood you have a database connection at run time. Hope that helps.

zwl1619 commented 4 years ago

@chris-hailstorm Thanks, that is ok.

So maybe www.whatever.com is in Gatsby, and app.whatever.com is in Redwood.

There are two sites above, could add a tutorial for Single Sign On (SSO) after completing the standard auth way in https://github.com/redwoodjs/redwood/issues/214 ?

chris-hailstorm commented 4 years ago

@zwl1619 good idea, will create that as a separate issue after outlining the #214 solution.

thedavidprice commented 4 years ago

Hi all, I understand having static rendering somewhere in the process (whether pre- or server-) is optimal. But do know there’s nothing currently blocking a React-helmet setup allowing you to manage the <meta> needed for pages: https://github.com/nfl/react-helmet

Personally, I’m continually interested in research and real-world examples that indicate where we do and don’t need rendering for performant SEO. Saying this because I’d welcome current information if you have good resources to share.

I think a lot of conversation confuses “SSR” with “SEO”, when it’s really about how performance aspects of your site/app affect indexing. (Yes, of course assuming the bots can get the <meta> in the first place.) We are building Redwood to be highly performant out of the box (code-splitting on routes and Netlify CDN, for example). Last I checked, the only remaining PWA feature we need to add is a Service Worker. (The app will also need a static asset manifest.json in the public/ folder, but that’s supported and trivial.)

If you do take React-helmet for a spin, please do let us know what your results are from something like Google Search Console "URL Inspection”.

Oh, and I’d be very curious to know your results from a Google Lighthouse audit on your app deployed to Netflify! That would be another indicator about whether or not we are supporting performance out of the box. Here’s the audit on our vanilla demo of the Redwood blog deployed on Netlify at https://redwood-example-blog.netlify.com/ Even without specific config focus on SEO or using React-helmet we hit 83 on SEO. Importantly, our biggest ding across all categories is not having offline support (because the app lacks a service worker). Run it for yourself and see.

Screen Shot 2020-03-12 at 10 01 23 PM
dgb23 commented 4 years ago

I completely understand that Redwood is in a very early stage and focusing on developer ergonomics is a priority right now (Typescript, Storybook, Jest) over SSR and SSG capabilities.

Rationale: why SSG (SSR) should be a critical aspect of modern sites and apps

For me SSG/SSR is not just there to specifically improve SEO.

First of all SEO is a muddy concept. I think the primary goal is to provide good content and UX. Sure there are specific things that one should do like providing a sitemap and so on. But an app or sites primary value comes from happy consumers.

Performance is one of the most important aspects of UX and there is simply nothing that beats well structured pre-rendered content, especially when enhanced with React (or similar) via hydration.

For anyone who isn't convinced that this is a complete paradigm shift:

  1. Visit a site that is generated with Next/Gatsby or similar like https://reactjs.org/.

  2. Open the network tab in your dev tools.

  3. Observe what exactly happens when you hover over links and when you click them.

  4. Observe what happens when you force refresh.

  5. Disable Javascript and continue to browse the site.

It should be absolutely obvious that this is the way to go for any content that can be pre-rendered: UX is amazing, caching is simplified and more powerful, content can be consumed/indexed even w/o JS.

And this is just the UX side. From an operational perspective this means you can also optimize server loads if SSG is implemented well in combination with client-side rendering.

"Jamstack" implies SSG

This might be a misunderstanding from my side but I very much associate Jamstack with SSG and when I read "Bringing full-stack to the JAMstack" I was very much expecting Redwood to have this feature.

I assume that many who are curious about Redwood will expect this too. on jamstack.org it literally reads: "Fast and secure sites and apps delivered by pre-rendering files and serving them directly from a CDN, removing the requirement to manage or run web servers."

mojombo commented 4 years ago

@dgb23 Thanks for the well laid out thoughts on this! I’m with you 100%. I’d love to make it possible to pre-render on a route-by-route basis, and it’s on our roadmap. We’re haven’t had a chance to think about rehydration much yet, so if you have ideas on what you think the interface should be like for that, I’d love your thoughts!

lachlanjc commented 4 years ago

@mojombo Yep, this is similarly my biggest hesitation around Redwood—there's a lot to love with the DX, but having a website that won't work whatsoever for users without JavaScript & will be a slow (esp. initial) experience for users on old devices is disappointing. Next.js has a really ideal setup here I think—there's flexible, per-page server rendering, isomorphic prefetching, fully static pages, and static-generated pages (with generative routing) all without any setup or configuration, and users can remember/use the methods without checking docs. In Redwood, having an HTML template feels dated (should just be generated from pages/head tags I feel), there's the clear access implications I mentioned of client rendering, & the SEO angle (your thoughts on #18 totally makes sense though).

zwl1619 commented 4 years ago

If adding next.js into Redwood, are there any problems?

nickgeerts commented 4 years ago

Yes, Redwood's tagline doesn't make sense to me, since it doesn't conform to JAMStack... 🤷‍♂

They chose not to use Next.js because of its lacking router. I agree with that, however there is a custom routes feature coming in version 9.3 / 10. Although it's not full-featured router, perhaps that is an option? It should also come with a router API.

https://github.com/zeit/next.js/issues/9081

It would at least be nice to have the option in Redwood to implement SSR oneself, as can be done in Meteor with its server-render package.

cr101 commented 4 years ago

SSR needs to be built in for RedwoodJS to be widely adopted by web developers for creating a wide range of web apps. Next.js is the obvious choice for providing SSR. I hope that the core team will listen to the community and implement Next.js soon.

lachlanjc commented 4 years ago

I don’t know technically whether wrapping Next.js is the best choice for Redwood or not, I’m more trying to say that their system I think is the best (& fairly similar to how Redwood already does other things, like the precedent of named exports on Cells) out there right now & Redwood should adopt something similar.

Jaikant commented 4 years ago

The gatsby solution of SSR is awesome - scalable and low cost. I love the way gatsby compiles/optimises the static part of a website. That said, routes which render dynamically in gatsby (client routes in gatsby terminology) are not server rendered. There are could be a page which has some components - server rendered (static part) and other components not server rendered. In gatsby, the components which depend on dynamic API data, would be rendered on the browser after the data is fetched from the API. In Next.js everything is server rendered, though less optimised than gatsby.

IMHO, I prefer the gatsby approach of SSR for redwood to start. And then building some kind of wrapper over the graphQL endpoints so the dynamic parts are also server rendered (how?).

nickgeerts commented 4 years ago

This is no longer true. Next.js also supports static pages with dynamic client content with ease. You just use useEffect to fetch your data from an API instead of getServerSideProps or getStaticProps. I actually do this a lot in my projects.

Next.js builds 3 types of pages: λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps)

Without server-side rendered pages, you can export your project to plain static files, just like Gatsby.

SSG pages scale better. SSR pages are more flexible. IMO at least SSG is necessary for a modern web framework. It's up to the Redwood developers to choose a solution, but don't dismiss Next.js as an option. I hope there will at least be a SSG or SSR implementation for Redwood 1.0.

tomByrer commented 4 years ago

Good writeup @njjkgeerts !

I hope there will at least be a SSG or SSR implementation for Redwood 1.0.

Well, I hope Redwood takes off, so if they need to have a smaller user-case for for a solid v1.0, that's for them to decide. But I do hope they start thinking more about how to include Pure Static / SSG at some point.

jonniebigodes commented 4 years ago

@tomByrer and @njjkgeerts and i indeed. But i would rather have a fully working project, well documented at boot than try and cram SSG or SSR right now, there's alot of work to be done to get this into fully stable solution and by the day i see this getting more and more traction and with that more and more people get to use it and inherently a small community is starting to develop here which is rather nice.

Probably down the line the "other side of the spectrum" (ssr approach) could be achieved with some work

thedavidprice commented 4 years ago

If you're looking for a way to handle pre-rendering for Redwood right now, @dac09 has paved the way. Here's his in-depth write-up on the forums: https://community.redwoodjs.com/t/pre-rendering-with-react-snap-redwood/863

Also, if you haven't taken a look at Tom's recent proposal, the conversation is happening here: https://community.redwoodjs.com/t/prerender-proposal/849

redbar0n commented 4 years ago

First, I really hope RedwoodJS succeeds, as I’m really excited about the developer experience (esp. the Cells and Services patterns).

Speaking of webapps needing much dynamic & fresh data from a DB:

Speed-wise, does it matter if the client can get the HTML/JS fast from a CDN in 1st request, if the client then has to make a 2nd request to the API to get the data? When the client instead could have gotten everything SSR’ed up in 1 request total? Spending slightly more time server-side, presumably closer to the data/API, to avoid the extra roundtrip. (see: general latency comparison)

Or like Relay does: Keep the rendering fully client-side, but send HTML/JS + graphql data in parallel at first request, and then hydrate instantly locally in the browser. (Perhaps the Relay way is what RedwoodJS does already... Is there a sequence diagram of the request response cycle somewhere?).

When the client has received first page via CDN, the added latency between the client and the API would presumably be larger than the time it would have taken to have run SSR on the server-side (in a Lambda, close to the API Lambda), and then simply returned the hydrated page to the client in the first place.

Not having SSR is the biggest barrier to adoption for me atleast. Since search-engine traffic is so dominant today, and could make or break a site, I cannot make sacrifices on SEO (even hypothetical ones... since as a dev/CTO I’m no SEO expert and can’t take the risk that all the JS will be parsed correctly by all search engines). I really really want to use RedwoodJS for its developer experience, but starting a potentially huge project, like I am (who isn’t?), and choosing technologies, then some things are a non-starter, which would prevent me to ever getting around to feel and stick around because of the developer experience.

Would it be feasible to fork NextJS and merely throw out its router with your own (if you don’t like it for some reason)? (I also read above that one of the latest NextJS versions has an option for using a custom router, so maybe no fork is needed at all.) Optimised SSR (and even hybrid SSG) is so complicated, and NextJS has a large community committed to it, so why not build on that?

Example:

NextJS solves initial page load, small bundle sizes, and SEO, in collaboration with Google Chrome team: https://www.netlify.com/blog/2020/06/18/next.js-101-what-you-should-know/ and https://nextjs.org/blog/next-9

A hybrid approach might be the most future-proof, since pure SSG and API’s is not best for every use case (only covering the static-site and slightly-dynamic-site use cases would make something kind of a «limited/narrow fullstack» instead of a «full fullstack»). SSG and SSR can be blended (even with CSR), to solve that. NextJS 9.3 can already do this on a per-page basis:

"Next.js [9.3] is able to do a full spectrum of static site generation [SSG], client side rendering [CSR] and server rendering [SSR]," says Rauch. "It's almost like a new beginning. This idea of combining SSG in a hybrid way and giving people the options, it's a really big thing." https://www.theregister.com/2020/03/19/jamstack_anyone_nextjs_creator_on_hybrid_rendering_typescript_and_visual_studio_code/

That sounds like quite a job to implement in full!

Wouldn’t your efforts go better towards optimising all of the sides of the developer experience you are really passionate about, than redoing all the low-level SSR (and SSG) stuff?

I’m sure you have weighed the choice considerably before, though I hope you’d be willing to reconsider.

There are also some concerns with SSR that I see, which you may have already taken into account: SSR would presume something extra on the server side besides the API, so it would come with a certain architectural burden for RW. However, SSR does not necessitate maintaining a server (contrary to the assumption that «you have to have a server running at all times to provide the benefits needed to perform server-side rendering», sometimes made in the JAMstack space). You could do SSR in a AWS Lambda function (Serverless SSR). Maybe it is possible to draw some inspiration from this NextJS on Lambda architecture diagram where the SSR is done in a separate Lambda function? The difficulty lies in that requests would need to go to that Lambda first, and not the CDN. (The Lambda would kinda work as a «virtual webserver»..). So perhaps one would lose some benefits with CDN’s being more available and faster than Lambdas. And perhaps it would totally break with the JAMstack philosophy... (if being in perfect ideological alignment with that philosophy is a point in itself...?)

It’s very hard to predict how dynamic a webapp will be, or how it will evolve over time. One might think SSG will suffice at first because one only foresees a limited finite amount of pages, but then new requirements come in, and it suddenly becomes a webapp needing a lot of dynamic and fresh data (and SSG thus becomes less feasible). Having chosen a framework that supports that evolution would have reduced risk.

More on the WHYs and HOWs of hybrid per-page SSG, CSR, or SSR, using a real life example website: https://vercel.com/blog/nextjs-server-side-rendering-vs-static-generation Hybrid seems like the future to me. And it seems very non-trivial for a framework to implement, maintain and optimise it over time. So building on an existing successful solution with a huge community seems like a reasonable approach to me.

That said, you are totally free to make choices that are right for you, considering where you are in the development of RW, of course. I do hope I have given some insight into the mind of a potential early adopter. Feel free to throw my feedback away if it doesn’t make sense. I just felt it was important to get out there in case it could ultimately show itself to have been helpful.

narciero commented 4 years ago

I just want to echo @redbar0n here on seeing if building on top of Next.js is a possibility.

Next.js is a proven leader in the frontend space and I think Redwood could complement it perfectly, gaining all the features of Next.js (and avoid having to re-invent them) and the addition of the awesome DX/tooling/etc you get with Redwood would make it a no-brainer framework of choice for full-stack (at least for me!).

I'm curious to hear others feedback/more info about the decision to pursue/not pursue an integration. Thanks for all the great work!

thedavidprice commented 4 years ago

This is a great conversation, @redbar0n and @narciero. When I think about the general idea of using both Next and Redwood, my mind goes to "Oh, yeah, use Next for the frontend and Redwood as API. Maybe that looks like supporting next as an official Redwood Side 🤔..."

But is this what you're suggesting/implying? Maybe what would help me better understand is the specific components, pieces, tools you'd use and how they'd work together in a complementary fashion. E.g. me saying Redwood API (Prisma, SDL, Services, Functions) could run the backend for Next frontend. You could use the backend generators for code and tests.

If you were to use pieces together, what would those pieces be?

narciero commented 4 years ago

@thedavidprice I am thinking more along the lines of "What if the web side of Redwood was built on top of Next.js...a Redwood web side is a Next.js app". This would unlock all of Next.js' features for Redwood without the team having to build custom solutions for things like prerender, SSG, and hybrid CSR/SSR.

Along the lines of Redwood supporting an official Next.js side, I think it would be great if in a Next.js app, I was able to use the following frontend tooling from Redwood:

These relatively simple codegen tools would save a lot of time + boilerplate and could be a good way to introduce Redwood into the Next.js ecosystem.

I think Redwood is a great choice for the API side (regardless of what gets used for frontend) and you can obviously integrate with Next.js today since you're just talking to a GraphQL API, but it would be awesome to have the Redwood tooling for Page, Layout, Cell, tests, storybook, etc. available when working in a Next.js frontend environment.

In my mind, I see Next.js as the best bet for the foundation of jamstack apps (especially with the introduction of API routes) and I see a lot of potential for something awesome like Redwood to leverage that foundation and provide all the great tooling/DX that you guys are working on - just my two cents...thanks!

dac09 commented 4 years ago

Hi, just chiming in here to say we’re using

Just my 2p, but I think all of these frameworks really focus on things that they are really good at, with their own roadmaps for improvements and that’s a wonderful thing isn’t it? I like all of these frameworks (having now used all of them in prod) and while I think SSR/SSG is important, I think its more important to pick the right tool for the job.

Can I ask, respectfully and genuinely, about the thought process behind needing it all to be in one framework?

Jaikant commented 4 years ago

I love Next, Gatsby and Redwood. Next was born on the server. Gatsby on the CDN. And Redwood is on the CDN too but with APIs!

I feel Nextjs isn't Jamstack. So it isn't the right move from a direction perspective, unless Next can live on a CDN like Gatsby.

narciero commented 4 years ago

@Jaikant I love all those frameworks too! But I believe Next.js 100% covers Jamstack use cases, and it can easily live on a CDN (next export - I have multiple prod Next.js apps running as static sites on Netlify) and it has the ability for SSG like Gatsby...I'd encourage you to checkout the Next.js docs. Next.js has evolved a lot recently and it's far from just a SSR framework. I'm wondering why you think Next.js wouldn't fit the Jamstack architecture?

@dac09 Hey, I think its definitely great that there's such a good ecosystem right now in the frontend but I think the situation you described where you need 3 different sites + 3 different frameworks is exactly the situation that many devs (myself included) would like to avoid when there is a framework that can handle all of those situations. Why isn't Next.js the right tool for the job?

I think needing a static site (like you mentioned for your help site) along with a dynamic CSR site statically deployed to a CDN is a super common use case, many sites have a landing page or other static pages (that may integrate with a headless CMS). Rather than having to integrate with a custom prerendering solution, or move the static portion over to Gatsby, Next.js gives you amazing performance (and imo a great DX) for both your static landing/help pages (SSG) and your dynamic CSR site (code-splitting, prerender, etc.) with literally zero effort on the developers end. And with one command next export your site is ready to be deployed to a CDN.

I don't want to beat a dead horse here, but I strongly encourage the Redwood community to consider supporting the Next.js frontend as it would give you all of the following features for free - and like @redbar0n mentioned, free up the team to focus on the stuff that makes Redwood unique + awesome!

Jaikant commented 4 years ago

@Jaikant I love all those frameworks too! But I believe Next.js 100% covers Jamstack use cases, and it can easily live on a CDN (next export - I have multiple prod Next.js apps running as static sites on Netlify) and it has the ability for SSG like Gatsby...I'd encourage you to checkout the Next.js docs. Next.js has evolved a lot recently and it's far from just a SSR framework. I'm wondering why you think Next.js wouldn't fit the Jamstack architecture?

@narciero Nextjs was not conceptualised for the CDN when it was created, it was born on the server. It can live on the CDN now, as an after thought. Which implies many of the design decisions in the code base may not be optimised for the CDN use-case. I don't think it appropriate to pull in any sort of technical debt for a high potential, shiny framework like redwood.

I am not familiar with the Nextjs codebase and could be wrong in my reading. The good news is, just today, I read on the forums a post from Arunoda, who is part of the Nextjs core team, he is now part of the redwood community đź’Ż. So I am sure the right approach will be adopted.

redbar0n commented 4 years ago

For reference, I'll add to @narciero's NextJS-list, some of the benefits unique to SSR in general:

It looks like one would need SSR to achieve these. Correct me if I'm wrong. Might be worth having this overview here in case you would at some point consider some architecture involving f.ex. Serverless SSR (as previously mentioned).

Source (with more details): https://arunoda.me/blog/hey-nextjs-is-server-side-rendering-dead

BasJan81 commented 3 years ago

I'm very curious about a future Static Site Generation functionality.

Let's say, this will be added to the roadmap, what label will it get. #Core #Deployment or #Prerender ?


RedwoodJS is looking very promising so far. I've learned working with Laravel in school, but this is the first time some 'React' or 'meta' Framework has got me excited. In a way this feels very comfy, coming from a Laravel flow.

redbar0n commented 3 years ago

«Async access to data inside a component is the toughest hurdle for JAMStack websites right now.« - Joel Varty, https://twitter.com/joelvarty/status/1341235382617255942?s=21

React Server Components were just announced: https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html

Lots of benefits like reducing bundle sizes sent to clients.

But Server Components could perhaps also give RW the ability to do Serverless SSR in a smooth way, without having any server state (so it would be possible to do it in Lambdas), and without having to build RW on something like NextJS (which I’ve understood won’t ever happen, due to the dislike of its pages-based router).

(Though, React Server Components is apparently in some ways opposite to purist JAMstack philosophy..)

React team will work with frameworks to enable Server Components first. So there is an opportunity here for RedwoodJS to be early out and leverage a potentially sweet integration here, to get both better UX and DX in one go..

thedavidprice commented 3 years ago

Update

I can confirm we are working on prerender capability (e.g. marketing pages) to be included in the v1 release. It's the number two priority right behind full TypeScript support.

There's no specific project board for tracking progress. Just keep a lookout on the Forums and PRs in the weeks to come.

Background

The core team has spent extensive time in conversation and research about how to conceptually approach the topic of Redwood at Scale, which is a much bigger landscape than just prerendering pages. The announcement about React Server Components came out after we had begun conversation + exploration, and the best part is that it confirmed a lot of our high-level goals and choices for overall direction. We aren't trying to copy what's existing, although we're definitely taking notes and learning.

The long-term goal for Redwood at Scale is to find optimal solutions based on what's possible, even if those solutions haven't been done before. So prerender support isn't a goal. It's just the next step.

Jaikant commented 3 years ago

This is great to hear. After spending 3-4 years soaking in this amazing js/ts ecosystem, I am now working on a new start up. The first thing to hit me is the totally new and amazing things which the python ecosystem enables!

I would so love it if redwood js could provide a backend technology agnostic server side rendering capability.

thedavidprice commented 3 years ago

https://github.com/redwoodjs/redwood/pull/1641

thedavidprice commented 3 years ago

Update: Prerender is now available in the latest canary release 🚀

🙏 Help Wanted 🙏

The new Redwood Prerender feature is ready for testing and feedback! First off, check out the primary PR:

There's one important change that will be coming via this PR:

How to get started

Warning: canary releases are unstable and Prerender is an experimental feature

Read the (draft) Manual

Prerender Documentation

This is a draft. Please add comments or questions to either the Notion doc or replying to this thread.

Start with a new project using canary

Run npx create-redwood-app@canary path/to/project to install a new project using the canary release

Upgrade an existing project

Run yarn rw upgrade -t canary to upgrade the latest canary release

thedavidprice commented 3 years ago

Closed with https://github.com/redwoodjs/redwood/releases/tag/v0.26.0

🚀