mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
🔧 refactor: Build Process and Static Asset Handling (#7605)
* 🔧 chore: Update build script to include post-build image removal
* refactor: staticCache middleware with options and special handling for manifest/sw/index files
* refactor(pwa): optimize service worker caching strategy
* refactor: streamline post-build process and update public directory handling
* chore: remove external images from rollupOptions in Vite config
* chore: enhance logging message in post-build script for clarity
This commit is contained in:
parent
2f462c9b3c
commit
f556aaeaea
4 changed files with 64 additions and 13 deletions
|
|
@ -1,3 +1,4 @@
|
|||
const path = require('path');
|
||||
const expressStaticGzip = require('express-static-gzip');
|
||||
|
||||
const oneDayInSeconds = 24 * 60 * 60;
|
||||
|
|
@ -5,16 +6,45 @@ const oneDayInSeconds = 24 * 60 * 60;
|
|||
const sMaxAge = process.env.STATIC_CACHE_S_MAX_AGE || oneDayInSeconds;
|
||||
const maxAge = process.env.STATIC_CACHE_MAX_AGE || oneDayInSeconds * 2;
|
||||
|
||||
const staticCache = (staticPath) =>
|
||||
expressStaticGzip(staticPath, {
|
||||
enableBrotli: false, // disable Brotli, only using gzip
|
||||
/**
|
||||
* Creates an Express static middleware with gzip compression and configurable caching
|
||||
*
|
||||
* @param {string} staticPath - The file system path to serve static files from
|
||||
* @param {Object} [options={}] - Configuration options
|
||||
* @param {boolean} [options.noCache=false] - If true, disables caching entirely for all files
|
||||
* @returns {ReturnType<expressStaticGzip>} Express middleware function for serving static files
|
||||
*/
|
||||
function staticCache(staticPath, options = {}) {
|
||||
const { noCache = false } = options;
|
||||
return expressStaticGzip(staticPath, {
|
||||
enableBrotli: false,
|
||||
orderPreference: ['gz'],
|
||||
setHeaders: (res, _path) => {
|
||||
if (process.env.NODE_ENV?.toLowerCase() === 'production') {
|
||||
setHeaders: (res, filePath) => {
|
||||
if (process.env.NODE_ENV?.toLowerCase() !== 'production') {
|
||||
return;
|
||||
}
|
||||
if (noCache) {
|
||||
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
|
||||
return;
|
||||
}
|
||||
if (filePath.includes('/dist/images/')) {
|
||||
return;
|
||||
}
|
||||
const fileName = path.basename(filePath);
|
||||
|
||||
if (
|
||||
fileName === 'index.html' ||
|
||||
fileName.endsWith('.webmanifest') ||
|
||||
fileName === 'manifest.json' ||
|
||||
fileName === 'sw.js'
|
||||
) {
|
||||
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
|
||||
} else {
|
||||
res.setHeader('Cache-Control', `public, max-age=${maxAge}, s-maxage=${sMaxAge}`);
|
||||
}
|
||||
},
|
||||
index: false,
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = staticCache;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"scripts": {
|
||||
"data-provider": "cd .. && npm run build:data-provider",
|
||||
"build:file": "cross-env NODE_ENV=production vite build --debug > vite-output.log 2>&1",
|
||||
"build": "cross-env NODE_ENV=production vite build",
|
||||
"build": "cross-env NODE_ENV=production vite build && node ./scripts/post-build.cjs",
|
||||
"build:ci": "cross-env NODE_ENV=development vite build --mode ci",
|
||||
"dev": "cross-env NODE_ENV=development vite",
|
||||
"preview-prod": "cross-env NODE_ENV=development vite preview",
|
||||
|
|
|
|||
14
client/scripts/post-build.cjs
Normal file
14
client/scripts/post-build.cjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const fs = require('fs-extra');
|
||||
|
||||
async function postBuild() {
|
||||
try {
|
||||
await fs.copy('public/assets', 'dist/assets');
|
||||
await fs.copy('public/robots.txt', 'dist/robots.txt');
|
||||
console.log('✅ PWA icons and robots.txt copied successfully. Glob pattern warnings resolved.');
|
||||
} catch (err) {
|
||||
console.error('❌ Error copying files:', err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
postBuild();
|
||||
|
|
@ -8,7 +8,7 @@ import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
|||
import type { Plugin } from 'vite';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
export default defineConfig(({ command }) => ({
|
||||
server: {
|
||||
host: 'localhost',
|
||||
port: 3090,
|
||||
|
|
@ -37,13 +37,21 @@ export default defineConfig({
|
|||
enabled: false, // disable service worker registration in development mode
|
||||
},
|
||||
useCredentials: true,
|
||||
includeManifestIcons: false,
|
||||
workbox: {
|
||||
globPatterns: ['**/*'],
|
||||
globPatterns: [
|
||||
'**/*.{js,css,html}',
|
||||
'assets/favicon*.png',
|
||||
'assets/icon-*.png',
|
||||
'assets/apple-touch-icon*.png',
|
||||
'assets/maskable-icon.png',
|
||||
'manifest.webmanifest',
|
||||
],
|
||||
globIgnores: ['images/**/*', '**/*.map'],
|
||||
maximumFileSizeToCacheInBytes: 4 * 1024 * 1024,
|
||||
navigateFallbackDenylist: [/^\/oauth/],
|
||||
},
|
||||
includeAssets: ['**/*'],
|
||||
includeAssets: [],
|
||||
manifest: {
|
||||
name: 'LibreChat',
|
||||
short_name: 'LibreChat',
|
||||
|
|
@ -94,14 +102,13 @@ export default defineConfig({
|
|||
template: 'treemap', // 'treemap' | 'sunburst' | 'network'
|
||||
}),
|
||||
].filter(Boolean),
|
||||
publicDir: './public',
|
||||
publicDir: command === 'serve' ? './public' : false,
|
||||
build: {
|
||||
sourcemap: process.env.NODE_ENV === 'development',
|
||||
outDir: './dist',
|
||||
minify: 'terser',
|
||||
rollupOptions: {
|
||||
preserveEntrySignatures: 'strict',
|
||||
// external: ['uuid'],
|
||||
output: {
|
||||
manualChunks(id: string) {
|
||||
if (id.includes('node_modules')) {
|
||||
|
|
@ -230,10 +237,10 @@ export default defineConfig({
|
|||
resolve: {
|
||||
alias: {
|
||||
'~': path.join(__dirname, 'src/'),
|
||||
$fonts: '/fonts',
|
||||
$fonts: path.resolve(__dirname, 'public/fonts'),
|
||||
},
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
interface SourcemapExclude {
|
||||
excludeNodeModules?: boolean;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue