mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 17:47:27 +00:00
🔧 chore: simplify build config and remove webpack customization (#12539)
- Remove desktop-related build steps from Dockerfile - Simplify next.config.ts, only apply Vercel-specific config on Vercel - Remove webpack customization from define-config.ts - Fix String() type conversion in video.ts
This commit is contained in:
parent
d9b4ab01ce
commit
18ec113bba
4 changed files with 32 additions and 106 deletions
15
Dockerfile
15
Dockerfile
|
|
@ -101,17 +101,6 @@ RUN rm -rf src/app/desktop "src/app/(backend)/trpc/desktop"
|
|||
# run build standalone for docker version
|
||||
RUN npm run build:docker
|
||||
|
||||
# Prepare desktop export assets for Electron packaging (if generated)
|
||||
RUN set -e && \
|
||||
if [ -d "/app/out" ]; then \
|
||||
mkdir -p /app/apps/desktop/dist/next && \
|
||||
cp -a /app/out/. /app/apps/desktop/dist/next/ && \
|
||||
echo "Copied Next export output into /app/apps/desktop/dist/next"; \
|
||||
else \
|
||||
echo "No Next export output found at /app/out, creating empty directory" && \
|
||||
mkdir -p /app/apps/desktop/dist/next; \
|
||||
fi
|
||||
|
||||
## Application image, copy all the files for production
|
||||
FROM busybox:latest AS app
|
||||
|
||||
|
|
@ -120,11 +109,9 @@ COPY --from=base /distroless/ /
|
|||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder /app/.next/standalone /app/
|
||||
COPY --from=builder /app/.next/static /app/.next/static
|
||||
# Copy SPA assets (Vite build output)
|
||||
COPY --from=builder /app/public/spa /app/public/spa
|
||||
# Copy Next export output for desktop renderer
|
||||
COPY --from=builder /app/apps/desktop/dist/next /app/apps/desktop/dist/next
|
||||
|
||||
# Copy database migrations
|
||||
COPY --from=builder /app/packages/database/migrations /app/migrations
|
||||
COPY --from=builder /app/scripts/migrateServerDB/docker.cjs /app/docker.cjs
|
||||
|
|
|
|||
|
|
@ -2,42 +2,31 @@ import { defineConfig } from './src/libs/next/config/define-config';
|
|||
|
||||
const isVercel = !!process.env.VERCEL_ENV;
|
||||
|
||||
const nextConfig = defineConfig({
|
||||
const vercelConfig = {
|
||||
// Vercel serverless optimization: exclude musl binaries and ffmpeg from all routes
|
||||
// Vercel uses Amazon Linux (glibc), not Alpine Linux (musl)
|
||||
// ffmpeg-static (~76MB) is only needed by /api/webhooks/video/* route
|
||||
// This saves ~120MB (29MB canvas-musl + 16MB sharp-musl + 76MB ffmpeg)
|
||||
outputFileTracingExcludes: isVercel
|
||||
? {
|
||||
'*': [
|
||||
'node_modules/.pnpm/@napi-rs+canvas-*-musl*',
|
||||
'node_modules/.pnpm/@img+sharp-libvips-*musl*',
|
||||
'node_modules/ffmpeg-static/**',
|
||||
'node_modules/.pnpm/ffmpeg-static*/**',
|
||||
// Exclude SPA/desktop/mobile build artifacts from serverless functions
|
||||
'public/spa/**',
|
||||
'dist/desktop/**',
|
||||
'dist/mobile/**',
|
||||
'apps/desktop/**',
|
||||
'packages/database/migrations/**',
|
||||
],
|
||||
}
|
||||
: undefined,
|
||||
// Include ffmpeg binary only for video webhook processing
|
||||
// refs: https://github.com/vercel-labs/ffmpeg-on-vercel
|
||||
outputFileTracingIncludes: isVercel
|
||||
? {
|
||||
'/api/webhooks/video/*': ['./node_modules/ffmpeg-static/ffmpeg'],
|
||||
}
|
||||
: undefined,
|
||||
webpack: (webpackConfig, context) => {
|
||||
const { dev } = context;
|
||||
if (!dev) {
|
||||
webpackConfig.cache = false;
|
||||
}
|
||||
|
||||
return webpackConfig;
|
||||
outputFileTracingExcludes: {
|
||||
'*': [
|
||||
'node_modules/.pnpm/@napi-rs+canvas-*-musl*',
|
||||
'node_modules/.pnpm/@img+sharp-libvips-*musl*',
|
||||
'node_modules/ffmpeg-static/**',
|
||||
'node_modules/.pnpm/ffmpeg-static*/**',
|
||||
// Exclude SPA/desktop/mobile build artifacts from serverless functions
|
||||
'public/spa/**',
|
||||
'dist/desktop/**',
|
||||
'dist/mobile/**',
|
||||
'apps/desktop/**',
|
||||
'packages/database/migrations/**',
|
||||
],
|
||||
},
|
||||
outputFileTracingIncludes: {
|
||||
'/api/webhooks/video/*': ['./node_modules/ffmpeg-static/ffmpeg'],
|
||||
},
|
||||
};
|
||||
const nextConfig = defineConfig({
|
||||
...(isVercel ? vercelConfig : {}),
|
||||
});
|
||||
|
||||
export default nextConfig;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { codeInspectorPlugin } from 'code-inspector-plugin';
|
||||
import { type NextConfig } from 'next';
|
||||
import { type Header, type Redirect } from 'next/dist/lib/load-custom-routes';
|
||||
import ReactComponentName from 'react-scan/react-component-name/webpack';
|
||||
|
||||
interface CustomNextConfig {
|
||||
experimental?: NextConfig['experimental'];
|
||||
|
|
@ -11,14 +10,12 @@ interface CustomNextConfig {
|
|||
redirects?: Redirect[];
|
||||
serverExternalPackages?: NextConfig['serverExternalPackages'];
|
||||
turbopack?: NextConfig['turbopack'];
|
||||
webpack?: NextConfig['webpack'];
|
||||
}
|
||||
|
||||
export function defineConfig(config: CustomNextConfig) {
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
const buildWithDocker = process.env.DOCKER === 'true';
|
||||
|
||||
const enableReactScan = !!process.env.REACT_SCAN_MONITOR_API_KEY;
|
||||
const shouldUseCSP = process.env.ENABLED_CSP === '1';
|
||||
|
||||
const isTest =
|
||||
|
|
@ -28,14 +25,23 @@ export function defineConfig(config: CustomNextConfig) {
|
|||
|
||||
const standaloneConfig: NextConfig = {
|
||||
output: 'standalone',
|
||||
|
||||
outputFileTracingIncludes: {
|
||||
'*': [
|
||||
'public/**/*',
|
||||
'.next/static/**/*',
|
||||
|
||||
// Only needed for Docker standalone builds.
|
||||
// On Vercel (serverless), including native bindings can easily exceed function size limits.
|
||||
...(buildWithDocker
|
||||
? [
|
||||
// Exclude SPA/desktop/mobile build artifacts from serverless functions
|
||||
'public/spa/**',
|
||||
'dist/desktop/**',
|
||||
'dist/mobile/**',
|
||||
|
||||
'packages/database/migrations/**',
|
||||
|
||||
// Ensure native bindings are included in standalone output.
|
||||
// `@napi-rs/canvas` is loaded via dynamic `require()` (see packages/file-loaders),
|
||||
// which may not be picked up by Next.js output tracing.
|
||||
|
|
@ -370,62 +376,6 @@ export function defineConfig(config: CustomNextConfig) {
|
|||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
|
||||
webpack(baseWebpackConfig, options) {
|
||||
baseWebpackConfig.experiments = {
|
||||
asyncWebAssembly: true,
|
||||
layers: true,
|
||||
};
|
||||
|
||||
// 开启该插件会导致 pglite 的 fs bundler 被改表
|
||||
if (enableReactScan) {
|
||||
baseWebpackConfig.plugins.push(ReactComponentName({}));
|
||||
}
|
||||
|
||||
// to fix shikiji compile error
|
||||
// refs: https://github.com/antfu/shikiji/issues/23
|
||||
baseWebpackConfig.module.rules.push({
|
||||
resolve: {
|
||||
fullySpecified: false,
|
||||
},
|
||||
test: /\.m?js$/,
|
||||
type: 'javascript/auto',
|
||||
});
|
||||
|
||||
baseWebpackConfig.resolve.alias.canvas = false;
|
||||
|
||||
// to ignore epub2 compile error
|
||||
// refs: https://github.com/lobehub/lobe-chat/discussions/6769
|
||||
baseWebpackConfig.resolve.fallback = {
|
||||
...baseWebpackConfig.resolve.fallback,
|
||||
zipfile: false,
|
||||
};
|
||||
|
||||
if (
|
||||
assetPrefix &&
|
||||
(assetPrefix.startsWith('http://') || assetPrefix.startsWith('https://'))
|
||||
) {
|
||||
// fix the Worker URL cross-origin issue
|
||||
// refs: https://github.com/lobehub/lobe-chat/pull/9624
|
||||
baseWebpackConfig.module.rules.push({
|
||||
generator: {
|
||||
// @see https://webpack.js.org/configuration/module/#rulegeneratorpublicpath
|
||||
publicPath: '/_next/',
|
||||
},
|
||||
test: /worker\.ts$/,
|
||||
// @see https://webpack.js.org/guides/asset-modules/
|
||||
type: 'asset/resource',
|
||||
});
|
||||
}
|
||||
|
||||
const updatedConfig = baseWebpackConfig;
|
||||
|
||||
if (config.webpack) {
|
||||
return config.webpack(updatedConfig, options);
|
||||
}
|
||||
|
||||
return updatedConfig;
|
||||
},
|
||||
};
|
||||
|
||||
return nextConfig;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export class VideoGenerationService {
|
|||
|
||||
const [metadata, videoBuffer] = await Promise.all([
|
||||
this.getVideoMetadata(tempVideoPath),
|
||||
fs.readFile(tempVideoPath),
|
||||
fs.readFile(String(tempVideoPath)),
|
||||
]);
|
||||
|
||||
log('Video metadata: %O', metadata);
|
||||
|
|
@ -91,7 +91,7 @@ export class VideoGenerationService {
|
|||
|
||||
// Generate cover screenshot and thumbnail
|
||||
tempCoverPath = await this.generateScreenshot(tempVideoPath, metadata.width, metadata.height);
|
||||
const coverBuffer = await fs.readFile(tempCoverPath);
|
||||
const coverBuffer = await fs.readFile(String(tempCoverPath));
|
||||
|
||||
// Convert cover to webp
|
||||
const coverWebpBuffer = await sharp(coverBuffer).webp({ quality: 100 }).toBuffer();
|
||||
|
|
|
|||
Loading…
Reference in a new issue