Next.js 提供未包含在构建或源代码中的静态文件

cse*_*itz 8 express next.js

我有未存储在 CDN 中的文件,并且希望通过 Next.js 提供它们。这些文件无意集成到 Next.js 中,也不应放置在公共文件夹中。将添加更多文件,我想避免使用自定义 Next.js 服务器为构建期间不可用的图像提供简单的文件服务。此外,该应用程序只能在本地部署,在这种情况下使用 CDN 就显得有些过分了。

目前,我使用 Express.js 和 Next.js 自定义服务器来提供express.static文件服务,但这最终会减慢 Next.js 的速度,并给我的堆栈增加许多不必要的复杂性。我宁愿只使用 Next.js CLI 来运行我的应用程序,而不是重新发明轮子。

有没有一种简单的方法可以在 Next.js 内和public目录外提供静态文件?

我在 StackOverflow 上发布了这个问题和我自己的答案,因为我无法找到有关如何执行此操作的良好教程。几乎每个谷歌搜索都说使用自定义服务器或将文件放在公共文件夹中,这不是我想要的。希望正在寻找同样东西的其他人可以在这里找到它。

cse*_*itz 13

免责声明:我不使用 Vercel 发布我的应用程序,我不知道这个答案是否适用于 Vercel 上的 Next.js。

Next.js 允许自定义 API 路由以支持Node.js HTTP 处理程序,这意味着 Express 也可以在 Next.js API 路由中使用。

express.static以下是在 Next.js API 路由上使用的一些代码。

// pages/api/images/[name].js

// Tell Next.js to pass in Node.js HTTP
export const config = {
   api: { externalResolver: true }
}

import express from 'express';
const handler = express();

const serveFiles = express.static('./path/to/files');
handler.use(['/api/images', '/images'], serveFiles);
//               ^              ^
// Multiple endpoints are passed. The first one is used when visiting /api/images. 
// The second one is used when visiting /images using the middleware rewrite I mention below.

// express is just a function that takes (http.IncomingMessage, http.ServerResponse), 
// which Next.js supports when externalResolver is enabled.
export default handler;
Run Code Online (Sandbox Code Playgroud)

但是,要避免通过 访问此端点/api/images/filename,您可以使用 Next.js 的新中间件来重写请求!

// pages/images/_middleware.js

import { NextResponse } from 'next/server';

export function middleware(req) {
   // Rewrite /images/... to /api/images/...
   return NextResponse.rewrite('/api' + req.nextUrl.pathname);
}
Run Code Online (Sandbox Code Playgroud)

使用这两种方法时,访问/images/photo.png将在内部重写/api/images/photo.png并由 处理express.static,从而允许您在 API 路由之外提供文件,而无需使用自定义服务器!

这段代码肯定可以简化,并且无需初始化express.js应用程序来处理请求,但是将express.js集成到next.js中而不使用自定义服务器非常简单!

我在 StackOverflow 上发布了这个问题和我自己的答案,因为我无法找到有关如何执行此操作的良好教程。几乎每个谷歌搜索都说使用自定义服务器或将文件放在公共文件夹中,这不是我想要的。希望正在寻找同样东西的其他人可以在这里找到它。


Riz*_*jad 6

public文件夹只能提供构建时包含的那些文件。

但我们可以采取一些解决方法来提供构建时未包含的文件。

解决方案从这里开始 我们可以创建一个 api 端点。例如/api/images-endpoint/[...slug].js

import fs from "fs";
import path from "path";

export default function handler(req, res) {
  const imagePath = req.query.slug.join("/");
  const filePath = path.resolve(".", `images-directory/${imagePath}`);
  const imageBuffer = fs.readFileSync(filePath);
  res.setHeader("Content-Type", "image/jpg");
  return res.send(imageBuffer);
}
Run Code Online (Sandbox Code Playgroud)

这样,我们的端点将从图像目录中读取图像并将其作为响应发送。

优点/注意:此解决方案适用于构建下一个项目后添加的图像,即npm run buildnext build 缺点:使用此解决方案,我们无法在 Next JSImage组件中构建优化图像,即next/image