diff --git a/docker/build-lib.js b/docker/build-lib.js index 7676ec075..95137125e 100644 --- a/docker/build-lib.js +++ b/docker/build-lib.js @@ -1,4 +1,4 @@ import getWebpackServeMiddleware from '../src/middleware/webpack-serve.js'; const middleware = getWebpackServeMiddleware(); -await middleware.runWebpackCompiler(); +await middleware.runWebpackCompiler(true); diff --git a/package-lock.json b/package-lock.json index 0c1415443..af55caae2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "ip-matching": "^2.1.2", "ip-regex": "^5.0.0", "ipaddr.js": "^2.0.1", + "is-docker": "^3.0.0", "jimp": "^0.22.10", "localforage": "^1.10.0", "lodash": "^4.17.21", @@ -4649,15 +4650,15 @@ "license": "MIT" }, "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "license": "MIT", "bin": { "is-docker": "cli.js" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4734,6 +4735,21 @@ "node": ">=8" } }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -5518,6 +5534,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openai": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/openai/-/openai-4.17.4.tgz", diff --git a/package.json b/package.json index 35617b74a..37fdc5e38 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "ip-matching": "^2.1.2", "ip-regex": "^5.0.0", "ipaddr.js": "^2.0.1", + "is-docker": "^3.0.0", "jimp": "^0.22.10", "localforage": "^1.10.0", "lodash": "^4.17.21", diff --git a/src/middleware/webpack-serve.js b/src/middleware/webpack-serve.js index 950e0a941..c62c39486 100644 --- a/src/middleware/webpack-serve.js +++ b/src/middleware/webpack-serve.js @@ -1,11 +1,8 @@ import path from 'node:path'; import webpack from 'webpack'; -import { publicLibConfig } from '../../webpack.config.js'; +import getPublicLibConfig from '../../webpack.config.js'; export default function getWebpackServeMiddleware() { - const outputPath = publicLibConfig.output?.path; - const outputFile = publicLibConfig.output?.filename; - /** * A very spartan recreation of webpack-dev-middleware. * @param {import('express').Request} req Request object. @@ -14,6 +11,10 @@ export default function getWebpackServeMiddleware() { * @type {import('express').RequestHandler} */ function devMiddleware(req, res, next) { + const publicLibConfig = getPublicLibConfig(); + const outputPath = publicLibConfig.output?.path; + const outputFile = publicLibConfig.output?.filename; + if (req.method === 'GET' && path.parse(req.path).base === outputFile) { return res.sendFile(outputFile, { root: outputPath }); } @@ -23,9 +24,11 @@ export default function getWebpackServeMiddleware() { /** * Wait until Webpack is done compiling. + * @param {boolean} [forceDist=false] Whether to force the use the /dist folder. * @returns {Promise} */ - devMiddleware.runWebpackCompiler = () => { + devMiddleware.runWebpackCompiler = (forceDist = false) => { + const publicLibConfig = getPublicLibConfig(forceDist); const compiler = webpack(publicLibConfig); return new Promise((resolve) => { diff --git a/webpack.config.js b/webpack.config.js index 187c7ded9..3579a3cae 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,35 +1,72 @@ import process from 'node:process'; import path from 'node:path'; +import isDocker from 'is-docker'; -/** @type {import('webpack').Configuration} */ -export const publicLibConfig = { - mode: 'production', - entry: './public/lib.js', - cache: { - type: 'filesystem', - cacheDirectory: path.resolve(process.cwd(), 'dist/webpack'), - store: 'pack', - compression: 'gzip', - }, - devtool: false, - watch: false, - module: {}, - stats: { - preset: 'minimal', - assets: false, - modules: false, - colors: true, - timings: true, - }, - experiments: { - outputModule: true, - }, - performance: { - hints: false, - }, - output: { - path: path.resolve(process.cwd(), 'dist'), - filename: 'lib.js', - libraryTarget: 'module', - }, -}; +/** + * Get the Webpack configuration for the public/lib.js file. + * 1. Docker has got cache and the output file pre-baked. + * 2. Non-Docker environments use the global DATA_ROOT variable to determine the cache and output directories. + * @param {boolean} forceDist Whether to force the use the /dist folder. + * @returns {import('webpack').Configuration} + * @throws {Error} If the DATA_ROOT variable is not set. + * */ +export default function getPublicLibConfig(forceDist = false) { + function getCacheDirectory() { + if (forceDist || isDocker()) { + return path.resolve(process.cwd(), 'dist/webpack'); + } + + if (typeof globalThis.DATA_ROOT === 'string') { + return path.resolve(globalThis.DATA_ROOT, '_webpack', 'cache'); + } + + throw new Error('DATA_ROOT variable is not set.'); + } + + function getOutputDirectory() { + if (forceDist || isDocker()) { + return path.resolve(process.cwd(), 'dist'); + } + + if (typeof globalThis.DATA_ROOT === 'string') { + return path.resolve(globalThis.DATA_ROOT, '_webpack', 'output'); + } + + throw new Error('DATA_ROOT variable is not set.'); + } + + const cacheDirectory = getCacheDirectory(); + const outputDirectory = getOutputDirectory(); + + return { + mode: 'production', + entry: './public/lib.js', + cache: { + type: 'filesystem', + cacheDirectory: cacheDirectory, + store: 'pack', + compression: 'gzip', + }, + devtool: false, + watch: false, + module: {}, + stats: { + preset: 'minimal', + assets: false, + modules: false, + colors: true, + timings: true, + }, + experiments: { + outputModule: true, + }, + performance: { + hints: false, + }, + output: { + path: outputDirectory, + filename: 'lib.js', + libraryTarget: 'module', + }, + }; +}