This library is a layer on top of the the next/image component, which allows you to load images from an imgproxy instance connected to an S3. With this library, the NextJS server acts as a middleman between the client and the imgproxy instance to perform additional tasks, such as applying signatures and/or guards before loading an image.
If you want to access the imgproxy instance directly from your client you can simply use the
next/image
component itself - no need to install this library (you might wanna look into the imgproxy-url-builder to build the request URL however).
You can find additional examples in the demo project.
You can install the package via npm:
npm install --save @bitpatty/next-image-s3-imgproxy-loader
The library by default proxies request through a custom endpoint. To register the endpoint create a custom server in your project and add the following lines:
// server.js
const imgProxy = require('@bitpatty/next-image-s3-imgproxy-loader');
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
if (pathname === imgProxy.IMGPROXY_ENDPOINT) {
// Add other middleware here, such as auth guards
// ...
imgProxy.handle(
new URL('<url to your imgproxy instance>'),
query,
res,
// (Optional) Additional configuration options
{
// (Optional) If your imgproxy uses signatures, specify
// the key and salt here
signature: {
// (Required) The IMGPROXY_KEY (hex encoded)
key: '<imgproxy secret>',
// (Required) The IMGPROXY_SALT (hex encoded)
salt: '<imgproxy salt>',
},
// (Optional) If your imgproxy instance uses
// the IMGPROXY_SECRET, specify the token here
authToken: '<my-token>',
// (Optional) If you wanna restrict access to specific
// buckets add an array of valid bucket names
bucketWhitelist: ['<my-bucket>'],
// (Optional) A list of imgproxy headers that should be
// forwarded through the imgproxy endpoint
forwardedHeaders: ['<my-header>'],
// (Optional) An object containing additional request
// headers that should be sent to the imgproxy endpoint
requestHeaders: {
'My-Header': 'My-Value',
// ...
},
// (Optional) The logger configuration. If you want additional
// debug output you can adjust the log level.
logging: {
// (Optional) The logger to use (defaults to console)
// The logger should implement the signature for
// for console.debug, console.warn and console.error
logger: console,
// (Optional) The log level, must be one of
// 'debug', 'warn' or 'error' (defaults to 'error')
level: 'debug',
},
},
);
} else {
handle(req, res, parsedUrl);
}
}).listen(3000, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
For serverless environments you can use an API endpoint instead of a custom endpoint.
The setup is similar, register your endpoint as follows:
// pages/api/image.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { handle } from '@bitpatty/next-image-s3-imgproxy-loader';
const handler = (req: NextApiRequest, res: NextApiResponse): void => {
if (req.method !== 'GET') {
res.statusCode = 405;
res.send('');
return;
}
handle(new URL('http://localhost:4000/'), req.query, res, {
// Handler Options
});
};
export default handler;
With this method, you have to supply the endpoint to the <ProxyImage>
component.
After registering the endpoint you can use the <ProxyImage />
component as you would with the Image
component from next/image
, except that you need to provide a file (<bucketname>/<filename>
) instead of src
and optional proxy params for image transformations/optimizations.
import ProxyImage from '@bitpatty/next-image-s3-imgproxy-loader';
import pb from '@bitpatty/imgproxy-url-builder';
<ProxyImage
file="mybucket/myfile.png"
proxyParams={pb().rotate(180).blur(10).build()}
/>;
Note: The layout prop is automatically set to 'fill' if no width is set
In case using the component is not an option, you can instead use the image path itself, by utilizing the buildProxyImagePath
function.
import { buildProxyImagePath } from '@bitpatty/next-image-s3-imgproxy-loader';
import pb from '@bitpatty/imgproxy-url-builder';
const imagePath = buildProxyImagePath('test-bucket/test-image.png', {
proxyParams: pb().blur(10).build(),
});
<img src={imagePath} />;
or as background image
import { buildProxyImagePath } from '@bitpatty/next-image-s3-imgproxy-loader';
import pb from '@bitpatty/imgproxy-url-builder';
const imagePath = buildProxyImagePath('test-bucket/test-image.png', {
proxyParams: pb().blur(10).format('jpg').build(),
});
<div
style={{
backgroundImage: `url(${imagePath})`,
backgroundSize: 'cover',
}}
>
{/* Content */}
</div>;
If you use a different endpoint than the one provided by IMGPROXY_ENDPOINT
you can override the endpoint used by the component by providing the endpoint
property. endpoint
can be both a path but also a URL.
<ProxyImage file="mybucket/myfile.png" endpoint="/my-endpoint" />;
// Or
buildProxyImagePath('test-bucket/test-image.png', {
endpoint: '/my-endpoint',
});
By default, the following imgproxy headers will be forwarded in the response to the client:
[
"date",
"expires",
"content-type",
"content-length",
"cache-control",
"content-disposition",
"content-dpr"
]
If you want to forward a different set of headers you can use the forwardedHeaders
option to specify a custom list of headers. Note that if forwardedHeaders
is specified, all headers not specified in the list will be omitted in the response.