netxjs 13 Beta

96 阅读4分钟

缘起(why not v12)

按组件职责划分,比如一个首页大概有Header,Main,Footer,Swiper这些组件,如果想在Swiper内消费数据,v12只能在页面入口内做请求然后传入子组件。个人有一点强迫症,觉得职责划分明确,代码接口清晰,任务分明,而不用调整Swiper的fetch内容需要跑到页面入口进行修改。

因此当v13 Beta可以将所有渲染组件随意嵌套,单个组件可以选择Server或者Client模式,最终决定此种方案。

由于pages的开发方式仍可在v13使用,简单起见,称v12为pages模式,v13 Beta为appDir模式

项目构建

拉取项目模板

自定义安装

npm install react react-dom next

使用nextjs创建应用

npx create-next-app@latest app

个人node环境 v16.14.0

配置环境变量(.env)

个人是用于在fetch时判断dev和prod环境

// .env.development
APP_ENV=development

// .env.test
APP_ENV=test

// .env.production
APP_ENV=production

路由结构

对比pages依旧以文件嵌套关系表示路由关系,只是命令有些不同

  • layout.js为布局组件,所有当前路由下的页面作为children参数传递到这个组件。可以使用Script引入一些插件
  • page.js 页面入口,对应路由层级的页面 有这个文件才被视为一个路由段
  • loading,error... 处理加载错误等附属信息

组件模式

重要,就是因为这点才使用这个方案。

所有组件都可以使用2种模式

Server Component

顾名思义,服务端组件就是进行服务端渲染,因此不能使用onClick,onChange,useEffect,useState涉及到浏览器渲染功能的函数,除此之外都可以使用客户端组件。

场景:比如显示新闻详情。

export default async function Page() {
  const data = await fetch('https://xxx.com');

  return <main></main>;
}

so easy

Client Component

在浏览器渲染的组件,涉及到事件或web API使用此模式。

场景:比如做一个ToDo List。

在文件头声明"use client"即可定义为客户端组件

混合模式(组件相互嵌套)

有时候2种模式都需要,比如新闻详情有一个左侧Menu List,而新闻内容又不会频繁变动。这时候既需要服务端提前拿到数据,又要onClick切换内容。

实现:引入一个Server Component,fetch后将data传递给Client Component,就在Client Component种愉快地写交互逻辑了。

对比pages

  1. pagespages下,appDirapp目录下
  2. 文件映射路由规则,都用文件目录嵌套关系表示路由映射

pages

pages

  • blog
    • index.js -> /blog

appDir

app

  • blog
    • page.js 入口文件 -> /blog

动态参数配置和pages也类似。

  1. pages 服务端渲染需额外添加数据生产函数getServerSideProps,在组件种消费数据,appDir只需导出一个async函数即可,方便快捷。

开发

切换appDir

cli create创建时指定实验模式的可忽略

cli默认创建的仍是pages,使用appDir需要修改next.config.js配置

const nextConfig = {
  experimental: {
    appDir: true,
  },
};

插入SCP header

缘起 在下类似'全干工程师',因为实际开始有一个测试环境和一个部署环境。测试环境用的阿里云ssl免费证书,没有根证书的痛苦就来了,前端域名是https,由于谷歌浏览器的安全策略,要么资源是https,要么浏览器自动升级https,否则资源无法访问。而一些文件服务域名实在不想一个个配免费证书,因此使用scp强制升级https。我也不想,个人用的nginx服务器,nginx.confnginx -s rleoad一把梭,没用类似宝塔面板的管理端。

module.export={
async headers() {
    return [
      {
        source: "/:path*",
        headers: [
          {
            key: "Content-Security-Policy",
            value: "upgrade-insecure-requests",
          },
        ],
      },
    ];
  }
}

前后端交互

由于有一些api是旧的,本次仍然被使用了前后端分离开发。nextjs提供了直接操作数据库,拿到数据后消费的‘全干’开发思路,在一些简单的项目中可以实验。 复杂的项目有一个‘厚重’的明确Controll,Service的后端服务还是有必要的。

部署

由于netxjs使用自带服务,不想每次编译,做了一个镜像,好处是不需要像官方案例那样每次打包镜像。

总结

  1. appDir组件模式更加方便,个人感觉逻辑更为清楚。当然因人而异,把页面组件看作一个数据中心,由下级组件消费的模式,也合理。
  2. 一直感觉额外导出一个fetch函数有些累赘,appDir去掉后,基本一个组件只需导出一个函数,当然定义meta等额外属性nextjs现在仍是export方式,后续会迁移到hook方式。
  3. 如果组件多数是既有fetch也有浏览器事件,使用appDir混合组件模式有些繁琐。

后记

做完项目后的笔记,这章介绍了主要概念,还有一些如less配置,动态参数,定义Meta,静态生成配置,以及编译的一些坑,有机会再发。

微信截图_20230421172200.png