百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

太猛了!GIThub大佬总结《Next.js 实践记录》,掀起业内热潮

csdh11 2025-02-26 11:42 6 浏览

背景

因主技术栈使用Vue,部分服务端渲染的项目就自然的选择了使用 Nuxt.js 框架进行开发。近期在尝试进行技术栈更新,所以选择使用 Next.js进行页面开发。目前采用 Next.js 12.13.1 版本,官方最近版本迭代到了 Next.js 13.4

Next.js 是基于React 的服务端渲染框架。

在传统的SPA项目中,例如使用 Vue-cli 创建的项目,最终build生成的静态文件,是基于浏览器渲染的,即所谓的 CSR (Client-side Rendering)。

CSR往往都是单页面应用,即一个HTML文件和若干个js、css文件。打开build后的HTML文件,发现代码很简单,页面和组件的元素都是放在了js里,由js动态渲染到HTML中。CSR模式是目前前端开发项目中应用最为广泛的。

但有些也场景,特别是需要SEO优化的时候,CSR就不太合适了,所以服务端(Server-side Rendering))渲染应运而生,SSR是由服务器将用户请求的页面DOM组装好后,再返回给浏览器,因此通过“查看网页源代码”,是可以看到完整的页面DOM的。

而SSG (Static Site Generation)顾名思义就是静态网站生成,也就是常说的“网页静态化”,除了适合SEO,还很方便CDN加速,比较适合内容相对比较固定的资讯发布类网站。

以下是关于CSR、SSR、SSG的简单对比


先说明依赖包版本

Node.js 16.17.0

next.js 12.13.1

react 18.2.0

react-dom 18.2.0

axios 0.27.2

sass 1.55.0

redux 4.2.0

创建Next.js项目

首先我们先对 Next.js 的项目进行初始化,Next.js 提供了脚手架来帮助我们初始化项目,我们可以执行下面的命令来初始化项目:


npx create-next-app@latest --typescript

其中 next-env.d.ts 是 Next.js 的类型文件,可以保证 ts 选择 Next.js 相关的类型,通常我们不需要对它进行修改,可以在提交后加到 .gitignore 中。next.config.js 是 Next.js 的构建配置,底层也是基于 Webpack 去打包的,我们可以在默认的配置上加上下面的配置来提供别名的能力。


// next.config.js
const path = require("path");

module.exports = {
  reactStrictMode: true,
  swcMinify: true,
  webpack: (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      "@": path.resolve(__dirname),
    };
    return config;
  },
};

tsconfig.json 中我们也需要加一下对应的别名解析识别(baseurl , paths)。

{
  "compilerOptions": {
    "target": "es5",
      "lib": ["dom", "dom.iterable", "esnext"],
      "allowJs": true,
      "skipLibCheck": true,
      "strict": true,
      "forceConsistentCasingInFileNames": true,
      "noEmit": true,
      "esModuleInterop": true,
      "module": "esnext",
      "moduleResolution": "node",
      "resolveJsonModule": true,
      "isolatedModules": true,
      "jsx": "preserve",
      "incremental": true,
      "baseUrl": ".",
      "paths": {
	"@/*": ["./*"]
      }
  },
    "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
    "exclude": ["node_modules"]
}

到这里项目其实就已经初步初始化完成了,我们执行npm run dev打开http://localhost:3000 就可以看到一个 Next.js 的默认服务器端渲染页面

配置项目


设置路径别名

Next的官方脚手架没有src目录,但是考虑src目录是普遍存在大多数脚手架工程中,所以Next也对src目录做了支持,我们可以新建一个 src 目录,将 pages、styles、api 目录移动到src 目录里,在执行 npm run dev,项目依旧正常运行


关于src目录,官方的规则如下:

1.如果根目录下有 pages,则src/pages 将被忽略

2.public 目录以及 next.config.js、tsconfig.json 等配置相关文件,不能放在src目录里

修改 tsconfig.json 别名解析

  "paths": {
    "@/*": ["src/*"]
  }

这样在代码中引用 src 目录下的文件,可以直接使用 @表示src目录,不需要 "../" 了。

修改 tsconfig.json 需要重启项目才能生效。

按照以上目录设置后,项目的入口文件变为 src/pages/_app.js。

配置 SourceMap

development 环境是开启sourceMap的,production 环境默认不开启。如果需要在prod 环境中开启,可以在next.config.js 中进行配置,为了不暴露项目源码,不建议进行配置


module.exports = {
  productionBrowserSourceMaps: !!isDev,
}

设置页面Title

设置页面的title很简单,修改 src/pages/_app.js

import '../styles/globals.css' // 引入全局样式
import Head from 'next/head';
import type { AppProps } from 'next/app'

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      
        页面标题
      
      
    
  )
}

运行项目,发现页面的title 已经修改成功

设置HTML框架代码

新建 src/pages/_document.js,代码如下:

import Document, { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';

class MyDocument extends Document {
  render() {
    return (
      
        
        
          
); } } MyDocument.getInitialProps = async (ctx) => { const initialProps = await Document.getInitialProps(ctx); return { ...initialProps }; }; export default MyDocument;

_document.js 也是Next.js 的指定文件名,且必须在pages目录下才生效。

那么 _document.js 和 _app.js 有什么区别呢?

自定义 App,可以对App 组件进行重构

  • 页面切换之间保持布局的持久化
  • 切换页面时保持状态(state)
  • 使用 componentDidCatch 自定义错误处理
  • 向页面(pages)注入额外的数据
  • 添加全局CSS

自定义Document

只有在服务端渲染的时候才会被调用,主要用来修改服务端渲染的文档内容,通常服务端渲染会使用一些 css-in-js 库,它在_document.js 中定义。

在next/document中提供的并不仅是Document组件,还有一些跟HTML标签对应的组件,在重写的时候要记得都要写上。

官方不建议把 title 放到_document.js中,如果在_document.js 中的head 设置了title,在build 的时候会收到 warning。所以我们将 head 的内容放在 _app.js 中设置。

设置错误页面

Next.js 自带了 404、500页面,但是比较简陋,我们可以自定义页面覆盖掉自带错误页面

可以自定义 404.tsx、500.tsx或者 _error.tsx。

环境变量

  • .env.development
  • .env.production
  • .env.test

CSS预处理及使用


集成Sass

Next.js 允许你导入(import)具有 .scss 和 .sass 扩展名的 Sass 文件。 你可以通过 CSS 模块以及 .module.scss 或 .module.sass 扩展名来使用组件及的 Sass。

npm install sass

Postcss 配置

为了适配移动端,采用 px-to-vw 方案,项目中引入

npm install postcss postcss-px-to-viewport-8-plugin autoprefixer css-loader cssnano tailwindcss --save-dev

新增 postcss.config.js

module.exports = {
  plugins: {
    'postcss-px-to-viewport-8-plugin': {
      // 视窗的宽度,对应的是我们设计稿的宽度,我们公司用的是750
      viewportWidth: 750,
      // 指定`px`转换为视窗单位值的小数位数
      unitPrecision: 3,
      // 指定需要转换成的视窗单位,建议使用vw
      viewportUnit: 'vw',
      // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
      selectorBlackList: ['.ignore'],
      // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
      minPixelValue: 1,
      // 允许在媒体查询中转换`px`
      mediaQuery: false,
      // exclude: undefined
    },
    // 自动补全
    autoprefixer: {
      overrideBrowserslist: [
        'Android 4.1',
        'iOS 7.1',
        'Chrome > 31',
        'ff > 31',
        'ie >= 8',
      ],
      grid: true,
    },
    tailwindcss: {},
    ...(process.env.NODE_ENV === 'development' ? {} : { cssnano: {} }),
  },
};

配置全局样式

新建 src/styles/globals.scss,内部进行样式初始化。然后在入口文件引入 globals.scss。参考_app.tsx

配置页面样式

需要注意的是,在Next.js 项目中,组件的代码中是无法引入全局样式的,对于组件自身的样式,只能使用 CSS Module 来引用,即文件名为 ***.module.scss。否则会报错。组件中的className,也需要按CSS Module的方式进行设置。

注意一下,这里使用 CSS Module 的方式加载样式,因此生成的HTML中,className 会自动加上随机字符串后缀,对应的css也会自动添加相应的字符串,正因为 CSS Module 这个机制,同名样式互相污染的问题也就不存在了。

页面路由

基于文件系统的路由

Next.js 的优势是 基于文件系统的路由,对应的只需要在 src/pages 下创建的对应页面即可。

在pages/ 下创建 /about.tsx 文件,重新启动项目,

next/link

Next.js 项目内的页面跳转使用, 该组件会预先加载引用的页面。如果是项目外部链接,则使用

next/router

Next.js 自带的router,通过 useRouter 来获取当前页面的pathname等信息

图片引用

使用原生标签引入图片

本地图片资源,存放在 public/img/*** 下,图片会跟随项目进行打包,图片根路径地址与项目跟路径地址一致

引用方式一



publicRuntimeConfig.basePath
是根据当前环境,获取的 basePath 路径

使用 next/image 引用图片

Next.js 自带的 可以认为是 的升级版,提供了非常方便的尺寸适配,加载等属性,会根据客户端的情况,进行图片的动态优化处理,但也会自动增加很多样式,会影响原生的 样式,所以要根据情况使用。

如果要使用,需要在包裹一个父容器,并为父容器定义样式。会自动适配父容器的大小,因为可以不用为特意设置宽高。需要注意的是,如果使用加载图片,因为 Next.js 的安全机制,还需要在 next.config.js文件中设置图片域属性,例如设置图片域名属性 qq.com

module.exports = {
  images: {
    domains: ['qq.com'],
    path: `${basePath}/_next/image`,
  },
}

项目中开始部分网络图片采用加载,Next 的确会做懒加载等处理,但是在安卓低端机下存在兼容问题,无法展示,所以后来统一使用原生 标签进行加载。

接口请求

CSR/SSR/SSG三种API请求方式

在Next.js 项目中,API请求有三种方式。但是根据项目的部署方式,最多可以同时有两种,即:

  1. CSR+SSR
  2. CSR+SSG

CSR 的API请求,就是常规的前端项目中的请求方式,即:由客户端浏览器发起请求,拿到数据后渲染到页面

SSR的API请求,是由服务端(Next.js的Node.js)发起请求,拿到数据后,组装到HTML里,然后将组装好的HTML返回给客户端浏览器

SSG的API请求,于SSR的API请求类似,也是由服务发起请求并把数据组装到HTML里,然后进行静态化输出。 但由于是完全静态化的,所以当API数据发生变化时,必须重新静态化才能更新页面。

getInitialProps (SSR)

getInitialProps是在渲染页面之前就会运行的API。 如果该路径下包含该请求,则执行该请求,并将所需的数据作为props传递给页面。

getServerSideProps (SSR)

getServerSideProps 每次访问时请求数据

getStaticProps(SSG)

所谓的SSG也就是静态站点生成,在build阶段将页面构建成静态的html文件,这样线上直接访问HTML文件,性能极高。

getStaticPaths (SSG)

用于在使用动态路由时生成静态文件。

如何选择SSR还是SSG?

axios

使用 axios,并进行的简单的封装,进行了请求拦截及响应拦截。

开发过程中的优化方案

上面提到的本地图片引用,因为项目采用Docker构建,图片如果跟随项目一起打包,每次更新上线后,图片的缓存会失效,页面会重新加载图片,体验上很不好,后来修改为将本地图片上传至CDN。需修改配置文件中的 assetPrefix 配置为CDN文件路径,需结合next-compose-plugins,next-optimized-images 使用

修改页面图片引用方式


npm install --save next-compose-plugins next-optimized-images
// next.config.js
const withPlugins = require('next-compose-plugins');

const optimizedImages = require('next-optimized-images');

const nextConfig = {
  assetPrefix: isDev ? '' : 'https://图片cdn地址',
  distDir: 'build', // 项目文件打包路径
  basePath: '',
  sassOptions: {
    includePaths: [path.join(__dirname, 'src/styles')],
  },
  ...
}

module.exports = withPlugins([optimizedImages], nextConfig);

module.exports = nextConfig;

修改图片的目录,原目录在public/img/*** 下,修改为src/assets/images/***

页面/组件引用方式修改

// 导入本地图片
import demoImg from '@/assets/image/demoImg.png';

// 使用

项目构建,执行 npm run build 后,会在项目目录下生成 build 文件夹,该文件夹下就是项目的构建结果。其中 build/static/media 文件夹存放的是项目引用的图片,并且文件名已经经过hash 处理,可通过工具上传至CDN目录。


Next.js 实践记录
原文链接:
https://juejin.cn/post/7232596270551711799

相关推荐

法拍房「捡漏」陷阱中,都是刚需们的血泪

文|镜相工作室,作者|李丹,编辑丨卢枕买法拍房的人越来越多了。2024年全国住宅类法拍房挂拍31.9万套,成交11.7万套。而在两年前,挂拍数相差无几,成交还只有8.1万套。当阿里法拍房五年激...

睡后收入新神话:90后程序员靠DEEPSEEK躺赚百万?

凌晨四点的杭州未来科技城,27岁程序员陈墨的支付宝响起提示音——这是他开发的AI情感咨询机器人自动完成第89单服务,当日收益突破1.2万元。这个基于DEEPSEEK模型打造的"赛博月老",正在批量制造...

当00后也变成打工人,还会认真谈恋爱吗?

当代年轻人的爱情里,总是会有以下这些场景:在家里被催婚,在约会app上左滑右滑地徘徊,又或者在陌生的环境里等待不期而遇。似乎比真爱更令人失落的,是一种现代人孤岛式的伤感。在专题“预制爱情”中,《新周刊...

我在冬天的上海,被汉王的办公本救了一命?

这老祖宗啊,说得还真没错。人到年末,工作上的破事就一箩筐,事情一多,感觉连血条都短了一大截。你敢相信,今天早上起床的时候,我看着镜子里那张有点认不出来人形的脸,那副垂头丧气的样子,属于是整个人从上到下...

老司机程序员用到的各种优秀资料、神器及框架整理

作者:欧巴冰冰链接:https://www.jianshu.com/p/d74934b49ba3目录资料篇技术站点...

聪明人都在教你用Deep Seek赚钱?不!他们只想“割韭菜”。

当“聪明人”开始用DeepSeek教你赚钱时,请先捂住钱包——因为他们的“聪明”,不过是把镰刀磨得更快,韭菜割得更响。第一步:制造焦虑,贩卖“时代抛弃论”。“不懂AI的人,正在被淘汰!”“某大厂裁员5...

我有一种紧迫感,去呈现社会转型中的思考|专访李睿珺

李睿珺可能是当代最受关注的青年导演之一。对乡村生活的关注是李睿珺创作的一大主题。《老驴头》《告诉他们,我乘白鹤去了》《家在水草丰茂的地方》对这一主题都有不同程度的体现。身为创作者,李睿珺的思考一直在持...

阿里云云效 vs 腾讯云CODING,DevOps孰强孰弱?

编辑导语:DevOps这个话题在IT、开发等领域是相对热门的,它意味着开发运维一体化,是推动业务发展与自动化交付的有效方式。国内便有不少DevOps平台可供企业使用。那么这些DevOps平台目前的发展...

所有小人书目录,以及手机观看截图

单双本连环画1-500连环画_B型美猴王(24册)连环画_一千零一日的故事(10册)连环画_一颗铜纽扣(3册)连环画_丁丁历险记(1-12册)...

瞧,布鲁范德又在一本正经地胡说八道

作者:孙欣祺1996年4月,在那个互联网尚不发达的年代,有一则网络流言引起不少美国人的关注:犹他大学的布鲁范德教授是不是去世了?刚刚办完退休手续的扬·哈罗德·布鲁范德亲自回复:“报道属实。本条信息发送...

“种草经济”种出了什么?

每天,有近400万篇笔记,在小红书上种草“诗与远方”。每小时,有超过1875万人在小红书搜索,求解“柴米油盐”。“种草”一词,源自社交媒体上看到他人分享,产生好感和想要亲自尝试的想法。一件心仪好物,一...

对Http Rest API接口设计和API治理管控的思考

作者:人月神话,新浪博客同名简介:多年SOA规划建设,私有云PaaS平台架构设计经验,长期从事一线项目实践在前面关于微服务方面的文章里面提到,对于多个微服务模块间往往都是以轻量的HttpRestA...

一部汇辑有关吕洞宾之事迹、神话传说及著作《吕祖全书》

0957-吕祖全书(古本)...

塞林格遗稿出版谜案:他并非完全拒斥出版

今年是J·D·塞林格诞辰一百周年,塞林格之子、塞林格基金会负责人马特·塞林格(MattSalinger)首次访华,进行了一系列讲座和对谈活动。在他的指导修订下,译林出版社于2018年末推出了塞林格作...

程序员十大层次,你在第几层

大家好,我是柠檬哥,专注编程知识分享。欢迎关注@程序员柠檬橙,编程路上不迷路,私信发送以下关键字获取编程资源:...