PageSourceSearch

https://uploadcare.com/blog/component---src-templates-post-index-t…-tutorial-index-mdx-84cd96da649f0b722f94.js

js uploadcare.com collected 2026-10-02 02:20:50 UTC 82,995 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkuploadcare_blog=self.webpackChunkuploadcare_blog||[]).push([[2459],{519:function(n,e,t){t.d(e,{F:function(){return r}});var a=t(6540),s=t(6493),o=t.n(s),l=t(560),c=t(5284),p=t(8876),i=t(2976);const r=n=>{let e=n.postData,t=n.orgData;const s=((n,e)=>{var t,a;const s=(0,p.x)(n.author,e),o=(0,i.cj)(n.jsonLdImageUrl);return{"@context":"https://schema.org/","@type":"Article",image:[n.jsonLdImageUrl,(0,i.pX)({...o,operations:{...o.operations,crop:"4:3"}}),(0,i.pX)({...o,operations:{...o.operations,crop:"1:1"}}),(0,i.pX)({...o,operations:{...o.operations,crop:"16:9"}})],url:n.url,headline:n.title,description:null!==(t=n.description)&&void 0!==t?t:"",datePublished:n.datePublished,dateModified:n.dateModified,author:{"@type":s["@type"],name:s.name,url:s.url,image:s.image},publisher:{"@type":"Corporation",url:e.url,name:e.name,logo:{"@type":"ImageObject",url:e.logoUrl}},mainEntityOfPage:{"@type":"WebPage","@id":n.url},articleBody:null!==(a=n.excerpt)&&void 0!==a?a:""}})(e,t),r=function(n){return!!n.jsonLdFaqItems&&!!n.jsonLdFaqHeadline}(e)?(n=>({"@context":"https://schema.org/","@type":"FAQPage",name:n.jsonLdFaqHeadline,headline:n.jsonLdFaqHeadline,mainEntity:n.jsonLdFaqItems.map(n=>({"@type":"Question",name:n.question,acceptedAnswer:{"@type":"Answer",text:n.answer}}))}))(e):null,u=((n,e)=>({"@context":"https://schema.org/","@type":"BreadcrumbList",itemListElement:[{"@type":"ListItem",position:1,name:"Uploadcare",item:o()(e.url,(0,l.withPrefix)("/"))},{"@type":"ListItem",position:2,name:n.category.title+" Category",item:o()(e.url,(0,l.withPrefix)("/"+c.AL.category+"/"+n.category.id+"/"))},{"@type":"ListItem",position:3,name:n.title,item:n.url}]}
1))(e,t),d=[s,r,u].filter(Boolean);return a.createElement("script",{type:"application/ld+json"},JSON.stringify(d))}},2040:function(n,e,t){t.d(e,{N:function(){return d}});var a=t(6540),s=t(780),o=t(149),l=t(4788),c=t(9592);const p=s.default.div.withConfig({displayName:"ArticleFinisher__Root",componentId:"sc-1w5kdkw-0"})(n=>{let e=n.theme,t=e.tablet,a=e.laptop;return"\n  width: 100%;\n  max-width: "+l.i+"px;\n  margin: 40px auto 0;\n  padding-top: 40px;\n  border-top: 1px solid #F1F2F3;\n  text-align: center;\n\n  "+t()+" {\n    display: flex;\n    gap: 80px;\n    align-items: center;\n    text-align: left;\n  }\n\n  "+a()+" {\n    margin: 60px auto 0;\n  }\n"}),i=s.default.div.withConfig({displayName:"ArticleFinisher__Body",componentId:"sc-1w5kdkw-1"})(["font-size:16px;line-height:1.5;"]),r=s.default.p.withConfig({displayName:"ArticleFinisher__Title",componentId:"sc-1w5kdkw-2"})(["margin-bottom:4px;font-size:16px;font-weight:600;line-height:1.4;color:#000;"]),u=(0,s.default)(o.$n).withConfig({displayName:"ArticleFinisher__StyledButton",componentId:"sc-1w5kdkw-3"})(n=>"\n  margin-top: 20px;\n\n  "+(0,n.theme.tablet)()+" {\n    margin-top: 0;\n    margin-left: auto;\n  }\n"),d=()=>a.createElement(p,null,a.createElement(i,null,a.createElement(r,null,"Ready to get started?"),a.createElement("p",null,"Join developers who use Uploadcare to build file handling quickly and reliably.")),a.createElement(u,{forwardedAs:c.N_,href:c.I6.SignUp,themeType:o.Mr.PRIMARY,size:o.Ni.SMALL,dataAnalytics:"btn_article-finisher_signup"},"Sign up for free"))},2993:function(n,e,t){t.r(e),t.d(e,{Head:function(){return y},default:function(){return b}});var a=t(8453),s=t(6540);function o(n){const e=Object.assign({h2:"h2",p:"p",em:"em",a:"a",span:"span",strong:"strong",code:"code",img:"img",h3:"h3",table:"table",thead:"thead",tr:"tr",th:"th",tbody:"tbody",td:"td"},(0,a.R)(),n.components);return s.createElement(s.Fragment,null,s.createElement(e.h2,null,"Intro"),"\n",s.createElement(e.p,null,"Based on my experience of working with different frameworks in different programming languages, I can say that Developer Experience (DX) is very important when you want to get your creative programming solutions to life. When you get excited by your new project idea, you don’t want to spend hours configuring app bundling, code-splitting or server-side rendering for your new React project. That is where Next.js framework comes in handy to reduce the amount of boilerplate you write and let you focus on delivering real value to your users."),"\n",s.createElement(e.p,null,"In this brief tutorial, you will find everything you need to take off with Next."),"\n",s.createElement(e.p,null,s.createElement(e.em,null,"I assume you have some basic knowledge of React, and Visual Studio Code is installed on your machine.")),"\n",s.createElement(e.p,null,"Let’s start from what Next.js is about..."),"\n",s.createElement(e.h2,null,"What is Next.js"),"\n",s.createElement(e.p,null,"Next.js is an open-source React framework which was first released in 2016 as a JavaScript toolchain with out-of-the-box functionality requiring no setup. Since that time, Next has become a popular production-ready framework with a huge community."),"\n",s.createElement(e.p,null,"Even though Next.js has everything preconfigured for a good start, it’s flexible enough to provide the choice between NPM and Yarn, JavaScript and TypeScript, CSS and SCSS, static export and serverless deployment model."),"\n",s.createElement(e.h2,null,"React vs. Next.js – What’s the difference"),"\n",s.createElement(e.p,null,"You probably know that React is a library and not a framework, meaning that it needs some additional building blocks for developing production-grade apps. To name a few, a router component, an app bundler and a style engine. Next.js provides those missing pieces of the puzzle but still allows to fully utilize everything people love React for."),"\n",s.createElement(e.h2,null,"How to create a Next.js app"),"\n",s.createElement(e.p,null,"To start with Next, make sure you have Node.js > 10 installed on your machine."),"\n",s.createElement(e.p,null,"The quickest way to create a Next app is to use ",s.createElement(e.a,{href:"https://nextjs.org/docs/api-reference/create-next-app"},"create-next-app"),"."),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="shell">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-shell"><code class="language-shell">$ npx create-next-app first-nextjs-app</code></pre></div>'}}),"\n",s.createElement(e.p,null,"The ",s.createElement(e.strong,null,"npx")," installer takes care about installing ",s.createElement(e.strong,null,"create-next-app")," itself and creating our first Next app with all the dependencies required."),"\n",s.createElement(e.p,null,"Once the installer has finished, the app can be found in the first-nextjs-app folder. Let’s run the app to make sure everything is fine with the installation:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="shell">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-shell"><code class="language-shell">$ <span class="token builtin class-name">cd</span> first-nextjs-app\n$ <span class="token function">yarn</span> dev</code></pre></div>'}}),"\n",s.createElement(e.p,null,"If everything goes well, Next should start the app in the development mode on ",s.createElement(e.code,null,"localhost:3000"),". If you open it, you will see a page with welcome text and some links to documentation."),"\n",s.createElement(e.p,null,"Thanks to ",s.createElement(e.a,{href:"https://nextjs.org/blog/next-9-4#fast-refresh"},"Fast Refresh technique")," integrated into Next, if you change anything in your code, for example a line of text in ",s.createElement(e.code,null,"pages/index.js"),", the changes will get onto the page instantly without losing current app state."),"\n",s.createElement(e.p,null,"As a naturally curious person, I often catch myself exploring the content of a generated project. If you’re curious enough too, let’s look at what’s inside of the first-nextjs-app folder."),"\n",s.createElement(e.h2,null,"Next.js app folder structure"),"\n",s.createElement(e.p,null,"Open the project folder in VSCode:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="shell">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-shell"><code class="language-shell">$ <span class="token builtin class-name">cd</span> first-nextjs-app\n$ code <span class="token builtin class-name">.</span></code></pre></div>'}}),"\n",s.createElement(e.img,{src:"https://ucarecdn.com/ddc348c1-116c-4e40-b703-c0691f553531/default-nextjs-app-folder-structure-screenshot.png",alt:"Default Next.js app folder structure screenshot",width:"293",height:"389",isFirst:!0}),"\n",s.createElement(e.p,null,"Here is what we have:"),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,"yarn.lock")," - by default, create-next-app utilizes yarn package manager, so yarn.lock file contains information about all installed third-party dependencies. Prefer npm? Then pass ",s.createElement(e.strong,null,"--use-npm")," parameter to the create-next-app tool."),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,"next.config.js")," - is used for Next settings primarily."),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,".eslintrc")," - eslint configuration. By default, it configures the linter to validate the code base against Next best practices and Core Web Vitals but you can extend it with additional plugins."),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,"styles/")," - for your app styles, obviously."),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,"public/")," - for static content which will be publicly available on https://your-domain/, e.g. a logo. Please be careful and don’t put any configs or code files in there."),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,"pages/")," - page routes."),"\n",s.createElement(e.p,null,s.createElement(e.strong,null,"pages/api")," - API routes."),"\n",s.createElement(e.p,null,"Next doesn’t enforce how you should structure your code files. You can create ",s.createElement(e.strong,null,"components/")," folder for React components and ",s.createElement(e.strong,null,"redux/")," for your Redux store-related code. It’s up to you, but from my experience, it’s better to keep the first level of the project as clean as possible, so you may consider putting all your app logic in a separate top level folder."),"\n",s.createElement(e.h2,null,"How to install React Developer Tools"),"\n",s.createElement(e.p,null,"You know that Next.js is a React framework, so you can make development more pleasant by installing the React Developer Tools plugin for your browser. To do that follow your browser-specific link and press install ",s.createElement(e.a,{href:"https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en"},"For Chrome")," ",s.createElement(e.a,{href:"https://addons.mozilla.org/en-US/firefox/addon/react-devtools/"},"For Firefox"),"\nAfter installing the browser extension, the React Developer Tools icon will appear in your extensions bar and the corresponding ",s.createElement(e.strong,null,"Component")," tab will be added to your browser developer tools window."),"\n",s.createElement(e.img,{src:"https://ucarecdn.com/838ccf29-b516-4ec0-9a51-760fe49704fe/react-dev-tools-component-tree-screenshot.png",alt:"React Dev Tools component tree screenshot",width:"1179",height:"643"}),"\n",s.createElement(e.h2,null,"How to style React components in Next.js"),"\n",s.createElement(e.p,null,"Next supports a few styling approaches out of the box, such as inline styles, standard CSS file includes and CSS modules."),"\n",s.createElement(e.h3,null,"Inline styles"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="jsx">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-jsx"><code class="language-jsx"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">style</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token literal-property property">color</span><span class="token operator">:</span> <span class="token string">\'red\'</span><span class="token punctuation">,</span> <span class="token literal-property property">fontWeight</span><span class="token operator">:</span> <span class="token string">\'bold\'</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">red text</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"Note that the properties of the inline styles should be camelCased, so we use ",s.createElement(e.strong,null,"fontWeight")," instead of ",s.createElement(e.strong,null,"font-weight")," in this particular case."),"\n",s.createElement(e.h3,null,"CSS file include"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="css">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-css"><code class="language-css"><span class="token comment">/* styles.css */</span>\n<span class="token selector">.red</span> <span class="token punctuation">{</span>\n  <span class="token property">color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="jsx">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-jsx"><code class="language-jsx"><span class="token comment">/* component.jsx */</span>\n<span class="token keyword">import</span> <span class="token string">\'styles.css\'</span><span class="token punctuation">;</span>\n\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>red<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">Red</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre></div>'}}),"\n",s.createElement(e.h3,null,"CSS modules"),"\n",s.createElement(e.p,null,"To use CSS file as a module, name it ",s.createElement(e.strong,null,"*.module.css")),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="css">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-css"><code class="language-css"><span class="token comment">/* component.module.css */</span>\n<span class="token selector">.red</span> <span class="token punctuation">{</span>\n  <span class="token property">color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="jsx">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-jsx"><code class="language-jsx"><span class="token comment">/* component.jsx */</span>\n<span class="token keyword">import</span> classes <span class="token keyword">from</span> <span class="token string">\'component.module.css\'</span><span class="token punctuation">;</span>\n\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">className</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>classes<span class="token punctuation">.</span>red<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">Red</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"With this approach, the entire CSS file is treated as an object where every class in the file has its corresponding object property."),"\n",s.createElement(e.p,null,"Read more about how to use CSS Modules in ",s.createElement(e.a,{href:"https://github.com/css-modules/css-modules"},"its documentation on Github"),s.createElement(e.strong,null,"."),"\nIf you prefer the SASS preprocessor for structuring styles, Next provides seamless integration with ",s.createElement(e.a,{href:"https://github.com/sass/sass"},"sass"),". To use it, just install sass and give your style file ",s.createElement(e.strong,null,".scss")," or ",s.createElement(e.strong,null,".sass")," extension."),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="shell">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-shell"><code class="language-shell">
1$ <span class="token function">yarn</span> <span class="token function">add</span> <span class="token parameter variable">-D</span> sass</code></pre></div>'}}),"\n",s.createElement(e.p,null,"It’s also possible to use the CSS Modules approach with SASS. And since Next.js is React-based, you can use any CSS-in-JS approach by installing corresponding packages."),"\n",s.createElement(e.h2,null,"Next.js routing system"),"\n",s.createElement(e.p,null,"Scripts which are located in the ",s.createElement(e.strong,null,"pages/")," folder of the app are converted into routes automatically. There are two types of routes in Next, such as page routes and API routes. Let’s try both of them."),"\n",s.createElement(e.h3,null,"Page routes"),"\n",s.createElement(e.p,null,"Create ",s.createElement(e.strong,null,"pages/time.js")," with the following content:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="jsx">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">\'react\'</span><span class="token punctuation">;</span>\n\n<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Time</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n  <span class="token keyword">return</span> <span class="token punctuation">(</span>\n    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">style</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>\n      <span class="token literal-property property">display</span><span class="token operator">:</span> <span class="token string">\'flex\'</span><span class="token punctuation">,</span>\n      <span class="token literal-property property">flexDirection</span><span class="token operator">:</span> <span class="token string">\'column\'</span><span class="token punctuation">,</span>\n      <span class="token literal-property property">justifyContent</span><span class="token operator">:</span> <span class="token string">\'center\'</span><span class="token punctuation">,</span>
1\n      <span class="token literal-property property">alignItems</span><span class="token operator">:</span> <span class="token string">\'center\'</span><span class="token punctuation">,</span>\n      <span class="token literal-property property">height</span><span class="token operator">:</span> <span class="token string">\'100vh\'</span>\n    <span class="token punctuation">}</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">\n      Time: </span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toLocaleTimeString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token plain-text">\n    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>\n  <span class="token punctuation">)</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"If you then open the ",s.createElement(e.code,null,"localhost:3000/time")," page you will see current time in the page center."),"\n",s.createElement(e.h3,null,"API routes"),"\n",s.createElement(e.p,null,"Create the ",s.createElement(e.strong,null,"time.js")," file in the ",s.createElement(e.strong,null,"pages/api/")," folder:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="js">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-js"><code class="language-js"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">handler</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n  res<span class="token punctuation">.</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span>\n    <span class="token literal-property property">time</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toLocaleTimeString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>\n  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"After running the app in the development mode, the created API handler will become available on `localhost:300/api/time and will respond with JSON content like this:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="json">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><span class="token property">"time"</span><span class="token operator">:</span> <span class="token string">"8:43:48 AM"</span><span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"API handlers are isolated but they have access to the request and response objects."),"\n",s.createElement(e.h2,null,"Next.js application configuration"),"\n",s.createElement(e.p,null,"There are two officially supported ways to store app configuration in Next, such as runtime configuration with ",s.createElement(e.strong,null,"next.config.js")," and build-time configuration with ",s.createElement(e.strong,null,".env")," files."),"\n",s.createElement(e.h3,null,"Runtime configuration"),"\n",s.createElement(e.p,null,"The runtime configuration is primarily used for storing Next.js own settings. Even though it’s possible to use it for app settings too, it’s not recommended because the runtime configuration affects performance and prevents the page from being automatically statically optimized."),"\n",s.createElement(e.h3,null,"Built-in time configuration"),"\n",s.createElement(e.p,null,"In a simple case scenario, it’s enough to have a single ",s.createElement(e.strong,null,".env.local")," configuration file for production and development environments with variables defined the following way:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="bash">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-bash"><code class="language-bash"><span class="token comment"># .env.local</span>\n<span class="token assign-left variable">APP_DOMAIN</span><span class="token operator">=</span><span class="token string">"example.com"</span>\n<span class="token assign-left variable">APP_URL</span><span class="token operator">=</span><span class="token string">"https://<span class="token variable">${APP_DOMAIN}</span>/"</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"As you may see, we can use previously defined variables for forming new variables."),"\n",s.createElement(e.p,null,"Then all environment variables can be accessed from the code this way:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="js">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-js"><code class="language-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">APP_URL</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"Don’t forget to include your ",s.createElement(e.strong,null,".env.local")," file to ",s.createElement(e.strong,null,".gitignore")," to keep your passwords and other private configuration in secret.\nBut ",s.createElement(e.strong,null,".env.local")," is not the only possible config file. Below is a list of config files which you may want to use in more complex scenarios."),"\n",s.createElement(e.table,null,s.createElement(e.thead,null,s.createElement(e.tr,null,s.createElement(e.th,null,"File"),s.createElement(e.th,null,"Purpose"),s.createElement(e.th,null,"Overrides"))),s.createElement(e.tbody,null,s.createElement(e.tr,null,s.createElement(e.td,null,".env"),s.createElement(e.td,null,'Environment-independent defaults, e.g. DATABASE_TYPE="mysql"'),s.createElement(e.td,null,"nothing")),s.createElement(e.tr,null,s.createElement(e.td,null,".env.development"),s.createElement(e.td,null,"Development-only configuration, used by ",s.createElement(e.strong,null,"yarn dev")),s.createElement(e.td,null,".env")),s.createElement(e.tr,null,s.createElement(e.td,null,".env.production"),s.createElement(e.td,null,"Production-only configuration, used by ",s.createElement(e.strong,null,"yarn start")),s.createElement(e.td,null,".env")),s.createElement(e.tr,null,s.createElement(e.td,null,".env.test"),s.createElement(e.td,null,"Test-only configuration, used by test engines, such as Jest, Cypress, etc."),s.createElement(e.td,null,".env")),s.createElement(e.tr,null,s.createElement(e.td,null,".env.local"),s.createElement(e.td,null,"The main app configuration which is not stored in Git and is loaded for every environment except the test environment."),s.createElement(e.td,null,".env")))),"\n",s.createElement(e.p,null,"One important thing to keep in mind is that by default, your environment variables are only available from server-side code. To utilize a variable on frontend, prefix it with ",s.createElement(e.strong,null,"NEXT_PUBLIC_"),", for example:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="bash">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-bash"><code class="language-bash"><span class="token assign-left variable">NEXT_PUBLIC_APP_URL</span><span class="token operator">=</span><span class="token string">"https://example.com"</span></code></pre></div>'}}),"\n",s.createElement(e.h2,null,"How to implement dynamic imports in Next.js"),"\n",s.createElement(e.p,null,"Dynamic ",s.createElement(e.strong,null,"import()")," of JavaScript modules allows you to split bundled code into a few smaller chunks and load them on-demand (aka lazy-loading)."),"\n",s.createElement(e.p,null,"Here is an example where our crypto module provides the encrypt() function which we load dynamically to encrypt the password:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="js">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-js"><code class="language-js"><span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">\'../lib/crypto\'</span><span class="token punctuation">)</span>\n  <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> encrypt <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>\n    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">encrypt</span><span class="token punctuation">(</span><span class="token string">\'PASSWORD\'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"And what if we need to load a React component dynamically and not just a module with some business logic? For this purpose, React itself has a solution, called ",s.createElement(e.strong,null,"React.lazy()"),". Unfortunately, it doesn’t support server-side rendering, so we can’t use it with Next."),"\n",s.createElement(e.p,null,"Good news is that Next has its own solution for dynamic import of React components - ",s.createElement(e.strong,null,"next/dynamic"),".\nTo see how dynamic imports w
1ork in Next, let’s create a component in the ",s.createElement(e.strong,null,"components/")," folder of our Next app with the following content:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="jsx">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-jsx"><code class="language-jsx"><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">DynamicComponent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n  <span class="token keyword">return</span> <span class="token punctuation">(</span>\n    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">Loaded dynamically</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>\n  <span class="token punctuation">)</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"Now we can use the created component from a page like this:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="jsx">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-jsx"><code class="language-jsx"><span class="token keyword">
1import</span> dynamic <span class="token keyword">from</span> <span class="token string">\'next/dynamic\'</span><span class="token punctuation">;</span>\n\n<span class="token keyword">const</span> DynamicComponent <span class="token operator">=</span> <span class="token function">dynamic</span><span class="token punctuation">(</span>\n  <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">\'../components/DynamicComponent\'</span><span class="token punctuation">)</span>\n<span class="token punctuation">)</span><span class="token punctuation">;</span>\n\n<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Home</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n  <span class="token keyword">return</span> <span class="token punctuation">(</span>\n    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">\n      </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">DynamicComponent</span></span> <span class="token punctuation">/></span></span><span class="token plain-text">\n    </span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>\n  <span class="token punctuation">)</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"Easy, right? But let’s imagine a situation when you found a beautiful image gallery component for your app which doesn’t support server-side rendering. In that case you may want to load the component on client only by passing ",s.createElement(e.strong,null,"ssr: false")," as a ",s.createElement(e.strong,null,"dynamic()")," function parameter:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="js">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-js"><code class="language-js"><span class="token keyword">const</span> DynamicComponent <span class="token operator">=</span> <span class="token function">dynamic</span><span class="token punctuation">(</span>\n  <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">
1import</span><span class="token punctuation">(</span><span class="token string">\'../components/DynamicComponent\'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>\n  <span class="token punctuation">{</span> <span class="token literal-property property">ssr</span><span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span>\n<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(e.h2,null,"How to deploy Next.js app"),"\n",s.createElement(e.h3,null,"Static app"),"\n",s.createElement(e.p,null,"Next makes it easy to generate fully-static sites which can be hosted anywhere without the need for a Node engine.\nAll you need to do is add export command to your ",s.createElement(e.strong,null,"package.json")," scripts:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="json">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-json"><code class="language-json"><span class="token punctuation">{</span>\n  <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span>\n    <span class="token property">"export"</span><span class="token operator">:</span> <span class="token string">"next build &amp;&amp; next export"</span>\n  <span class="token punctuation">}</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"And run:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="shell">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-shell"><code class="language-shell">
1$ <span class="token function">yarn</span> <span class="token builtin class-name">export</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"Your static app will be generated in the ",s.createElement(e.strong,null,"out/")," directory of your project. Just deploy the folder content to any static hosting or CDN and that’s it."),"\n",s.createElement(e.p,null,"The problem with static exports is that if your Next app has data requirements, for example it loads blog content from a remote third-party source and visualizes it someway, your static deploy will be based on the current version of the data. You have to re-export your app regularly to reflect the data changes."),"\n",s.createElement(e.p,null,"Please note that API routes are not supported here."),"\n",s.createElement(e.h3,null,"Standalone app with PM2"),"\n",s.createElement(e.p,null,"Alternatively, you can keep your app dynamic and run it as a standalone Node.js app, for example on port 80:"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="shell">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-shell"><code class="language-shell">$ next build <span class="token operator">&amp;&amp;</span> next start <span class="token parameter variable">-p</span> <span class="token number">80</span></code></pre></div>'}}),"\n",s.createElement(e.p,null,"This way you have to restart the app on errors manually and handle server restarts which is not a very convenient approach. Instead, I suggest using a Node process manager, for example ",s.createElement(e.a,{href:"https://pm2.keymetrics.io/"},"pm2"),", to solve these problems."),"\n",s.createElement(e.h3,null,"Standalone app with Docker"),"\n",s.createElement(e.p,null,"If you enjoy using Docker for hosting your apps as many of us do, follow the ",s.createElement(e.a,{href:"https://github.com/vercel/next.js/tree/canary/examples/with-docker"},"with-docker example")," from the official examples. You will find a multi-stage ",s.createElement(e.strong,null,"Dockerfile")," there which is tuned for Next.js apps."),"\n",s.createElement(e.h3,null,"Serveless app"),"\n",s.createElement(e.p,null,"For those who build serverless apps, starting from version 8, Next supports a serverless deployment model where each page in the ",s.createElement(e.strong,null,"pages/")," folder is converted into a standalone lambda function.\nTo enable the serverless mode in Next.js, add the ",s.createElement(e.strong,null,"serverless")," build target through your ",s.createElement(e.strong,null,"next.config.js"),":"),"\n",s.createElement(e.span,{dangerouslySetInnerHTML:{__html:'\n        <div class="gatsby-highlight" data-language="js">\n        <button\n          class="code-copy-button"\n          onclick="navigator.clipboard.writeText(this.nextElementSibling.textContent).then(() => { this.classList.add(\'code-copy-button-activated\'); setTimeout(() => this.classList.remove(\'code-copy-button-activated\'), 3000)});"\n          data-analytics="btn_blog_copy-code"\n        >\n          Copy\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-action-icon"\n          >
1\n            <path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M0 2.489A2.489 2.489 0 0 1 2.489 0h5.973a2.489 2.489 0 0 1 2.49 2.489v.56h.56A2.489 2.489 0 0 1 14 5.538v5.973A2.489 2.489 0 0 1 11.511 14H5.538a2.489 2.489 0 0 1-2.49-2.489v-.56h-.56A2.489 2.489 0 0 1 0 8.462V2.49Zm3.049 7.467V5.538a2.489 2.489 0 0 1 2.489-2.49h4.418v-.56c0-.824-.669-1.492-1.494-1.492H2.49c-.825 0-1.493.668-1.493 1.493v5.973c0 .825.668 1.494 1.493 1.494h.56Zm2.489-5.912c-.825 0-1.494.669-1.494 1.494v5.973c0 .825.669 1.493 1.494 1.493h5.973c.825 0 1.493-.668 1.493-1.493V5.538c0-.825-.668-1.494-1.493-1.494H5.538Z"/>\n          </svg>\n\n          <svg\n            xmlns="http://www.w3.org/2000/svg"\n            width="14"\n            height="14"\n            class="code-copy-button-icon code-copy-button-done-icon"\n          >\n            <path fill="#000" fill-rule="evenodd" clip-rule="evenodd" d="m12.546 3.613-6.849 7.451-4.243-4.156.7-.715L5.66 9.627l6.15-6.691.736.677Z"/>\n          </svg>\n        </button>\n      <pre class="language-js"><code class="language-js"><span class="token comment">// next.config.js</span>\nmodule<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>\n  <span class="token literal-property property">target</span><span class="token operator">:</span> <span class="token string">\'serverless\'</span>\n<span class="token punctuation">}</span></code></pre></div>'}}),"\n",s.createElement(e.h2,null,"To sum up"),"\n",s.createElement(e.p,null,"As you may see, Next.js simplifies development of React apps and helps focusing on the most important things - your app logic and UI. It has everything which is necessary for building modern frontend-rich and API-powered apps. And because of its ability to generate static HTML sites, it’s also suitable for content-only projects, such as blogs and corporate sites."),"\n",s.createElement(e.p,null,"With the latest versions, Next.js not only keeps the developer experience at a high level but it also provides tools for improving visual performance and user experience, which, no doubt, secures a great future ahead for this framework."),"\n",s.createElement(e.h2,null,"Next steps"),"\n",s.createElement(e.p,null,"Nothing works better than practice, so I recommend you come up with a simple project idea and get your hands dirty with Next to cement what you’ve already learned."),"\n",s.createElement(e.p,null,"In case you need some additional resources, refer to ",s.createElement(e.a,{href:"https://nextjs.org/docs"},"the Next.js documentation")," and ",s.createElement(e.a,{href:"https://github.com/vercel/next.js/tree/canary/examples"},"Next.js examples"),".\nAnd if you’re looking for a higher level framework, you may be interested in giving ",s.createElement(e.a,{href:"https://blitzjs.com/"},"Blitz")," a try because it’s inspired by Ruby on Rails and built on top of Next.js."))}var l=function(n){void 0===n&&(n={});const e=Object.assign({},(0,a.R)(),n.components).wrapper;return e?s.createElement(e,n,s.createElement(o,n)):o(n)},c=t(7861),p=t(5284),i=t(4630),r=t(3503),u=t(2040),d=t(519),h=t(2766),g=t(8189),m=t(9674);const v=n=>{var e;let t=n.data,a=n.pageContext,o=n.children;const l=(0,p.tn)(t);return s.createElement(i.P,null,s.createElement(r.B,{lastCrumbText:null!==(e=l.h1Title)&&void 0!==e?e:l.title}),s.createElement(c.n9,{post:l},o),s.createElement(u.N,null),s.createElement(m.v,{author:l.author}),s.createElement(c.Fx,{list:a.relatedPosts.map(p.r9)}))},y=n=>{let e=n.data;const t=(0,h.U)(),a=(0,p.tn)(e);return s.createElement(c.kW,{post:a},s.createElement("link",{rel:"canonical",href:a.url}),s.createElement("meta",{name:"blog-category",content:a.category.title.toLowerCase()}),!!a.isDraft&&s.createElement("meta",{name:"robots",content:"noindex, nofollow"}),!!a.metaRobots&&!a.isDraft&&s.createElement("meta",{name:"robots",content:a.metaRobots}),s.createElement(g.d,{postData:a}),s.createElement(c.uu,{id:a.author.id,firstName:a.author.firstName,lastName:a.author.lastName}),s.createElement(d.F,{postData:a,orgData:t.organization}))};function b(n){return s.createElement(v,n,s.createElement(l,n))}},3503:function(n,e,t){t.d(e,{B:function(){return r}});var a=t(6540),s=t(780),o=t(9592);const l=s.default.div.withConfig({displayName:"styles__BreadcrumbsWrapper",componentId:"sc-1a8j902-0"})(["overflow:hidden;padding:15px 0;font-size:13px;line-height:1.3;white-space:nowrap;text-overflow:ellipsis;color:#858f99;"]),c=(0,s.default)(o.N_).withConfig({displayName:"styles__BreadcrumbsLink",componentId:"sc-1a8j902-1"})(["color:#495560;font-weight:500;text-decoration:none;transition:color 0.2s ease;&:hover{color:#000;}"]),p=s.default.span.withConfig({displayName:"styles__Separator",componentId:"sc-1a8j902-2"})(["margin:0 6px;color:#d6dadd;"]),i=s.default.span.withConfig({displayName:"styles__LastCrumb",componentId:"sc-1a8j902-3"})(["font-weight:500;"]),r=n=>{let e=n.lastCrumbText;return a.createElement(l,null,a.createElement(c,{to:"/"},"Home"),a.createElement(p,null,"/"),a.createElement(c,{to:"/blog/"},"Blog"),a.createElement(p,null,"/"),a.createElement(i,null,e))}},8189:function(n,e,t){t.d(e,{d:function(){return s}});var a=t(6540);const s=n=>{var e;let t=n.postData;return a.createElement(a.Fragment,null,a.createElement("meta",{property:"article:published_time",content:t.datePublished}),a.createElement("meta",{property:"article:modified_time",content:t.dateModified}),a.createElement("meta",{property:"article:section",content:t.category.title}),null===(e=t.tags)||void 0===e?void 0:e.map(n=>a.createElement("meta",{key:n,property:"article:tag",content:n})))}},9674:function(n,e,t){t.d(e,{v:function(){return m}});var a=t(6540),s=t(780),o=t(4788),l=t(9592),c=t(5284);const p=s.default.div.withConfig({displayName:"ArticleAuthorSegment__Root",componentId:"sc-1uyk9m9-0"})(n=>{let e=n.theme.laptop;return"\n  display: grid;\n  grid-template-areas:\n    'avatar written-by'\n    'about about';\n  grid-template-columns: auto 1fr;\n  gap: 15px 20px;\n  align-items: center;\n  width: 100%;\n  max-width: "+o.i+"px;\n  margin: 40px auto 0;\n  padding-top: 40px;\n  border-top: 1px solid #F1F2F3;
1\n  color: #495560;\n\n  "+e()+" {\n    grid-template-areas:\n      'avatar written-by'\n      '. about';\n    gap: 5px 30px;\n    margin: 60px auto 0;\n  }\n"}),i=(0,s.default)(l.$h).withConfig({displayName:"ArticleAuthorSegment__AvatarLink",componentId:"sc-1uyk9m9-1"})(["grid-area:avatar;border-radius:50%;outline:4px solid rgb(2 25 30 / 0%);transition:outline-color 0.2s ease;&:hover{outline-color:rgb(2 25 30 / 6%);}"]),r=s.default.img.withConfig({displayName:"ArticleAuthorSegment__Avatar",componentId:"sc-1uyk9m9-2"})(n=>"\n  display: block;\n  width: 50px;\n  height: 50px;\n  border-radius: 50%;\n  background-color: #f0f1f1;\n\n  "+(0,n.theme.laptop)()+" {\n    width: 60px;\n    height: 60px;\n  }\n"),u=s.default.p.withConfig({displayName:"ArticleAuthorSegment__WrittenBy",componentId:"sc-1uyk9m9-3"})(["grid-area:written-by;display:flex;flex-direction:column;gap:5px;width:fit-content;font-size:13px;font-weight:400;line-height:1.3;"]),d=(0,s.default)(l.FS).withConfig({displayName:"ArticleAuthorSegment__NameLink",componentId:"sc-1uyk9m9-4"})(["font-size:17px;font-weight:500;line-height:1.3;"]),h=s.default.div.withConfig({displayName:"ArticleAuthorSegment__About",componentId:"sc-1uyk9m9-5"})(["grid-area:about;font-size:15px;line-height:1.8;"]),g=s.default.p.withConfig({displayName:"ArticleAuthorSegment__AboutTextLine",componentId:"sc-1uyk9m9-6"})(["& + &{margin-top:1em;}"]),m=n=>{var e;let t=n.author;const s="/"+c.AL.author+"/"+t.id+"/",o="Picture of "+t.fullName,l=t.avatar+"/-/scale_crop/60x60/",m=t.avatar+"/-/scale_crop/60x60/ 1x, "+t.avatar+"/-/scale_crop/120x120/ 2x";return a.createElement(p,null,a.createElement(i,{to:s},a.createElement(r,{alt:o,src:l,srcSet:m})),a.createElement(u,null,a.createElement("span",null,"Written by "),a.createElement(d,{to:s},t.fullName)),a.createElement(h,null,(null!==(e=t.shortAbout)&&void 0!==e?e:t.fullAbout).split("\n").map(n=>a.createElement(g,{key:n},n))))}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.