目录
- Next.js
- next.js的实现
- 1,nextjs初始化
- 2, 项目结构
- 3, 数据注入
- getInitialProps
- getServerSideProps
- getStaticProps
- 客户端注入
 
- 3,CSS Modules
- 4,layout组件
- 5,文件式路由
- 6,BFF层的文件式路由
- 7,路由跳转
- 8,header的修改
- 9, 移动端适配---css适配
- 10, 移动端适配--js
- 11,大图优化 ---webp
 
- Nextjs服务端开发
- 1,BFF层开发
 
 
Next.js
学习之前应该了解的知识: 页面的几种渲染方式指路网址
对于SSR的实现,如下图所示,是一个比较复杂和繁琐的事情。
 那nextjs就是作为一个基于react的框架,来进行更好的服务端渲染的。
 
next.js的实现
是一个前后端一体化的一个框架。
 
1,nextjs初始化
创建nextjs项目命令:
npx create-next-app@latest --typescript 
2, 项目结构

 其中:
 pages中放置的是模板页面
 public: 放置的静态资源
 next-env.d.ts: 确保typescript 编译器选择Net.js类型,可以放置到.gitignore中,不需要变更
 next.config.js: 就是nextjs 的配置,我们可以补充webpack的一些配置进行。比如是补充一些别名。
3, 数据注入
和客户端开发最不同的地方,就是数据注入的部分。
 比如我们在csr模式中,可以在一个生命周期钩子里面,向后端获取数据,将得到的数据放到一个声明的state里面,这样我们就可以使用这个数据。
 
 但是在ssr模式里面,尽量不使用在生命周期钩子里面去获取数据,而是会有单独的数据注入的一个方式。
 下面就是next提供的三个数据注入的方式:
 
getInitialProps
在服务器端执行,只能在页面层面进行绑定,采用的同构ssr渲染,说明一套代码要在服务端运行一次,又要在客户端运行一次,首次渲染是服务器端渲染,路由跳转时是使用的客户端路由,
 该方法在路由跳转使用客户端路由,意味着如果使用router跳转当前页,会在客户端执行这部分逻辑。
在刷新页面的时候,会走服务器端的代码,来保证seo
 在进行内部路由跳转的时候,会走客户端的代码。
比如下面的代码,当直接刷新页面,是不会进行degugger的,但是当跳转路由的时候,就会进行debugger。

 不好的地方是,因为node引擎和v8引擎是在变量和方法中 是不相同的,同一套代码在node引擎中和v8引擎中都要走一遍的话,就会在编写代码时比较麻烦,要进行代码兜底。
getServerSideProps
与getInitialProps不同的是,即使使用router跳转当前页,也只会在服务端执行这部分逻辑,这就弥补了getInitialProps的缺点。
 这个和getInitialProps 不同的地方就是,在返回数据的时候,需要使用props字段,将数据进行包裹起来。
 
getStaticProps
这个就是使用的SSG,在服务端构建时执行的, ssg就是一个静态页面, 当访问的时候,就直接将一个页面返回。
SSG,是在服务器端构建时执行的
 如果涉及到动态路由(带参数), 需要使用getStaticPaths配置所有可能的参数情况。
客户端注入
就是上面内容写的,使用生命周期钩子, 在钩子方法中,去获取数据。
3,CSS Modules
Next.js支持使用文件命名约定的CSS 模块
写法: [name].module.css
 使用方式: 使用上面的写法来为css文件进行命名,然后再js文件中直接import进行普通引用即可。
在打包后的html里面,都会为class加上一个哈希值,为了避免类名重复。
 
4,layout组件
通过在入口文件导入layout,可以实现每个页面公共的页眉页尾。
 
 页面的页眉页尾:
 
5,文件式路由
Nextjs 有一个基于页面概念的基于文件系统的路由器,当一个文件被添加到pages目录中时,它会自动作为一个路径可用。
 比如下面的pages文件夹中,
- api文件就是作为数据的中间层,用来重组数据的。
- article就是一个路由文件,是以/article路径存在的。其中在这个文件夹下面,有一个[articleId].tsx,articleId就是作为一个参数
  
 文件式路由的格式:
./pages/demo/index.tsx 对应的路由格式: /demo
./pages/demo/[id].tsx 对应的路由格式: /demo/:id
./pages/demo/[a,b,c].tsx 对应的路由格式: /demo/a/b/c
上面的路由是有优先级的
 当文件中,以上三种文件都存在,则第一种文件会先优先
 第一种路由其实就是预定义路由。优先级就会更高。
6,BFF层的文件式路由

 BFF,作为服务器构建包,不影响客户端构建bundle体积,相同的router生成方式,不过是作为API层访问,而不是page
7,路由跳转
nextjs路由跳转使用方式1:
import Link from "next/link";
<Link href={item.link} key={index}>
              <div className={styles.card}>
                <h2>{item.label} →</h2>
                <p>{item.info}</p>
              </div>
            </Link>
路由跳转使用方式2:
 使用useRouter钩子进行跳转
 
其他方式:
 除了这些之外,还可以使用远程方法进行跳转,不过远程的方法不会进行DIff比对渲染,性能上Nextjs提供的路由跳转会更好。
8,header的修改
对于seo来说,一个页面的header是非常重要的,
 nextjs就暴露出来这样一个组件Head,进行对header的内容进行修改。就修改的内容,放在Head组件里面即可
 
9, 移动端适配—css适配
一般是使用rem来进行适配。rem是根据当前的页面的font-size来决定1rem的大小。
// 极小分辨率移动端设备
@mixin media-mini-mobile {
  @media screen and (max-width: 25.875rem) {
    @content;
  }
}
// 介于极小分辨率和正常分辨率之间的移动端设备
@mixin media-between-mini-and-normal-mobile {
  @media screen and (min-width: 25.876rem) and (max-width: 47.9375rem) {
    @content;
  }
}
// 移动端设备
@mixin media-mobile {
  @media screen and (max-width: 47.9375rem) {
    @content;
  }
}
// ipad
@mixin media-ipad {
  @media screen and (min-width: 47.9375rem) and (max-width: 75rem) {
    @content;
  }
}
使用@include来判断情况。
如下: 当进行移动端适配的时候,需要将css文件导入进来,
 使用@include关键字来进行判断
 当时手机端的时候,就可以对页面进行一些调整。
 当时ipad端的时候,对应的进行页面调整。
 
10, 移动端适配–js
当PC端和移动端项目的同一个功能,由于适配的问题,导致组件的更换。
 那使用css适配方式,已经无法去满足。
 只能是使用js方式,来进行适配。
 适配的方式: 就是在store中保存一个变量 用来记录 当前屏幕的宽度 或者是屏幕环境(是移动端还是pc)等,
- 监听屏幕宽度变化,使用resize方方法,
- 当屏幕发生变化的时候,获取屏幕的宽度,
- 用宽度去判断,不同的宽度有不同的样式
- 添加none类型来缓冲默认类型样式切换时候的视觉冲突。
  
11,大图优化 —webp
webP其实就是一个图片格式,类似于png等。
 对于大图片来说,当用户的网络特别卡的时候,就会导致图片加载不出来,为了缓解这种情况,那么就提供了webp的这种图片格式。webp的图片格式的大小是非常小的,可以更好的加载出来。但是有趣的是,当快网的时候,webp的解析时间是大于png的解析时间。
 这个需要注意兼容性的问题。可以通过方法来进行判断该浏览器是否兼容webP格式
export const getIsSupportWebp = (context: AppContext) => {
  const { headers = {} } = context.ctx.req || {};
  return headers.accept?.includes("image/webp");
};
对于目前转换成webp格式,都有软件或者网页可转,可以自行百度。
Nextjs服务端开发
1,BFF层开发
其实是和express等开发类似,区别是并没有参数可以区别请求类型。
 在BFF层请求数据的时候,不去规定其post方法和get方法
 位置主要是写在pages下面的api里面。
 
 BFF,作为服务器构建包,不影响客户端构建bundle体积,相同的router生成方式,不过是作为API层访问,而不是pages
 axios
    .get(`${CMSDOMAIN}/api/article-introductions`, {
      params: {
        pageNo,
        pageSize,
      },
    })
由于BFF层是在服务器端跑的,你在代码中dugger是不起作用的,下面有两种方式进行调试:
 一个是JS的Debug 终端:
 
 直接在调试终端 ,去跑代码即可。在浏览器是不起作用的,而是在vscode中可见。
 
 第二个是: 直接在node终端中运行下面这个命令即可。
npm run debugger



















