next.js搭载ant Design框架,服务端渲染步骤详解,页面渲染速度飞起来

3,837 阅读5分钟

1. 从0-1搭建next.js+antDesign框架

react的服务端渲染框架next.js,现在说页面渲染速度被吹上天了,丝滑到无法抗拒,解决了传统的客户端渲染慢的很多性能问题。近期想来试试的话,去官网第一步就是先安装next.js官网的脚手架,

npx create-next-app@latest --typescript

下面会提示你选装哪些配置,选择是否配置tailwind组件库和路由选择等,在APP Router中选择Nopages路由,YesApp路由,因为之前写国际官网时我喜欢用webpack配置多页面应用,有利于seo,框架习惯了pages路由,所以这里也依旧用pages路由吧,还是熟悉的配方~

截屏2023-12-14 18.31.16.png

那么问题来了,然后你会发现tailwind组件库官网如果想使用全部的组件,那么它的收费是249欧,折合人民币2000大洋,免费的用惯了是不是有点抢钱的感觉,

截屏2023-12-14 18.24.08.png

莫慌,那就用常用的ant Design组件库吧,现在已经完全适配了next框架,官网也有详细的步骤,重点是它免费,下面我们来试试,

截屏2023-12-14 18.35.46.png

第一步:安装next脚手架 npx create-next-app my-next-demo

安装脚手架,这里我们选择使用pages路由,不选择tailwind样式:

截屏2023-12-14 18.55.36.png

第二步:安装ant组件库 npm install antd --save

详请参考antd官网

第三步:启动项目npm run dev

在引入ant组件时可能会遇到一些兼容性问题比如

import React from 'react';
import { Button } from 'antd';


const Home = () => (
  <div className="App">
    <Button type="primary">Button</Button>
  </div>
);


export default Home;

就报错了,页面提示SyntaxError: Cannot use import statement outside a module

截屏2023-12-19 13.20.43.png

这个错误因为 import 是 ES6 的模块语法,但是第三方组件库"antd", "@ant-design"等并没有被Next.js 在构建项目时进行编译转换,所以要在 Next.js 项目中,next.config.js 文件,配置项目构建过程中的各种设置。transpilePackages 选项是其中一个配置项,用于告诉 Next.js 哪些包应该被编译。

当你在 Next.js 项目中使用 transpilePackages 配置时,你指定了一组需要被编译(转译)的包的名称列表。这些包通常是第三方库或者其他 npm 包,它们可能使用了 ES6+ 语法或其他 TypeScript 特性,需要被转换成更老版本的 JavaScript 以确保兼容性或支持旧版本的浏览器。

const nextConfig = {
  reactStrictMode: true,
  //指定了一组需要被编译(转译)的包的名称列表。
  transpilePackages: [ "antd", "@ant-design", "rc-util", "rc-pagination", "rc-picker", "rc-notification", "rc-tooltip", "rc-tree", "rc-table" ],
}

module.exports = nextConfig

最后项目启动成功!!!!我们可以随意使用# Ant Design的组件库啦,免费的组件库搭配next.js框架,它不香吗?赶紧的,用起来吧!

2.用next.js去搭建个人博客文章

默认情况下,Next.js 将 预渲染 每个 page(页面)。这意味着 Next.js 会预先为每个页面生成 HTML 文件,而不是由客户端 JavaScript 来完成。预渲染可以带来更好的性能和 SEO 效果。

每个生成的 HTML 文件都与该页面所需的最少 JavaScript 代码相关联。当浏览器加载一个 page(页面)时,其 JavaScript 代码将运行并使页面完全具有交互性。(此过程称为 水合(hydration) 。)

预渲染有两种形式:

第一步,在pages下面搭建创建blog目录,然后新建[slug].tsx文件用于动态路由,根据url中的动态部分渲染不同的页面:

- pages/
  - blog/
    - [slug].tsx
- components/
  - BlogPost.tsx
- markdownFile
  - http1-http2-http3.md
- tsconfig.json

例如,如果你有一个名为 http1-http2-http3.md 的 Markdown 文件,你可以通过 /blog/http1-http2-http3 的路径访问它,Next.js 会自动匹配并渲染对应的页面。

[slug].tsx 文件中,你需要导出 getStaticPathsgetStaticProps 这两个函数,它们负责获取动态路由的参数并渲染对应的页面内容。

import { GetStaticPaths, GetStaticProps } from 'next';
import fs from 'fs';
import path from 'path';
import grayMatter from 'gray-matter';
import {remark} from 'remark';
import remarkHtml from 'remark-html';
import { ParsedUrlQuery } from 'querystring';
import BlogPost from '../../component/blogPost';

interface PostProps {
  data: { [key: string]: any };
  content: string;
}

interface PostParams extends ParsedUrlQuery {
  slug: string;
}

const BlogSlugPage = ({ post }: { post: PostProps }) => {
  return (
    <div>
      <BlogPost post={post} />
    </div>
  );
};

export default BlogSlugPage;

export const getStaticPaths: GetStaticPaths<PostParams> = async () => {
  const postsDirectory = path.join(process.cwd(), 'markdownFile');
  const filenames = fs.readdirSync(postsDirectory);

  const paths = filenames.map((filename) => ({
    params: { slug: filename.replace(/\.md$/, '') },
  }));

  return { paths, fallback: false };
};

export const getStaticProps: GetStaticProps<PostProps, PostParams> = async ({ params }) => {
  const postFilePath = path.join(process.cwd(), 'markdownFile', `${params?.slug}.md`);
  const fileContents = fs.readFileSync(postFilePath, 'utf8');

  const { data, content } = grayMatter(fileContents);

  const processedContent = await remark().use(remarkHtml).process(content);
  const contentHtml = processedContent.toString();

  return {
    props: {
      post: {
        data,
        content: contentHtml,
      },
    },
  };
};

在 Next.js 中,getStaticPathsgetStaticProps 是需要在页面组件文件中进行导出的特殊函数。这两个函数用于构建静态生成(静态页面)的功能。

  • getStaticPaths:用于生成动态路由的路径。它确定了哪些路径在构建时应该被预先渲染(静态生成)。
  • getStaticProps:用于获取页面的静态数据。它用于预先获取页面所需的数据,并在构建时将其注入到页面中。

渲染页面组件 /components/BlogPost.tsx

import React from 'react';
interface PostProps {
  post: {
    data: { [key: string]: any };
    content: string;
  };
}

const BlogPost = ({ post }: PostProps) => {
  return (
    <div>
      <h1>{post.data.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </div>
  );
};

export default BlogPost;

最后在对应的页面可以看到你的制定目录下面的所有.md类型的博客文件啦

截屏2023-12-22 14.57.28.png

如果想用next.js+antDesign写一个个人简历或者个人技术博客可以参考github.com/xiongqianhu…

服务端渲染,相当丝滑~ next项目部署页面 my-technology-website-ll68lbgrm-xiongqianhuas-projects.vercel.app/