184 lines
5.0 KiB
JavaScript
184 lines
5.0 KiB
JavaScript
/** @type {import('next').NextConfig} */
|
||
let withBundleAnalyzer = (config) => config;
|
||
try {
|
||
withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||
enabled: process.env.ANALYZE === 'true',
|
||
});
|
||
} catch (_) {
|
||
// @next/bundle-analyzer не установлен (например в production Docker-образе)
|
||
}
|
||
|
||
const nextConfig = {
|
||
// Оптимизация для production
|
||
output: 'standalone',
|
||
|
||
// Turbopack конфиг (пустой, используем webpack)
|
||
turbopack: {},
|
||
|
||
// Компрессия
|
||
compress: true,
|
||
|
||
// Оптимизация изображений
|
||
images: {
|
||
formats: ['image/avif', 'image/webp'],
|
||
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
|
||
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
||
minimumCacheTTL: 60,
|
||
dangerouslyAllowSVG: true,
|
||
contentDispositionType: 'attachment',
|
||
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
||
},
|
||
|
||
// Оптимизация webpack
|
||
webpack: (config, { dev, isServer }) => {
|
||
// Hot reload для development (в т.ч. в Docker с volume)
|
||
if (dev) {
|
||
config.watchOptions = {
|
||
...config.watchOptions,
|
||
poll: process.env.WATCHPACK_POLLING ? 500 : 1000,
|
||
aggregateTimeout: 300,
|
||
ignored: ['**/node_modules', '**/.git'],
|
||
};
|
||
}
|
||
|
||
// Оптимизация для production
|
||
if (!dev && !isServer) {
|
||
// Агрессивное разделение чанков
|
||
config.optimization = {
|
||
...config.optimization,
|
||
splitChunks: {
|
||
chunks: 'all',
|
||
cacheGroups: {
|
||
default: false,
|
||
vendors: false,
|
||
// Material Web Components в отдельный chunk
|
||
material: {
|
||
name: 'material',
|
||
test: /[\\/]node_modules[\\/]@material[\\/]/,
|
||
chunks: 'all',
|
||
priority: 30,
|
||
enforce: true,
|
||
},
|
||
// LiveKit — скрипты бандлятся с нашего сервера, внешние домены не используются
|
||
livekit: {
|
||
name: 'livekit',
|
||
test: /[\\/]node_modules[\\/](livekit-client|@livekit)[\\/]/,
|
||
chunks: 'all',
|
||
priority: 30,
|
||
enforce: true,
|
||
},
|
||
// React и React DOM
|
||
react: {
|
||
name: 'react',
|
||
test: /[\\/]node_modules[\\/](react|react-dom|scheduler)[\\/]/,
|
||
chunks: 'all',
|
||
priority: 25,
|
||
enforce: true,
|
||
},
|
||
// Axios и другие утилиты
|
||
utils: {
|
||
name: 'utils',
|
||
test: /[\\/]node_modules[\\/](axios|date-fns)[\\/]/,
|
||
chunks: 'all',
|
||
priority: 20,
|
||
},
|
||
// Остальные vendor библиотеки
|
||
vendor: {
|
||
name: 'vendor',
|
||
test: /[\\/]node_modules[\\/]/,
|
||
chunks: 'all',
|
||
priority: 10,
|
||
minChunks: 2,
|
||
},
|
||
// Общий chunk для часто используемых модулей
|
||
common: {
|
||
name: 'common',
|
||
minChunks: 2,
|
||
chunks: 'all',
|
||
priority: 5,
|
||
reuseExistingChunk: true,
|
||
},
|
||
},
|
||
},
|
||
// Минификация
|
||
minimize: true,
|
||
};
|
||
|
||
// Tree shaking для Material Web Components
|
||
config.resolve.alias = {
|
||
...config.resolve.alias,
|
||
};
|
||
}
|
||
|
||
return config;
|
||
},
|
||
|
||
// Заголовки для кеширования и безопасности
|
||
async headers() {
|
||
return [
|
||
{
|
||
source: '/:path*',
|
||
headers: [
|
||
{
|
||
key: 'X-DNS-Prefetch-Control',
|
||
value: 'on',
|
||
},
|
||
{
|
||
key: 'X-Frame-Options',
|
||
value: 'SAMEORIGIN',
|
||
},
|
||
{
|
||
key: 'X-Content-Type-Options',
|
||
value: 'nosniff',
|
||
},
|
||
{
|
||
key: 'Referrer-Policy',
|
||
value: 'origin-when-cross-origin',
|
||
},
|
||
],
|
||
},
|
||
{
|
||
source: '/assets/:path*',
|
||
headers: [
|
||
{
|
||
key: 'Cache-Control',
|
||
value: 'public, max-age=31536000, immutable',
|
||
},
|
||
],
|
||
},
|
||
{
|
||
source: '/_next/static/:path*',
|
||
headers: [
|
||
{
|
||
key: 'Cache-Control',
|
||
value: 'public, max-age=31536000, immutable',
|
||
},
|
||
],
|
||
},
|
||
];
|
||
},
|
||
|
||
// Rewrites для API
|
||
async rewrites() {
|
||
return [
|
||
{
|
||
source: '/api/:path*',
|
||
destination: `${process.env.NEXT_PUBLIC_API_URL || 'https://api.uchill.online/api'}/:path*`,
|
||
},
|
||
];
|
||
},
|
||
|
||
// Отключаем x-powered-by для безопасности
|
||
poweredByHeader: false,
|
||
|
||
// Оптимизация React
|
||
reactStrictMode: true,
|
||
|
||
// Оптимизация компиляции TypeScript
|
||
typescript: {
|
||
ignoreBuildErrors: false,
|
||
},
|
||
};
|
||
|
||
module.exports = withBundleAnalyzer(nextConfig);
|