Our Global Presence
Canada
57 Sherway St,
Stoney Creek, ON
L8J 0J3
India
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
USA
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
Next.js 13 has landed in a somewhat confusing way. Many remarkable things have been added; however, a good part is still Beta. Nevertheless, the Beta features give us important signals on how the future of Next.js will be shaped, so there are good reasons to keep a close eye on them, even if you’re going to wait to adopt them.
This article is part of a series of experiences about the Beta features. Let’s play with Server Components today.
Making server components the default option is arguably the boldest change made in Next.js 13. The goal of server component is to reduce the size of JS shipped to the client by keeping component code only on the server side. I.e., the rendering happens and only happens on the server side, even if the loading of the component is triggered on the client side (via client-side routing). It’s quite a big paradigm shift.
It feels quite “reasearch-y” by then, so it was shocking when seeing that Next.js is already betting its future on it now. Time flies and the fantastic engineers from React must have done some really great work.
npx create-next-app@latest --experimental-app --ts --eslint next13-server-components
Let’s have some fun playing with the project.
The first difference noticed is that a new app folder now sits along with old friend page. They’ll save the routing changes to another article, but what’s worth mentioning for now is that every component under the app folder is, by default, a server component, meaning that it’s rendered on the server side, and its code stays on the server side.
Let’s create our very first server component now:
// app/server/page.tsx export default function Server() { console.log('Server page rendering: this should only be printed on the server'); return ( <div> <h1>Server Page</h1> <p>My secret key: {process.env.MY_SECRET_ENV}</p> </div> ); }
If you access the /server route, whether by a fresh browser load or client-side routing, you’ll only see the line of log printed in your server console but never in the browser console. The environment variable value is fetched from the server side as well.
Looking at network traffic in the browser, you’ll see the content of the Server component is loaded via a remote call which returns an octet stream of JSON data of the render result:
{ ... "childProp": { "current": [ [ "$", "div", null, { "children": [ ["$", "h1", null, { "children": "Server Page" }], [ "$", "p", null, { "children": ["My secret key: ", "abc123"] } ] ] } ] ] } }
Rendering a server component is literally an API call to get serialized virtual DOM and then materialize it in the browser.
The most important thing to remember is that server components are for rendering non-interactive content, so there are no event handlers, no React hooks, and no browser-only APIs.
The most significant benefit is you can freely access any backend resource and secrets in server components. It’s safer (data don’t leak) and faster (code doesn’t leak).
To make a client component, you’ll need to mark it so explicitly with use client:
// app/client/page.tsx 'use client'; import { useEffect } from 'react'; export default function Client() { console.log( 'Client page rendering: this should only be printed on the server during ssr, and client when routing' ); useEffect(() => { console.log('Client component rendered'); }); return ( <div> <h1>Client Page</h1> {/* Uncommenting this will result in an error complaining about inconsistent rendering between client and server, which is very true */} {/* <p>My secret env: {process.env.MY_SECRET_ENV}</p> */} </div> ); }
As you may already anticipate, this gives you a similar behavior to the previous Next.js versions.
When the page is first loaded, it’s rendered by SSR, so you should see the first log in the server console; during client-side routing, both log messages will appear in the browser console.
One of the biggest differences between Server Component and SSR is that SSR is at page level, while Server Component, as its name says, is at component level. This means you can mix and match server and client components in a render tree as you wish.
// A server page containing client component and nested server component // app/mixmatch/page.tsx import Client from './client'; import NestedServer from './nested-server'; export default function MixMatchPage() { console.log('MixMatchPage rendering'); return ( <div> <h1>Server Page</h1> <div className="box"> <Client message="A message from server"> <NestedServer /> </Client> </div> </div> ); }
// app/mixmatch/client.tsx 'use client'; import { useEffect } from 'react'; export default function Client({ message, children, }: { message: string; children: React.ReactNode; }) { console.log('Client component rendering'); return ( <div> <h2>Client Child</h2> <p>Message from parent: {message}</p> <div className="box-red">{children}</div> </div> ); }
// app/mixmatch/nested-server.tsx export default function NestedServer() { console.log('Nested server component rendering'); return ( <div> <h3>Nested Server</h3> <p>Nested server content</p> </div> ); }
In a mixed scenario like this, server and client components get rendered independently, and the results are assembled by React runtime. Props passed from server components to client ones are serialized across the network (and need to be serializable).
One caution you need to take is that if a server component is directly imported into a client one, it silently degenerates into a client component.
Let’s revise the previous example slightly to observe it:
// app/degenerate/page.tsx import Client from './client'; export default function DegeneratePage() { console.log('Degenerated page rendering'); return ( <div> <h1>Degenerated Page</h1> <div className="box-blue"> <Client message="A message from server" /> </div> </div> ); }
// app/degenerate/client.tsx 'use client'; import NestedServer from './nested-server'; export default function Client({ message }: { message: string }) { console.log('Client component rendering'); return ( <div> <h2>Client Child</h2> <p>Message from parent: {message}</p> <div className="box-blue"> <NestedServer /> </div> </div> ); }
// app/degenerated/nested-server.tsx export default function NestedServer() { console.log('Nested server component rendering'); return ( <div> <h3>Degenerated Server</h3> <p>Degenerated server content</p> </div> ); }
If you check out the log, you’ll see NestedServer has “degenerated” and is now rendered by the browser.
For more information and to develop web applications using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”.
To develop custom web apps using React JS, please visit our technology page.
Content Source:
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
© 2024 — HK Infosoft. All Rights Reserved.
© 2024 — HK Infosoft. All Rights Reserved.
T&C | Privacy Policy | Sitemap