NextJS + Ingress subpath prefixing
January 27, 2020
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.