feat: Static File Caching (#3455)

* add static file cache

* disable compression env variable
This commit is contained in:
matt burnett 2024-08-04 21:17:59 -04:00 committed by GitHub
parent 020c4a1a0e
commit e4ac42f034
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 99 additions and 5 deletions

View file

@ -425,6 +425,18 @@ FIREBASE_APP_ID=
ALLOW_SHARED_LINKS=true ALLOW_SHARED_LINKS=true
ALLOW_SHARED_LINKS_PUBLIC=true ALLOW_SHARED_LINKS_PUBLIC=true
#==============================#
# Static File Cache Control #
#==============================#
# Leave commented out to use default of 1 month for max-age and 1 week for s-maxage
# NODE_ENV must be set to production for these to take effect
# STATIC_CACHE_MAX_AGE=604800
# STATIC_CACHE_S_MAX_AGE=259200
# If you have another service in front of your LibreChat doing compression, disable express based compression here
# DISABLE_COMPRESSION=true
#===================================================# #===================================================#
# UI # # UI #
#===================================================# #===================================================#

View file

@ -45,6 +45,7 @@
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",
"cohere-ai": "^7.9.1", "cohere-ai": "^7.9.1",
"compression": "^1.7.4",
"connect-redis": "^7.1.0", "connect-redis": "^7.1.0",
"cookie": "^0.5.0", "cookie": "^0.5.0",
"cors": "^2.8.5", "cors": "^2.8.5",

View file

@ -4,6 +4,7 @@ require('module-alias')({ base: path.resolve(__dirname, '..') });
const cors = require('cors'); const cors = require('cors');
const axios = require('axios'); const axios = require('axios');
const express = require('express'); const express = require('express');
const compression = require('compression');
const passport = require('passport'); const passport = require('passport');
const mongoSanitize = require('express-mongo-sanitize'); const mongoSanitize = require('express-mongo-sanitize');
const { jwtLogin, passportLogin } = require('~/strategies'); const { jwtLogin, passportLogin } = require('~/strategies');
@ -17,8 +18,9 @@ const configureSocialLogins = require('./socialLogins');
const AppService = require('./services/AppService'); const AppService = require('./services/AppService');
const noIndex = require('./middleware/noIndex'); const noIndex = require('./middleware/noIndex');
const routes = require('./routes'); const routes = require('./routes');
const staticCache = require('./utils/staticCache');
const { PORT, HOST, ALLOW_SOCIAL_LOGIN } = process.env ?? {}; const { PORT, HOST, ALLOW_SOCIAL_LOGIN, DISABLE_COMPRESSION } = process.env ?? {};
const port = Number(PORT) || 3080; const port = Number(PORT) || 3080;
const host = HOST || 'localhost'; const host = HOST || 'localhost';
@ -43,12 +45,16 @@ const startServer = async () => {
app.use(express.json({ limit: '3mb' })); app.use(express.json({ limit: '3mb' }));
app.use(mongoSanitize()); app.use(mongoSanitize());
app.use(express.urlencoded({ extended: true, limit: '3mb' })); app.use(express.urlencoded({ extended: true, limit: '3mb' }));
app.use(express.static(app.locals.paths.dist)); app.use(staticCache(app.locals.paths.dist));
app.use(express.static(app.locals.paths.fonts)); app.use(staticCache(app.locals.paths.fonts));
app.use(express.static(app.locals.paths.assets)); app.use(staticCache(app.locals.paths.assets));
app.set('trust proxy', 1); // trust first proxy app.set('trust proxy', 1); // trust first proxy
app.use(cors()); app.use(cors());
if (DISABLE_COMPRESSION !== 'true') {
app.use(compression());
}
if (!ALLOW_SOCIAL_LOGIN) { if (!ALLOW_SOCIAL_LOGIN) {
console.warn( console.warn(
'Social logins are disabled. Set Environment Variable "ALLOW_SOCIAL_LOGIN" to true to enable them.', 'Social logins are disabled. Set Environment Variable "ALLOW_SOCIAL_LOGIN" to true to enable them.',

View file

@ -1,7 +1,8 @@
const express = require('express'); const express = require('express');
const staticCache = require('../utils/staticCache');
const paths = require('~/config/paths'); const paths = require('~/config/paths');
const router = express.Router(); const router = express.Router();
router.use(express.static(paths.imageOutput)); router.use(staticCache(paths.imageOutput));
module.exports = router; module.exports = router;

View file

@ -0,0 +1,19 @@
const express = require('express');
const oneWeekInSeconds = 24 * 60 * 60 * 7;
const sMaxAge = process.env.STATIC_CACHE_S_MAX_AGE || oneWeekInSeconds;
const maxAge = process.env.STATIC_CACHE_MAX_AGE || oneWeekInSeconds * 4;
const staticCache = (staticPath) =>
express.static(staticPath, {
setHeaders: (res) => {
if (process.env.NODE_ENV.toLowerCase() !== 'production') {
return;
}
res.setHeader('Cache-Control', `public, max-age=${maxAge}, s-maxage=${sMaxAge}`);
},
});
module.exports = staticCache;

55
package-lock.json generated
View file

@ -55,6 +55,7 @@
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",
"cohere-ai": "^7.9.1", "cohere-ai": "^7.9.1",
"compression": "^1.7.4",
"connect-redis": "^7.1.0", "connect-redis": "^7.1.0",
"cookie": "^0.5.0", "cookie": "^0.5.0",
"cors": "^2.8.5", "cors": "^2.8.5",
@ -12729,6 +12730,60 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/compressible": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
"integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
"dependencies": {
"mime-db": ">= 1.43.0 < 2"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/compression": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
"integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
"dependencies": {
"accepts": "~1.3.5",
"bytes": "3.0.0",
"compressible": "~2.0.16",
"debug": "2.6.9",
"on-headers": "~1.0.2",
"safe-buffer": "5.1.2",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/compression/node_modules/bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/compression/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/compression/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/compression/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",