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

Add example + discussion points: static export with dynamic routes #6963

Closed
wants to merge 3 commits into from
Closed

Add example + discussion points: static export with dynamic routes #6963

wants to merge 3 commits into from

Conversation

baer
Copy link

@baer baer commented Apr 8, 2019

Over the last year, I have used (and loved) Next.js to build several large React applications. I'm somewhat of an evangelist - it's an outstanding platform and an incredibly well-run project.

There is a body of uses cases, however, that are not well covered by the current examples or documentation: statically deployed applications where the data can't be determined at build time. Applications like these are common when page data is time-sensitive, too-large, user-specific, or can't reliably be fetched from a build server. Even when data is readily available, some developers prefer to use the App Shell Model, where an application bundle contains fully compiled, but empty, pages.

Despite my best efforts, Using Next.js for applications like this requires a fair amount of complexity. I'd like to use this PR as a place to discuss:

  • Whether this is a scenario that Next.js can/should/will support
  • What PRs are possible that could push some of this complexity into the framework

If the Zeit/Next.js team decides that additional work to make this easier is not a priority, this example at least gives some guidance to other developers who would like to try similar things.

Areas for discussion:

Note: I've already included most of these discussion points as comments in the code. I figured that, if the PR is merged ahead of or without changes to Next.js, these would be good guideposts for other developers.

Configuration for route translation

Applications with dynamically defined routes need configuration in three places:

  • next.config.js - The exportPathMap defines the set of routes to export
  • server.js - The development server needs the set of routes, and their translation into Next.js pages, in the Express path format
  • serve.json (or other CDN configuration) - The CDN needs the set of routes, and their translation into static paths, in the format required by that CDN

In my application, I've defined redirects in a file called redirects.js which I then read from Express and the next.config.js. I also use that file to generate the configuration for Serve.

Handling of URI parameters for static pages

When re-hydrating a statically compiled Next.js page, Next.js will ignore query parameters. For example, for the URL http://myapp.com?page=1, this.props.router.query is {}. The reason for this is that if Next.js were to process the parameters, React's virtual DOM might not match the statically rendered one which can cause React to fail in weird ways. One solution (proposed in #4341) is to trigger a second render if there are query parameters.

The Link tag

For dynamic pages (in a static application), using the Link component without an as property causes a full-page refresh. Since the symptom is, just a slightly slower page transition, this is an easy bug to introduce - especially now that the Next.js dev server compiles pages in real-time. Depending on whether your state (Redux, MobX, etc.) is stored in memory, and if performance is critical to your app, this could be anything from a non-issue to a show-stopper.


Again, thank you for your hard work and for your contributions the the ecosystem!

@baer baer requested a review from lfades as a code owner April 8, 2019 22:56
@github-actions
Copy link
Contributor

github-actions bot commented Apr 8, 2019

Stats from current PR

Click to expand stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 13.7s 13.3s -472ms
node_modules Size 44 MB 44 MB
Total Bundle (main, webpack, commons) Size 202 kB 202 kB
Total Bundle (main, webpack, commons) gzip Size 65.9 kB 65.9 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 8.85 kB 8.85 kB
Client _error gzip Size 3.31 kB 3.31 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 174 kB 174 kB
Client commons gzip Size 56.8 kB 56.8 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Base Rendered Size 1.34 kB 1.34 kB
Build Dir Size 339 kB 339 kB
Click to expand serverless stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 14.4s 14.2s -194ms
node_modules Size 44 MB 44 MB
Total Bundle (main, webpack, commons) Size 202 kB 202 kB
Total Bundle (main, webpack, commons) gzip Size 65.9 kB 65.9 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 8.85 kB 8.85 kB
Client _error gzip Size 3.31 kB 3.31 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 174 kB 174 kB
Client commons gzip Size 56.8 kB 56.8 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Serverless pages/link Size 307 kB 307 kB
Serverless pages/link gzip Size 79.1 kB 79.1 kB
Serverless pages/index Size 300 kB 300 kB
Serverless pages/index gzip Size 77.2 kB 77.2 kB
Serverless pages/_error Size 300 kB 300 kB
Serverless pages/_error gzip Size 77 kB 77 kB ⚠️ +1 B
Serverless pages/routerDirect Size 300 kB 300 kB
Serverless pages/routerDirect gzip Size 77.3 kB 77.3 kB ⚠️ +1 B
Serverless pages/withRouter Size 300 kB 300 kB
Serverless pages/withRouter gzip Size 77.4 kB 77.4 kB ⚠️ +1 B
Build Dir Size 1.72 MB 1.72 MB

@baer
Copy link
Author

baer commented Apr 8, 2019

Apologies for the first commit, I hadn't installed git hooks, and it let me commit all of my files without running prettier and standard. It was just linty stuff :)

@github-actions
Copy link
Contributor

github-actions bot commented Apr 8, 2019

Stats from current PR

Click to expand stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 14.6s 14s -613ms
node_modules Size 44 MB 44 MB
Total Bundle (main, webpack, commons) Size 202 kB 202 kB
Total Bundle (main, webpack, commons) gzip Size 65.9 kB 65.9 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 8.85 kB 8.85 kB
Client _error gzip Size 3.31 kB 3.31 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 174 kB 174 kB
Client commons gzip Size 56.8 kB 56.8 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Base Rendered Size 1.34 kB 1.34 kB
Build Dir Size 339 kB 339 kB
Click to expand serverless stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 14.8s 14.8s -59ms
node_modules Size 44 MB 44 MB
Total Bundle (main, webpack, commons) Size 202 kB 202 kB
Total Bundle (main, webpack, commons) gzip Size 65.9 kB 65.9 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 8.85 kB 8.85 kB
Client _error gzip Size 3.31 kB 3.31 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 174 kB 174 kB
Client commons gzip Size 56.8 kB 56.8 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Serverless pages/link Size 307 kB 307 kB
Serverless pages/link gzip Size 79.1 kB 79.1 kB ⚠️ +2 B
Serverless pages/index Size 300 kB 300 kB
Serverless pages/index gzip Size 77.2 kB 77.2 kB ⚠️ +1 B
Serverless pages/_error Size 300 kB 300 kB
Serverless pages/_error gzip Size 77 kB 77 kB ⚠️ +1 B
Serverless pages/routerDirect Size 300 kB 300 kB
Serverless pages/routerDirect gzip Size 77.3 kB 77.3 kB ⚠️ +1 B
Serverless pages/withRouter Size 300 kB 300 kB
Serverless pages/withRouter gzip Size 77.4 kB 77.4 kB
Build Dir Size 1.72 MB 1.72 MB

@chirag04
Copy link

chirag04 commented Apr 9, 2019

This is amazing! Is it assuming that the app is dynamic(fetches data from backend) but the data itself is static?

Not sure if I understand how this will work when data changes

@baer
Copy link
Author

baer commented Apr 9, 2019

@chirag04 - thanks for your comment. No, there is no assumption that the data is static. The dynamic routes are generated from the Express.js-style routes in the redirects.js file, and the pages pull dynamic content on the client-side in componentDidMount. There is no reason you can't add static data with getInitialProps, like any other Next.js app, if you'd like.

@github-actions
Copy link
Contributor

github-actions bot commented Apr 9, 2019

Stats from current PR

Click to expand stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 12.5s 12.2s -314ms
node_modules Size 44 MB 44 MB
Total Bundle (main, webpack, commons) Size 202 kB 202 kB
Total Bundle (main, webpack, commons) gzip Size 65.9 kB 65.9 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 8.85 kB 8.85 kB
Client _error gzip Size 3.31 kB 3.31 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 174 kB 174 kB
Client commons gzip Size 56.8 kB 56.8 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Base Rendered Size 1.34 kB 1.34 kB
Build Dir Size 339 kB 339 kB
Click to expand serverless stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 12.8s 12.8s -7ms
node_modules Size 44 MB 44 MB
Total Bundle (main, webpack, commons) Size 202 kB 202 kB
Total Bundle (main, webpack, commons) gzip Size 65.9 kB 65.9 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 8.85 kB 8.85 kB
Client _error gzip Size 3.31 kB 3.31 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 174 kB 174 kB
Client commons gzip Size 56.8 kB 56.8 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Serverless pages/link Size 307 kB 307 kB
Serverless pages/link gzip Size 79.1 kB 79.1 kB
Serverless pages/index Size 300 kB 300 kB
Serverless pages/index gzip Size 77.2 kB 77.2 kB ⚠️ +1 B
Serverless pages/_error Size 300 kB 300 kB
Serverless pages/_error gzip Size 77 kB 77 kB ⚠️ +2 B
Serverless pages/routerDirect Size 300 kB 300 kB
Serverless pages/routerDirect gzip Size 77.3 kB 77.3 kB ⚠️ +1 B
Serverless pages/withRouter Size 300 kB 300 kB
Serverless pages/withRouter gzip Size 77.4 kB 77.4 kB ⚠️ +1 B
Build Dir Size 1.72 MB 1.72 MB

@baer baer changed the title Add example for static export with dynamic routes Add example + discussion points: static export with dynamic routes Apr 17, 2019
@github-actions
Copy link
Contributor

Stats from current PR

Click to expand stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 12.1s 11.3s -723ms
node_modules Size 43.9 MB 43.9 MB
Total Bundle (main, webpack, commons) Size 210 kB 210 kB
Total Bundle (main, webpack, commons) gzip Size 68.5 kB 68.5 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 9.66 kB 9.66 kB
Client _error gzip Size 3.52 kB 3.52 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 183 kB 183 kB
Client commons gzip Size 59.4 kB 59.4 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Base Rendered Size 1.34 kB 1.34 kB
Build Dir Size 580 kB 580 kB
Click to expand serverless stats
zeit/next.js canary baer/next.js feature/static-export-dynamic-routes-example Change
Build Duration 13.1s 12.8s -368ms
node_modules Size 43.9 MB 43.9 MB
Total Bundle (main, webpack, commons) Size 210 kB 210 kB
Total Bundle (main, webpack, commons) gzip Size 68.5 kB 68.5 kB
Client _app Size 2.49 kB 2.49 kB
Client _app gzip Size 1.04 kB 1.04 kB
Client _error Size 9.66 kB 9.66 kB
Client _error gzip Size 3.52 kB 3.52 kB
Client pages/index Size 298 B 298 B
Client pages/index gzip Size 235 B 235 B
Client pages/link Size 3.28 kB 3.28 kB
Client pages/link gzip Size 1.49 kB 1.49 kB
Client pages/routerDirect Size 426 B 426 B
Client pages/routerDirect gzip Size 304 B 304 B
Client pages/withRouter Size 408 B 408 B
Client pages/withRouter gzip Size 293 B 293 B
Client main Size 24.4 kB 24.4 kB
Client main gzip Size 7.89 kB 7.89 kB
Client commons Size 183 kB 183 kB
Client commons gzip Size 59.4 kB 59.4 kB
Client webpack Size 1.49 kB 1.49 kB
Client webpack gzip Size 774 B 774 B
Serverless pages/link Size 337 kB 337 kB
Serverless pages/link gzip Size 87.4 kB 87.4 kB ⚠️ +1 B
Serverless pages/index Size 330 kB 330 kB
Serverless pages/index gzip Size 85.4 kB 85.4 kB ⚠️ +2 B
Serverless pages/_error Size 331 kB 331 kB
Serverless pages/_error gzip Size 85.3 kB 85.3 kB ⚠️ +1 B
Serverless pages/routerDirect Size 330 kB 330 kB
Serverless pages/routerDirect gzip Size 85.5 kB 85.5 kB ⚠️ +2 B
Serverless pages/withRouter Size 330 kB 330 kB
Serverless pages/withRouter gzip Size 85.6 kB 85.6 kB ⚠️ +1 B
Build Dir Size 2.12 MB 2.12 MB

@timneutkens
Copy link
Member

timneutkens commented May 27, 2019

Hey @baer, I ended up writing #7355 based on this feedback and a bunch of other feedback 👍 Let's discuss more there if needed 👌

Over the last year, I have used (and loved) Next.js to build several large React applications. I'm somewhat of an evangelist - it's an outstanding platform and an incredibly well-run project.

Thank you 😌🙏

@baer baer deleted the feature/static-export-dynamic-routes-example branch May 28, 2019 20:47
@baer baer mentioned this pull request Dec 4, 2019
@vercel vercel locked as resolved and limited conversation to collaborators Feb 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants