<h1 dir="auto">Examples bug report</h1>
<h2 dir="auto">Example name</h2>
<p dir="auto">with-material-ui</p>
<h2 dir="auto">Describe the bug</h2>
<p dir="auto">There is two "single source of truth" for material ui.<br>
One coming from here, with-material-ui and one here :<br>
<a href="https://github.com/mui-org/material-ui/blob/master/examples/nextjs">https://github.com/mui-org/material-ui/blob/master/examples/nextjs</a></p>
<h2 dir="auto">Expected behavior</h2>
<p dir="auto">Only one repo, the other one pointing to the first.</p>
<h2 dir="auto">Summary</h2>
<p dir="auto">Allow Next.js to become fully hybrid by providing methods to do both static generation and server-side rendering on a per-page basis.</p>
<ul dir="auto">
<li>Two new per-page data fetching methods
<ul dir="auto">
<li><code class="notranslate">getStaticProps</code> - Opt-in to static generation (SSG) at <code class="notranslate">next build</code> time.</li>
<li><code class="notranslate">getServerSideProps</code> - Opt-in to server-side rendering (SSR) which renders on-demand.</li>
</ul>
</li>
<li>A new method for statically generating (SSG) a set of routes from dynamic sources
<ul dir="auto">
<li><code class="notranslate">getStaticPaths</code> - Return list of parameters for dynamic routes to do static generation (SSG)</li>
</ul>
</li>
</ul>
<p dir="auto">This RFC exclusively discusses API additions. All new functionality is completely backwards compatible and can be incrementally adopted. This RFC introduces no deprecations.</p>
<h2 dir="auto">Background</h2>
<p dir="auto">When building websites or web applications you generally have to choose between 2 strategies: Static generation (SSG) or server-side rendering (SSR).</p>
<p dir="auto">Next.js instead lets you build hybrid applications that allow you to choose per-page which strategy is used. Starting with Next.js 9, pages without <code class="notranslate">getInitialProps</code> get <a href="https://nextjs.org/blog/next-9#automatic-static-optimization" rel="nofollow">statically optimized</a> and output as <code class="notranslate">.html</code> files upon <code class="notranslate">next build</code>.</p>
<p dir="auto">However, you might want to do data fetching while generating static pages for your specific use case.</p>
<p dir="auto">For example, to statically generate marketing pages from a CMS or a blog section of the site.</p>
<p dir="auto">Using <code class="notranslate">getInitialProps</code> would opt you into SSR in that case.</p>
<p dir="auto">Next.js currently has a <code class="notranslate">next export</code> command, that makes the application fully SSG, losing the hybrid nature of Next.js.</p>
<p dir="auto">If you use <code class="notranslate">next export</code> with <code class="notranslate">getInitialProps</code> there is another problem that surfaces. <code class="notranslate">getInitialProps</code> is called at build time (which is great), but then when you use <code class="notranslate">next/link</code> to move between pages <code class="notranslate">getInitialProps</code> is called client-side, instead of using the <code class="notranslate">next export</code> result.</p>
<p dir="auto">This also means the data source (CMS / API endpoint) is called directly on client-side transitions, if your data source is down, client-side transitions break while moving between pages.</p>
<p dir="auto">We've collaborated with heavy users of SSG and <code class="notranslate">next export</code> in Next.js like HashiCorp (thanks <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/jescalan/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/jescalan">@jescalan</a>) and extensively investigated the right constraints for introducing two new data fetching methods: <code class="notranslate">getStaticProps</code> and <code class="notranslate">getServerSideProps</code>. But also a way to provide parameters to statically generate static pages for dynamic routes: <code class="notranslate">getStaticPaths</code> (replacement for <code class="notranslate">exportPathMap</code> that is per-page).</p>
<p dir="auto">These new methods have many advantages over the <code class="notranslate">getInitialProps</code> model as there is a clear distinction between what will become SSG vs SSR.</p>
<ul dir="auto">
<li><code class="notranslate">getStaticProps</code> marks the page to be statically generated at build time (when running <code class="notranslate">next build</code>)</li>
<li><code class="notranslate">getStaticPaths</code> allows for returning a list of parameters to generate at build time for dynamic routes</li>
<li><code class="notranslate">getServerSideProps</code> marks the page to be server-side rendered on every request and is the most similar to the current <code class="notranslate">getInitialProps</code> behavior when using a server.</li>
</ul>
<p dir="auto">Separating these methods also allows us to provide the correct context object that can be typed using TypeScript. When you opt for a specific rendering strategy you get the correct values, currently with <code class="notranslate">getInitialProps</code> you have to guess what is available on SSG vs SSR when using TypeScript.</p>
<p dir="auto">Furthermore, by making these methods explicit, it'll allow us to document the different trade-offs more clearly.</p>
<h2 dir="auto">Implementation</h2>
<p dir="auto">Note that all these methods are top-level on the page component file and can't be nested, similar to <code class="notranslate">getInitialProps</code>.</p>
<h3 dir="auto"><code class="notranslate">getStaticProps</code></h3>
<p dir="auto">Using <code class="notranslate">getStaticProps</code> means the page will be rendered statically at build time (SSG).</p>
<p dir="auto">This new method will allow you to do data fetching for a page that will be statically generated into a <code class="notranslate">.html</code> file at <code class="notranslate">next build</code> time.</p>
<p dir="auto">Next.js will also automatically generate a JSON file that holds the result of <code class="notranslate">getStaticProps</code> at <code class="notranslate">next build</code> time. This is being used for client-side routing.</p>
<p dir="auto">When client-side routing through <code class="notranslate">next/link</code> or <code class="notranslate">next/router</code>, Next.js will fetch this JSON file to get the props needed to render the page client-side.</p>
<p dir="auto">Properties are returned under a <code class="notranslate">props</code> key so that other options can be introduced in the future.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// pages/index.js

// getStaticProps is only called server-side
// In theory you could do direct database queries
export async function getStaticProps(context) {
  return {
    // Unlike `getInitialProps` the props are returned under a props key
    // The reasoning behind this is that there's potentially more options
    // that will be introduced in the future.
    // For example to allow you to further control behavior per-page.
    props: {}
  };
}"><pre class="notranslate"><span class="pl-c">// pages/index.js</span>

<span class="pl-c">// getStaticProps is only called server-side</span>
<span class="pl-c">// In theory you could do direct database queries</span>
<span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">getStaticProps</span><span class="pl-kos">(</span><span class="pl-s1">context</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Unlike `getInitialProps` the props are returned under a props key</span>
    <span class="pl-c">// The reasoning behind this is that there's potentially more options</span>
    <span class="pl-c">// that will be introduced in the future.</span>
    <span class="pl-c">// For example to allow you to further control behavior per-page.</span>
    <span class="pl-c1">props</span>: <span class="pl-kos">{</span><span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The <code class="notranslate">context</code> will contain:</p>
<ul dir="auto">
<li><code class="notranslate">params</code> - The parameters when on a dynamic route.</li>
</ul>
<h3 dir="auto"><code class="notranslate">getStaticPaths</code></h3>
<p dir="auto">This is an extension on <code class="notranslate">getStaticProps</code> usage for dynamic routes.</p>
<p dir="auto"><code class="notranslate">getStaticPaths</code> replaces the need for having a <code class="notranslate">exportPathMap</code> and works per-page.</p>
<p dir="auto">Since you might want to statically generate a list of urls that have a dynamic parameter, like in the example below a <code class="notranslate">slug</code>. Next.js will provide a <code class="notranslate">getStaticPaths</code> method that allows for returning a list of urls. Since it's a <code class="notranslate">async</code> method you can also fetch that list from a data source like your CMS.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// pages/blog/[slug].js

// `getStaticProps` gets a `params` object holding the dynamic parameters
// For `/blog/hello-world` it would look like `{ slug: 'hello-world }`
export async function getStaticProps({ params }) {
  return {
    props: {}
  };
}

// `getStaticPaths` allows the user to return a list of parameters to
// render to HTML at build time.
export async function getStaticPaths() {
  return {
    paths: [
      // This renders /blog/hello-world to HTML at build time
      { params: { slug: &quot;hello-world&quot; } }
    ]
  };
}"><pre class="notranslate"><span class="pl-c">// pages/blog/[slug].js</span>

<span class="pl-c">// `getStaticProps` gets a `params` object holding the dynamic parameters</span>
<span class="pl-c">// For `/blog/hello-world` it would look like `{ slug: 'hello-world }`</span>
<span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">getStaticProps</span><span class="pl-kos">(</span><span class="pl-kos">{</span> params <span class="pl-kos">}</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-kos">{</span>
    <span class="pl-c1">props</span>: <span class="pl-kos">{</span><span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-c">// `getStaticPaths` allows the user to return a list of parameters to</span>
<span class="pl-c">// render to HTML at build time.</span>
<span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">getStaticPaths</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-kos">{</span>
    <span class="pl-c1">paths</span>: <span class="pl-kos">[</span>
      <span class="pl-c">// This renders /blog/hello-world to HTML at build time</span>
      <span class="pl-kos">{</span> <span class="pl-c1">params</span>: <span class="pl-kos">{</span> <span class="pl-c1">slug</span>: <span class="pl-s">"hello-world"</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<h4 dir="auto">Fallback</h4>
<p dir="auto">In many cases you might not want to pre-render every possible route in your application at build-time (for example if you have millions of products). For this reason Next.js will automatically generate a <code class="notranslate">fallback</code> page that is a render of the page without data (so that a loading state can be shown) for when the page hasn’t been generated yet.</p>
<p dir="auto">The exact behavior of serving will be:</p>
<ul dir="auto">
<li>Incoming request
<ul dir="auto">
<li>Next.js checks if the path was generated at build time
<ul dir="auto">
<li>If the path was generated
<ul dir="auto">
<li>serve directly</li>
</ul>
</li>
<li>If the path was not generated
<ul dir="auto">
<li>Serve the fallback
<ul dir="auto">
<li>Next.js renders the page (with data) in the background and adds it to the list of generated pages</li>
<li>Subsequent request to the same path will serve the generated page</li>
<li>This ensures that users always have a fast experience and never have slow TTFB from server-rendering while preserving fast builds and static-generation properties</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p dir="auto">In case you want paths that weren’t generated at build time to result in a 404 that is also possible by returning <code class="notranslate">fallback: false</code> from <code class="notranslate">getStaticPaths</code></p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// `getStaticPaths` allows the user to return a list of parameters to
// render to HTML at build time.
export async function getStaticPaths() {
  return {
    // Opt-out of the described fallback behavior
    fallback: false,
    paths: [
      // This renders /blog/hello-world to HTML at build time
      { params: { slug: &quot;hello-world&quot; } }
    ]
  };
}"><pre class="notranslate"><span class="pl-c">// `getStaticPaths` allows the user to return a list of parameters to</span>
<span class="pl-c">// render to HTML at build time.</span>
<span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">getStaticPaths</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Opt-out of the described fallback behavior</span>
    <span class="pl-c1">fallback</span>: <span class="pl-c1">false</span><span class="pl-kos">,</span>
    <span class="pl-c1">paths</span>: <span class="pl-kos">[</span>
      <span class="pl-c">// This renders /blog/hello-world to HTML at build time</span>
      <span class="pl-kos">{</span> <span class="pl-c1">params</span>: <span class="pl-kos">{</span> <span class="pl-c1">slug</span>: <span class="pl-s">"hello-world"</span> <span class="pl-kos">}</span> <span class="pl-kos">}</span>
    <span class="pl-kos">]</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<h3 dir="auto"><code class="notranslate">getServerSideProps</code></h3>
<p dir="auto">When using <code class="notranslate">getServerSideProps</code>, the page is not statically generated (SSG) and instead renders on-demand on every request to the server (SSR).</p>
<p dir="auto">Next.js will also automatically expose an API endpoint that returns the result of calling <code class="notranslate">getServerSideProps</code>. This is being used for client-side routing.</p>
<p dir="auto">When client-side routing through <code class="notranslate">next/link</code> or <code class="notranslate">next/router</code>, Next.js will fetch this exposed API endpoint to get the JSON data that is turned into the props needed to render the page client-side.</p>
<p dir="auto">This method is the most similar to the current <code class="notranslate">getInitialProps</code>, with the main difference being <code class="notranslate">getServerSideProps</code> is always executed server-side instead of in the browser. Either on server-side rendering or the API fetch when client-side routing.</p>
<p dir="auto">Similarly to <code class="notranslate">getStaticProps</code> the properties are returned under a <code class="notranslate">props</code> key.</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// pages/index.js

// getServerSideProps is only called server-side
// In theory you could do direct database queries
export async function getServerSideProps(context) {
  return {
    // Unlike `getInitialProps` the props are returned under a props key
    // The reasoning behind this is that there's potentially more options
    // that will be introduced in the future.
    // For example to allow you to further control behavior per-page.
    props: {}
  };
}"><pre class="notranslate"><span class="pl-c">// pages/index.js</span>

<span class="pl-c">// getServerSideProps is only called server-side</span>
<span class="pl-c">// In theory you could do direct database queries</span>
<span class="pl-k">export</span> <span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">getServerSideProps</span><span class="pl-kos">(</span><span class="pl-s1">context</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-kos">{</span>
    <span class="pl-c">// Unlike `getInitialProps` the props are returned under a props key</span>
    <span class="pl-c">// The reasoning behind this is that there's potentially more options</span>
    <span class="pl-c">// that will be introduced in the future.</span>
    <span class="pl-c">// For example to allow you to further control behavior per-page.</span>
    <span class="pl-c1">props</span>: <span class="pl-kos">{</span><span class="pl-kos">}</span>
  <span class="pl-kos">}</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The <code class="notranslate">context</code> will contain:</p>
<ul dir="auto">
<li><code class="notranslate">params</code> - The parameters on a dynamic route</li>
<li><code class="notranslate">req</code> - The HTTP request object</li>
<li><code class="notranslate">res</code> - The HTTP response object</li>
<li><code class="notranslate">query</code> - The query string (not entirely sure about this one, but probably needed)</li>
</ul>
<hr>
<p dir="auto">Authored by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/timneutkens/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/timneutkens">@timneutkens</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/Timer/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/Timer">@Timer</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/ijjk/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/ijjk">@ijjk</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/lfades/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/lfades">@lfades</a>. Collaborated with <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/rauchg/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/rauchg">@rauchg</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/jescalan/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/jescalan">@jescalan</a> and others <g-emoji class="g-emoji" alias="rocket" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f680.png">🚀</g-emoji></p>