nextjs 初体验

最近有个项目转到我这里维护,项目基于 nextjs,刚好之前只有耳闻,未尝使用过,这里简单记录一下。

接手过来的时候项目没有添加 eslint,查看文档后发现添加 eslint 比较简单

npm i eslint eslint-config-next -D

// .eslintrc.json
{
  "extends": "next"
}

本次有个调整需要引入一个新的 npm,麻烦就来了。

首先是 next.js 默认不编译 node_modules,具体查看 https://github.com/vercel/next.js/issues/706。解决办法是添加 next-transpile-modules

const withTM = require('next-transpile-modules')(['package-need-transpile']);

module.exports = withTM({
  // ...
  webpack5: false,
});

项目不是 webpack5,因此置为 false

接着,nextjs 提示我第三方库引入了全局 css。具体查看 https://github.com/fullcalendar/fullcalendar/issues/5393。解决办法我这里就比较粗暴了,fork 出一份第三方库,将里面的全局样式注释掉。

接着,nextjs 提示入门必提示的 window is not defined,这是由于 node 环境还不存在 window。

这时候有几个解决方案:

  1. 在 didMount / useEffect 中使用 window
  2. 如果是引入组件,那么通过 next/dynamic 引入, 且设置 ssr 为 false
  3. 判断 typeof window !== “undefined” 再使用 window

按上述的方法解决完之后,代码运行,看似没啥问题了。打包,大功告成?等等,又出现了 window is not defined,打包失败。可是我在 dev 的时候确实是编译成功了且没有报错啊。查看提示发现原来是引入的包中使用到了 window

const MyNoSsrCom = dynamic(() => import('./MyCom'), { ssr: false })

// MyCom.jsx
import { sometool } from 'my-package'
// ...

// my-package.js
// 使用到了 window
window.xxxx

这种情况虽然在 dev 是可以的,然而 build 的时候却会报错,原因不详

无奈,只能做如下处理

// MyCom.jsx
const {sometool } = typeof 'window' === undefined ? {} : require('my-package')
// ...

看似没啥问题了,再次 build,依然还是失败了。这次提示 pages 下有文件没有默认导出 react 组件,仔细一看正是我 fork 出来的包文件。不知道为什么将这个文件判断成 react 组件,估计是因为其中存在 Class?只好添加一个默认导出

至此大功告成,但我却陷入怀疑,这个项目本身并没有太多 seo 的痕迹/需求,也只是一个页面,按道理没有首屏幕渲染之类的问题,为什么强行上了个 nextjs,代码中处处都要 typeof 'window' === undefined 这真的好吗?

也许是还没有更深入去了解 nextjs,才会有上述见解。但起码对普通的项目于我而言大概率是不会再有 next 了吧。。