Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving to JAMstack #1051

Closed
robertu7 opened this issue May 5, 2020 · 5 comments
Closed

Moving to JAMstack #1051

robertu7 opened this issue May 5, 2020 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@robertu7
Copy link
Contributor

robertu7 commented May 5, 2020

Background

We are suffering from website instability caused by traffic grows. And it's hard to keep it fast without putting more cloud resources, like adding more servers.

Ideally, we should make as much request resources as possible as static, and served by CDN. That's what JAMstack for:

...building websites and apps that delivers better performance, higher security, lower cost of scaling, and a better developer experience.

Architecture

We mainly use these two frameworks to build and run matters.news:

Untitled-2020-05-05-1807 (1)

In our current architecture,

  • Static assets (JS bundles, CSS, SVG, etc.) are generated by Next.js at build-time, uploaded to AWS S3, then served & cached by CDN in a long TTL.
  • Dynamic pages (/:username, /follow, etc.) are rendered (SSR) by Next.js server on-demand, at runtime, with API calls, then served & cached by CDN in a short TTL.

Because the CDN cache pages by token (user-specific data) and short TTL (fresh data), the hit rate is low.

Solutions

Guiding by the philosophy of JAMstack, based on the restrictions [1][2] of the tech stack we used, we can do the optimization in stages.

Stage 1

  • Separate public and user-specific data into different API queries;
  • Serving dynamic pages only with public data in SSR (server-side rendering), and queries user-specific data in CSR (client-side rendering);
  • Increase the TTL and remove the token-based cache strategy from CDN;

Stage 2

  • Use getStaticProps and getStaticPaths (with fallback: true) to serve dynamic pages in iSSG (Incremental Static Site Generation);

References

[1] iSSG may bad for SEO: loading indicator will be shown if the page has never been rendered before;

[2] Need to refactor API queries: next-with-apollo uses getInitialProps and still not support for getStatic* methods

[3] https://nextjs.org/blog/next-9-3#fallback-true

[4] https://static-tweet.now.sh/

@robertu7 robertu7 added the enhancement New feature or request label May 5, 2020
@robertu7
Copy link
Contributor Author

robertu7 commented May 5, 2020

@guoliu
Copy link
Contributor

guoliu commented May 5, 2020

Great summary! And very cool techniques with iSSG.

I think stage 1 might be the most significant, as it already satisfy the philosophy of JAMstack, and we can already start utilizing CDN.

Stage 2 should be an optional plus, since it speeds up the process from SSR server to CDN. iSSG is not really static webpages that can be cached in CDN, it's a cache inside SSR server. But it's definitely a cool technique worth trying: vercel/next.js#11552

@robertu7
Copy link
Contributor Author

robertu7 commented May 6, 2020

One thought: Disable SSR for protected routes (e.g. /me/*) to offload Next.js servers since they don't need to be indexed by search engines.

@guoliu
Copy link
Contributor

guoliu commented May 19, 2020

@guoliu
Copy link
Contributor

guoliu commented May 19, 2020

pattern of seperating SSR & SPA fragments

It looks like there's no common ways of defining directives for client side, and it is also a non-trivial logic to mark certain fields as SPA only, skip them during SSR, and reassemble then during SPA.

I think splitting SSR and SPA fragments at component level makes more sense, and gives us more control.

For example, we can leave the current fragment pattern unchanged, and use Component.fragments.spa, Component.fragments.client or Component.fragments.private for SPA fragments. Then, the parent component can decide how to assemble them and fetch with <Query ssr={false} />.

@guoliu guoliu added this to To do in Enhancements & Bugs via automation Aug 11, 2020
@guoliu guoliu moved this from To do to In progress in Enhancements & Bugs Aug 11, 2020
@guoliu guoliu closed this as completed Sep 16, 2020
Enhancements & Bugs automation moved this from In progress to Done Sep 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
No open projects
Development

No branches or pull requests

3 participants