'Next.js serving static files that are not included in the build or source code
I have files that are not stored in a CDN and would like to serve them with Next.js. These files are not intended to be integrated into Next.js and should not be placed in the public folder. More files will be added and I want to avoid using a custom Next.js server to do simple file serving for images that are not available during building. Additionally, this application will only be deployed locally and using a CDN is overkill for this situation.
Currently, I use Express.js and a Next.js custom server to use express.static
to serve files, but this ends up slowing down Next.js and adds lots of unnecessary complexity to my stack. I'd rather just use the Next.js CLI to run my app instead of reinventing the wheel.
Is there a simple way I can serve static files within Next.js and outside the public
directory?
I posted this question and my own answer here on StackOverflow because I was unable to find a good tutorial on how to do this. Nearly every google search says to use a custom server or to just put your files in the public folder, which is not what I was looking for. Hopefully, others who are looking for the same thing may find it here.
Solution 1:[1]
Disclaimer: I do not use Vercel to publish my applications, and I do not know if this answer will be applicable to Next.js on Vercel.
Next.js allows API routes to be customized to support Node.js HTTP handlers, which means express can also be used within Next.js API routes.
Here is some code to utilize express.static
on a Next.js API route.
// 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;
However to get around visiting this endpoint via /api/images/filename
, you can use Next.js's new middleware to rewrite the request!
// 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);
}
With both these in use, visiting /images/photo.png
will internally rewrite to /api/images/photo.png
and in turn be handled by express.static
, allowing you to serve files outside an API route and without using a custom server!
This code can surely be simplified and get rid of the need of initializing a express.js app just to handle a request, but its incredibly simple to integrate express.js into next.js without using a custom server!
I posted this question and my own answer here on StackOverflow because I was unable to find a good tutorial on how to do this. Nearly every google search says to use a custom server or to just put your files in the public folder, which is not what I was looking for. Hopefully, others who are looking for the same thing may find it here.
Solution 2:[2]
The public
folder can only serve those files that were included at build time.
But we can do some workaround that can serve files that were not included at build time.
Solution starts here
We can create an api endpoint. For example /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);
}
By this, our endpoint will read the image from the image directory and send it as a response.
Benifit/Note: This solution works for images that were added after Next project is build i-e npm run build
or next build
Drawback: Using this, We can not build optimized images in Next JS Image
component i-e next/image
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Rizwan Amjad |