NextJS + Ingress subpath prefixing
January 27, 2020•300 words
Prefixing your NextJS app through Ingress
What do we want to achieve?
By default, NextJS doesn't support serving an application with it's assets from a custom app prefix (in both dev and prod), for example:
https://www.myapp.com/ <-- SomeOtherApp
https://www.myapp.com/portal <--- My NextJS app
https://www.myapp.com/static/portal <--- My NextJS static (cached by CDN)
NextJS configuration
To be able to do this we need to add a custom server.(js|ts)
, use the setAssetPrefix
and pass handling the assets into the NextJS request handler.
const assetPrefix = '/static/portal';
const app = next({ dev: process.env.NODE_ENV !== 'production' });
const handle = app.getRequestHandler();
// Handle the asset and rewrite the pathname
const handleAppAssets = (assetRegexp, handle) => (req, res) => {
const parsedUrl = parse(req.url, true);
const pathname = parsedUrl.pathname as string;
const assetMatch = assetRegexp.exec(pathname);
const [, asset] = assetMatch;
req.url = format({
...parsedUrl,
pathname: asset,
});
return handle(req, res);
};
app.prepare().then(() => {
// Set the asset prefix
app.setAssetPrefix(assetPrefix);
const server = express();
// Handle the app assets and route them
server.get(
`${assetPrefix}/*`,
handleAppAssets(new RegExp(`^${assetPrefix}(/.*$)`), handle),
);
server.all('*', (req, res) => handle(req, res));
server.listen(3000, error => {
if (error) throw error;
console.log('Server started.');
});
});
Ingress configuration
By default, ingress will rewrite+proxy to our pod(s), but it'll keep the subpath. By using the rewrite-target
annotation, it'll rewrite to the root of our container.
metadata:
name: frontend-portal
labels:
owner: myorg
annotations:
# Route all traffic to pod, but don't keep subpath (!)
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: {{ .Values.clusterDomain }}
http:
paths:
- path: /portal(/.*|$)
backend:
serviceName: frontend-portal
servicePort: 80
- path: /static/portal(/.*|$)
backend:
serviceName: frontend-portal
servicePort: 80
Result
Now your NextJS app will live in the subpath, with it's assets served separately, and your dev and production environment will be in sync.