为 Next.js 加上 Git Commit 版本号

text

在开发服务端应用的时候,由于服务端应用本身的特性,其实是没有一个明确的版本的概念。毕竟不需要专门下载,理论上每次都是最新的,所以也没有版本的概念。

但在实际开发调试过程中,我们又的确需要关注版本的概念,因为会影响具体的表现形态,所以就需要有一个前后端协调的版本号概念,来帮助我们更好的定位问题,避免前后端之间的扯皮。

一个比较好的思路是,虽然服务端没有版本号概念,但大部分时候会有一个对应的 Commit ID(毕竟现在开发项目完全不用版本控制工具的还是挺少见的)。所以,你可以选择将 Commit ID 作为版本号,进行输出,从而让协作者知道当前线上跑的版本,便于 debug。

在具体实现时,有两种方式:

1. 将 Commit ID 放在 Header 里

我自己平时会把 Vercel 和 Next.js 提供的 API Route 作为一个简单的 Serverless FaaS 环境来使用,因此一个诉求便是在 API Route 当中返回具体的 Commit ID。而为了避免对代码的侵入,将其放在 Response Header 当中是比较合适的。

d2b5ca33bd970f64a6301fa75ae2eb22 2
添加完成的效果。

而如果你希望和我一样,达成对特定路由下的返回结果添加特定的 Header(比如上面截图中 x-build-sha 就是我添加的 Commit ID 的 Header),则需要借助于 Next.js 提供的自定义 Header 能力

通过在 next.config.js 当中的 header 属性中添加具体的配置,来实现对特定的路径下添加自定义 Header。

module.exports = {
  async headers() {
    return [
      {
        source: '/about',
        headers: [
          {
            key: 'x-custom-header',
            value: 'my custom header value',
          },
          {
            key: 'x-another-custom-header',
            value: 'my other custom header value',
          },
        ],
      },
    ];
  },
};
Code language: JavaScript (javascript)

这里面比较关键的是 source 字段,这个字段定义了究竟哪些路由下会返回特定的 Header。比如上面的这段配置就是只给 /about 添加具体的 Header。你可以使用 /:path* 来匹配所有路由,从而实现给所有路由都添加上具体的 Header。

以我为例,我在线上跑的配置实际上是下面这段配置:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [{ key: 'X-Build-SHA', value: process.env.VERCEL_GIT_COMMIT_SHA }]
      }
    ];
  }
}

module.exports = nextConfig
Code language: JavaScript (javascript)

在上面这段配置中,我给所有的路径都配置了一个 x-build-sha 的 header ,并从进程的变量中提取出 VERCEL_GIT_COMMIT_SHA 变量(这个变量在 Vercel 的部署环境中指向具体的 Commit ID)的值,将其返回。

2. 将 Commit ID 放在 UI 里

除了在 Header 中返回,如果你是需要去 Debug UI 的话,版本号同样重要,这个时候,你可以选择将 Commit ID 放在界面上,从而实现快速找到 Commit ID。

在 Vercel 部署的 Next.js 上,有一批 Next.js 框架所属的环境变量, 可以直接在 UI 当中引用(上面的 VERCEL_GIT_COMMIT_SHA 是不能在 UI 中直接引用的)。

只需要在特定的位置,加入SHA: {process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA} ,就可以展示具体的 Commit ID。

(除了 Next.js,其他框架也有类似的框架变量可以使用,你可以根据自己的需求来选择)。

总结

在服务端 Debug 时,将你的 Commit ID 以某种方式返回可以有效的帮助快速定位问题,试着给你的 Next.js 添加上这个 Commit ID,来加速你的问题排查吧~

在 Next.js 中直接引入 SVG

computer screen displaying website home page

随着 SVG 的兴起,过去使用雪碧图、IconFont 作为界面中图标用法已经过时。大家会更倾向于加载更加简单、空间占用更小、编写更容易的 SVG 作为图标的解决方案。

而 Next.js 同样对于 SVG 提供了支持。

最简单的加载方式 —— URL 加载

如果不希望对应用程序做任何的改进,一个最简单的方式是直接使用路径进行加载。只需要使用一个 img 标签,并设定 src 为 svg 文件的路径就可以了。

<img src="/logo.svg" alt="Logo SVG" />
Code language: HTML, XML (xml)

不过,使用 URL 来加载的问题是,当你的文件夹路径和结构比较复杂的时候,你需要使用一个较长的路径来加载 SVG,比较麻烦。

当然, 你也可以简单的优化这个方案 —— 比如自行封装一个 svg component,支持传入文件名 & alt 文字和其他参数。这样在调用的时候只需要输入文件名即可。

最舒服的加载方式 —— 编程加载

在 Next.js 当中,如果你希望更加舒服的引入 SVG,那比较好的方案是使用 import 标签来进行引入。不过,由于 SVG 本身并不是一个标准的 React 组件,你需要在 Next.js 上安装插件来支持对 SVG 的解析。

加入对 SVG 的解析需要安装 @svgr/webpack 插件。执行如下命令安装插件。

# yarn
yarn add @svgr/webpack
# npm
npm install --save @svgr/webpack
Code language: PHP (php)

安装完成后,修改 next.config.js添加相关的解析规则。

module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ["@svgr/webpack"]
    }); // 针对 SVG 的处理规则

    return config;
  }
};
Code language: JavaScript (javascript)

修改后保存,便可以直接使用 import 语法来处理

import Logo from "../assets/logo.svg";


// usage
<Logo />
Code language: JavaScript (javascript)

这样,你就可以直接将 SVG 作为一个 Component 引入,并使用你熟悉的 React Componet Props 来修改这个 Component 的各项属性。

总结

在这篇文章中,分享了两种在 Next.js 的方法,你可以根据自己的实际情况来决定选择具体使用什么样的方式来引入 SVG。

Next.js 实现动态引入,实现对非 SSR 组件的支持

CAPTCHA

在使用 Next.js 进行开发的时候,会遇到某些组件是不提供 SSR 支持的(很正常,毕竟 SSR 是一个相对比较小众的应用场景。此外,某些组件会依赖浏览器环境的上下文),在这种情况下,我们需要一种方式来实现对非 SSR 组件的支持。

一般而言, 有两种方式,一种是使用 useEffects 来控制组件的载入,从而实现只在客户端层面加载组件,服务端渲染的时候就不再加载该组件。

另外一种方式是可以考虑借助于 Next.js 自带的 Dynamic Import 的特性,来完成组件的引入。

在使用层面比较简单,引入组件的方式从直接引入改为最外层套一层 dynamic 函数即可

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponentWithNoSSR />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home
Code language: JavaScript (javascript)

总结

这个问题的解决让我再次激起了对于 Next.js 的兴趣。过去因为不确定如何解决在浏览器和客户端环境下的问题,对于 Next.js 有些畏难;如今问题已解决,可以继续放心的使用 Next.js 了。

参考阅读

https://nextjs.org/docs/advanced-features/dynamic-import

Material UI 如何引入自定义主题

CAPTCHA

在 Next.js 中,如果你希望为 Material UI 引入自定义主题,可以如下实现

1. 设计自定义主题

参考 Theming 主题 – MUI 来定制自己的主题,所有的属性可以在 默认主题 – MUI 找到。修改你需要修改的对应项目即可。剩下的可以使用默认。

2. 修改代码,引入主题

修改你的 pages/_app.js,在其中添加如下代码,来应用你的主题。

import { ThemeProvider, createTheme } from '@material-ui/core/styles';
const themeOptions = createTheme({
  palette: {
    type: 'dark',
    primary: {
      main: '#ff9900',
    }
  },
});
function MyApp({ Component, pageProps }) {
  return (
      <ThemeProvider theme={themeOptions}> <Component {...pageProps} /></ThemeProvider>
  )
}
Code language: JavaScript (javascript)