Recently, I explored and studied the related content of front-end engineering. In order to improve the first screen rendering speed and SEO effect, I went back to the server side rendering in order to improve the structure of front and back end separation.
This article is mainly about how to use the Next. Js framework to implement server-side rendering, which will greatly improve SEO and first screen rendering speed, and may be used someday, right?
1. Server Rendering (SSR)
The core point of differentiation between SSR (Server Side Render) and CSR (Client Side Render) is simply that the complete HTML document is assembled on the Server or in the browser.
Another concept of SSR is isomorphic rendering, you can see the discussion in Zhihu: what is isomorphic rendering of the front end?
In simple terms, isomorphic rendering is a piece of code. The server first generates HTML and initialization data through the server rendering (SSR). After the client gets the code and initialization data, His client-side activation of THE HTML DOM through patch and event binding is called isomorphic rendering.
The principle of SSR, this article will not repeat, interested friends recommend reading this article: “Thoroughly understand server rendering – SSR principle”
Second, the Next. Js
Next. Js is a React framework for production environments that requires no configuration and provides best development practices for all functionality required by production environments by default: static and server-side rendering support, TypeScript support, smart packaging, route preloading, and more.
At the same time, Next. Js also provides the following SDK out of the box to assist in developing Web applications:
As you can see from SSR Principles, configuring to support server rendering is a bit of a hassle, but with Next. Js, you can easily adapt to support existing Web application server rendering.
Whether to adopt server rendering or not still needs to consider the benefits comprehensively. After all, server rendering will increase the computing overhead of the server, and its stability is worse than CSR.
Create the Next. Js application
Initializing a Next. Js application can be done quickly directly through scaffolding:
npx create-next-app@latest --ts
# or
yarn create next-app --typescript
Copy the code
The project name is asked midway through and the required modules are automatically installed
After yarn Dev is executed, you need to manually open the browser to http://localhost:3000, and the following page is displayed:
The contents of the home page correspond to the./pages/index.tsx file
The initial directory structure is as follows:
. ├ ─ ─ pages// Use reduced-form routing (filesystem routing)│ ├── ├─ TSX │ ├─ API/ / API| ├ ─ ─ hello. Ts │ └ ─ ─ index. The TSX/ / home page├ ─ ─ the public// Public resources│ ├─ ├─ ├─ favicon. Ico │ ├─ Exercises/ / style│ │ ├ ─ ─ Home. The module. CSS └ ─ ─ globals. CSS ├ ─ ─ next - env. Which s// Next related TS definition├ ─ ─ next. Config. Js// next.js custom configuration├── ├─ ├─ download.exe └─ ├─ download.exe └─ download.exe └─ download.exeCopy the code
4. Page routing
Typically, our Web applications are multi-page, multi-route, and therefore involve jumping between pages, so it’s important to be familiar with the route usage of next.js.
Next. Js is a specified route based on the file system and corresponds to the./pages directory. When a page file is added to the./pages directory, next. js automatically identifies and registers the corresponding file on the route
4.1 Index Route
Next. Js will automatically register the “index” file in the folder as the home page of the folder
The file path | Corresponding routing |
---|---|
pages/index.tsx |
/ |
pages/blog/index.tsx |
/blog |
4.2 Nested routine by
Next.js supports routing for nested files, and if you create a nested folder structure, the files will still be automatically routed in the same way.
The file path | Corresponding routing |
---|---|
pages/blog/first-post.tsx |
/blog/first-post |
pages/dashboard/settings/username.tsx |
/dashboard/settings/username |
4.3 Dynamic Parameter Routing
Common in article details pages such as blogs, the id of the article is dynamically changed, and the corresponding named parameters can be resolved in Next
The file path | Corresponding routing | 🌰 |
---|---|---|
pages/blog/[slug].js |
/blog/:slug |
/blog/hello-world |
pages/[username]/settings.js |
/:username/settings |
/foo/settings |
pages/post/[...all].js |
/post/* |
/post/2021/id/title |
For more information on dynamic routing resolution, see: nextjs.org/docs/routin…
4.4 Route Redirection
As mentioned before, the route preloading function in next.js needs to use the Next /link provided by next.js, written as follows:
<Link href="/blog/hello-world">
<a>The first article</a>
</Link>
Copy the code
Jumps between application pages can be wrapped with the tag.
The value of the href attribute is the path to the page string or URL object:
import Link from 'next/link'
function Articles({ articles }) {
return (
<ul>
{articles.map((article) => (
<li key={article.id}>
<Link
href={{
pathname: '/article/ [slug] ',query: { slug: article.slug}}} >,
<a>{article.title}</a>
</Link>
</li>
))}
</ul>)}export default Articles
Copy the code
If you need to redirect a route through JS, you can use the useRouter Hook in the Next/Router provided by next.js.
4.5 Code splitting and preloading
With the routing function of Next. Js, it can automatically load the code required by the current page as required, and automatically preload the links of its own application in the page.
This means that you render the home page without initially providing code for other pages, and ensures that even if you have hundreds of pages, the home page loads quickly on demand.
The code that loads only the page you request also means that the page becomes independent, and if one page throws an error, the rest of the application can still work.
In the production version of next.js, every time a Link component appears in the browser viewport, next.js automatically prefetches the linked page code in the background. When you click the link, the code for the target page loads in the background, and the page conversion is almost instantaneous.
Static resources
All static resources can be placed in the./public directory, and next.js automatically registers routes for the files in it, in filesystem fashion, similar to Page routes.
5.1 Image Elements
The general picture in the webpage is written as follows:
<img src="/images/logo.png" alt="logo" />
Copy the code
This will require manual optimizations, such as loading on demand, error handling, etc.
With this in mind, Next. Js provides Next/Image right out of the box to ease the developer’s burden.
In fact, it can be used for reference. In other projects, an Image component can be encapsulated for unified Image processing to improve r&d efficiency.
import Image from 'next/image'
const YourComponent = () = > (
<Image
src="/images/profile.jpg"// Image file pathheight={144}// The required size with the correct aspect ratiowidth={144}
alt="Image Alt"
/>
)
export default YourComponent;
Copy the code
5.2 Meta data
The Meta data of the web page, i.e. the content in the HTML ->head tag
Next. Js provides Next/Head head content for declaratively writing web pages.
import Link from 'next/link'
import Head from 'next/head'
export default function FirstPost() {
return (
<>
<Head>
<meta charset="UTF-8" />
<title>First Post</title>
<link rel="shortcut icon" href="/favicon.ico" />
<meta name="keywords" content="Web Keywords" />
<meta name="description" content="Page Description" />
<meta name="author" content="DYBOY,[email protected]" />
<meta name="version" content="1.0" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2319527_hng3o947ocv.css" />
<link rel="stylesheet" href="/style/fancybox.css" />
<link rel="stylesheet" href="/style/app.css" />
<script src="/scripts/jquery.js"></script>
</Head>
<h1>First Post</h1>
<h2>
<Link href="/">
<a>Back to home</a>
</Link>
</h2>
</>)}Copy the code
In addition, if we need to modify < HTML lang=”zh-cn”>, we can create pages/_document.js file, and inherit and unify the public content output of all web pages through the way of “custom document”.
5.3 JS Script File
For example, we used the Jquery tripartite library, although we could have written it directly in the component:
<script src="/scripts/jquery.js"></script>
Copy the code
However, including the script in this way does not make it clear when other JavaScript code retrieved on the same page is loaded. If a particular script blocks rendering and delays the loading of page content, performance can be significantly affected.
Therefore, it can be optimized by Next/Script
import Link from 'next/link'
import Head from 'next/head'
import Script from 'next/script'
export default function FirstPost() {
return (
<>
<Head>
<title>First Post</title>
</Head>
<Script
src="/scripts/jquery.js"
strategy="lazyOnload"/ / setjsLoading modeonLoad={()= >
// the callback function after the script file is loaded
console.log(`script loaded correctly`)
}
/>
<h1>First Post</h1>
<h2>
<Link href="/">
<a>Return to the home page</a>
</Link>
</h2>
</>)}Copy the code
5.4 the CSS file
Next. Js already has built-in support for CSS and SASS, allowing developers to introduce style files by introducing.css and.sass files, as well as Tailwind CSS.
You need to manually install the SASS module
yarn add sass
Copy the code
By default, csS-in-JS is also supported. Using the Gravitation-jsx module, you can write CSS directly to the React component without affecting other components.
If modularity is required, the CSS file name should be in *.module.css format.
import styles from './layout.module.css'
export default function Layout({ children }) {
return <div className={styles.container}>{children}</div>
}
Copy the code
Global CSS injection, written in the./styles directory of the root directory, also introduces global style files only in the./pages/_app.tsx file
import '.. /styles/globals.css' // Introduce global styles
import type { AppProps } from 'next/app'
function MyApp({ Component, pageProps }: AppProps) {
return <Component {. pageProps} / >
}
export default MyApp
Copy the code
Next. Js uses PostCSS to compile CSS and customize PostCSS.
6. Pre-rendering and data acquisition
Next, js support:
- Prerender on the server
- Static page generation and server rendering
- Static generation with data and no data
- Some predefined methods (lifecycle functions) inject data
6.1 pre-rendered
By default, Next. Js prerenders every page. This means that Next. Js generates HTML ahead of time for each page, and pre-rendering leads to better performance and SEO.
Each generated HTML is associated with the minimum amount of JavaScript code required for that page. When the browser loads the page, its JavaScript code runs and makes the page fully interactive.
The comparison between pre-rendered and non-pre-rendered is as follows:
6.2 Static Generation and Server Rendering
Next. Js supports two forms of pre-rendering: static generation and server-side rendering
- Static generation: A pre-render method that generates HTML at build time. The pre-rendered HTML is then reused on each request.
- Server-side rendering: A pre-rendering method that generates HTML on each request.
6.3 Obtaining Data
(1) Obtain data during static generation
Sometimes you need to get some data before a server builds a static page, and you can use the getStaticProps method.
Inside the page component, also export a getStaticProps method:
export default function HomePage(props) {... }// Export the asynchronous data fetch method
export async function getStaticProps() {
// Get data from databases, apis, files, etc
const data = ...
// The returned argument is assigned to the homepath of the HomePage component based on the key value
return {
props:... }}Copy the code
Note that this method is exported only within the page component
(2) Data acquisition during server rendering
For example, the user’s personal center page does not need SEO optimization. Its data usually needs to be updated and obtained in real time. Therefore, SSR is adopted
Similar to how we get data at build time:
export default function HomePage(props) {... }// Export the asynchronous data fetch method
export async function getServerSideProps() {
// Get data from databases, apis, files, etc
const data = ...
// The returned argument is assigned to the homepath of the HomePage component based on the key value
return {
props:... }}Copy the code
(3) Data acquisition during client rendering
If you don’t need to get data during “pre-rendering”, that is, you don’t need to get data during “static generation” and “server side rendering”, you can write code related to network request in the corresponding page component generation.
The Next. Js team provides a recommended useSWR hook based on React Hooks that handle caching, revalidation, focus tracking, interval recapture, and more.
A simple example is as follows:
import useSWR from 'swr'
function Profile() {
const { data, error } = useSWR('/api/user', fetch)
if (error) return <div>failed to load</div>
if(! data)return <div>loading...</div>
return <div>hello {data.name}!</div>
}
Copy the code
Like some enclosed Hooks for requests, useSWR also supports custom request libraries. By default, the fetch pollyfill module (Unfetch) is used. The official Chinese documentation is very clear: swr.vercel.app/ zh-cn /docs/…
Dynamic routing
I talked about pre-rendering, but what if it’s pre-rendering for dynamic routing? You rely on the getStaticPaths method to generate a list of pages for dynamic routes.
// ./pages/post/[id].tsx
import Layout from '.. /.. /components/layout'
export default function Post({id, article}) {
return (
<Layout>
<Head>
<title>{article.title}</title>
</Head>
{article.title}
<br />
{id}
<br />
{article.date}
</Layout>)}export async function getStaticPaths() {
// Returns a list of all possible article ids
const paths = [
{
params: {
id: 'ssg-ssr'}}, {params: {
id: 'pre-rendering'}}]return {
paths,
fallback: false.// If no value is found for id in Paths, point to the 404 page}}export async function getStaticProps({ params }) {
// Get the necessary article data via params.id
// parmas is the parameter object in the route
const article = getContentById(parmas.id);
return {
props: {
id,
artcile,
}
}
}
Copy the code
For more information about fallback, see fallback props
Create a 404 page, file path:./pages/404.tsx
export default function Custom404() {
return <h1>404 - Page Not Found</h1>
}
Copy the code
Eight, BFF API
The./pages/ API /hello.ts file in the initialized directory structure is an API page with the same route as the page
import type { NextApiRequest, NextApiResponse } from 'next'
type Data = {
name: string
}
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.status(200).json({ name: 'John Doe'})}Copy the code
In the./pages/ API/directory, front-end developers write desirable API applications called Serverless Functions, similar to bytes of “light services”
Nine, deployment,
Vercel is officially recommended for one-click automated build deployment
The build is performed first, and optimizations are automatically made during the build
Yarn build // Run the next build commandCopy the code
Then start the service:
Yarn start // The next start -p 8080 command is executedCopy the code
In a production environment, PM2 is used to manage the daemons
Then use Nginx as the gateway, configure the domain name, SSL, map to the local port 8080.
Developing more
Next. Js has more details and apis, you can refer to the Next. Js API documentation
In addition to Next. Js, there’s Razzle. Js too.
Recommended reading:
- Understanding Server Rendering from top to bottom – SSR Principles
- Summary and Sharing of Reconstruction Practice of Meizu official Website Based on next.js
- SWR – React Hooks library for Data requests
- React Server (SSR) Framework next. Js
- Next. Js Application Development Practice
conclusion
Through to the Next. Preliminary started using js, SSR did help to improve the user experience, such as some documents, website, marketing web site, personal highly recommend this way, but its shortcoming is also very obvious, server stability will be reduced, the stability can be increased costs rise, and compared with its advantages, is worth the investment!
Next. Js builds some of the production configurations as they are initialized, and it feels great right out of the box for developers!
The first wechat official account of this article is DYBOY. If you are interested in it, you can click the following button and play with it