openreader/next.config.ts
Richard R fb32dea73c build(config): adjust output and file tracing for Vercel and local compute modes
Update Next.js configuration to conditionally set 'output' only when not on
Vercel, and always define 'outputFileTracingExcludes' with dynamic includes
based on compute mode. This ensures compatibility with Vercel deployments and
improves local/server build behavior.
2026-05-20 15:53:26 -06:00

113 lines
3.7 KiB
TypeScript

import type { NextConfig } from "next";
import path from "node:path";
const securityHeaders = [
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{
key: 'Content-Security-Policy',
value: "frame-ancestors 'self' https://*.huggingface.co https://huggingface.co",
},
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains; preload',
},
];
const computeModeRaw = (process.env.COMPUTE_MODE || 'local').trim().toLowerCase();
const computeMode = computeModeRaw === 'none' || computeModeRaw === 'worker' || computeModeRaw === 'local'
? computeModeRaw
: 'local';
const computeLocal = computeMode === 'local';
const isVercel = process.env.VERCEL === '1';
const serverExternalPackages = [
'@napi-rs/canvas',
'ffmpeg-static',
'better-sqlite3',
...(computeLocal ? ['onnxruntime-node', '@huggingface/tokenizers'] : []),
];
const nextConfig: NextConfig = {
...(isVercel ? {} : { output: 'standalone' }),
async headers() {
return [
{
// Apply security headers to all routes
source: '/(.*)',
headers: securityHeaders,
},
];
},
turbopack: {
resolveAlias: {
canvas: '@napi-rs/canvas',
},
},
transpilePackages: computeLocal ? ['@openreader/compute-core'] : [],
serverExternalPackages,
outputFileTracingIncludes: {
'/api/audiobook': [
'./node_modules/ffmpeg-static/ffmpeg',
],
'/api/audiobook/chapter': [
'./node_modules/ffmpeg-static/ffmpeg',
],
'/api/tts/segments/ensure': [
'./node_modules/ffmpeg-static/ffmpeg',
],
'/api/documents/blob/preview/ensure': [
'./node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs',
],
'/api/documents/blob/preview/presign': [
'./node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs',
],
'/api/documents/blob/preview/fallback': [
'./node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs',
],
},
outputFileTracingExcludes: {
'/*': [
'./docstore/**/*',
...(!computeLocal
? [
'./node_modules/onnxruntime-node/**/*',
'./node_modules/@huggingface/tokenizers/**/*',
]
: []),
],
},
webpack: (config, { isServer }) => {
if (isServer) {
// Use runtime require to avoid adding an explicit webpack TS dependency.
const { DefinePlugin } = require('webpack') as { DefinePlugin: new (defs: Record<string, string>) => unknown };
config.plugins = config.plugins || [];
config.plugins.push(
new DefinePlugin({
__OPENREADER_COMPUTE_MODE__: JSON.stringify(computeMode),
}),
);
}
if (isServer && !computeLocal) {
const workerComputeEntry = path.resolve(__dirname, 'src/lib/server/compute/index.worker.ts');
const computeIndexTs = path.resolve(__dirname, 'src/lib/server/compute/index.ts');
const computeIndexNoExt = path.resolve(__dirname, 'src/lib/server/compute/index');
const computeDir = path.resolve(__dirname, 'src/lib/server/compute');
config.resolve.alias = {
...(config.resolve.alias || {}),
'@/lib/server/compute$': workerComputeEntry,
'@/lib/server/compute/index$': workerComputeEntry,
[`${computeIndexTs}$`]: workerComputeEntry,
[`${computeIndexNoExt}$`]: workerComputeEntry,
[`${computeDir}$`]: workerComputeEntry,
'@openreader/compute-core/local-runtime$': false,
'onnxruntime-node$': false,
'@huggingface/tokenizers$': false,
};
}
return config;
},
};
export default nextConfig;