cache all language builds in the same folder

write custom webpack loader to invalidate language specific files
choose most recent asset based on mtime rather than birthtime
This commit is contained in:
HF 2023-12-12 16:29:16 +01:00
parent 22b9cf2612
commit 6d3b6edd8a
3 changed files with 40 additions and 25 deletions

View File

@ -0,0 +1,20 @@
/*
* webpack loader that
* marks modules that include ttag as non-cachable
*/
const filtered = {};
module.exports = function (source) {
if (filtered.hasOwnProperty(this.resourcePath)) {
if (filtered[this.resourcePath]) {
this.cacheable(false);
}
return source;
}
const hasTtag = source.slice(0, 400).includes('ttag');
filtered[this.resourcePath] = hasTtag;
if (hasTtag) {
this.cacheable(false);
}
return source;
}

View File

@ -28,7 +28,7 @@ function checkAssets() {
css: {}, css: {},
}; };
const assetFiles = fs.readdirSync(assetDir); const assetFiles = fs.readdirSync(assetDir);
const birthtimes = {}; const mtimes = {};
for (const filename of assetFiles) { for (const filename of assetFiles) {
const parts = filename.split('.'); const parts = filename.split('.');
@ -38,13 +38,13 @@ function checkAssets() {
continue; continue;
} }
// if multiple candidates exist, take most recent created file // if multiple candidates exist, take most recent created file
const birthtime = fs.statSync(path.resolve(assetDir, filename)) const mtime = fs.statSync(path.resolve(assetDir, filename))
.birthtime.getTime(); .mtime.getTime();
const ident = parts.filter((a, ind) => ind !== parts.length - 2).join('.'); const ident = parts.filter((a, ind) => ind !== parts.length - 2).join('.');
if (birthtimes[ident] && birthtimes[ident] > birthtime) { if (mtimes[ident] && mtimes[ident] > mtime) {
continue; continue;
} }
birthtimes[ident] = birthtime; mtimes[ident] = mtime;
const ext = parts[parts.length - 1]; const ext = parts[parts.length - 1];
const relPath = `${ASSET_DIR}/${filename}`; const relPath = `${ASSET_DIR}/${filename}`;

View File

@ -37,14 +37,6 @@ function buildWebpackClientConfig(
['ttag', ttag], ['ttag', ttag],
]; ];
// cache invalidates if .po file changed
const buildDependencies = {
config: [__filename],
}
if (locale !== 'default') {
buildDependencies.i18n = [ttag.resolve.translations];
}
return { return {
name: 'client', name: 'client',
target: 'web', target: 'web',
@ -69,6 +61,7 @@ function buildWebpackClientConfig(
? '[name].[chunkhash:8].js' ? '[name].[chunkhash:8].js'
: `[name].${locale}.[chunkhash:8].js`, : `[name].${locale}.[chunkhash:8].js`,
chunkFilename: `[name].${locale}.[chunkhash:8].js`, chunkFilename: `[name].${locale}.[chunkhash:8].js`,
clean: true,
}, },
resolve: { resolve: {
@ -91,9 +84,7 @@ function buildWebpackClientConfig(
{ {
test: /\.svg$/, test: /\.svg$/,
use: [ use: [
{ 'babel-loader',
loader: 'babel-loader',
},
{ {
loader: 'react-svg-loader', loader: 'react-svg-loader',
options: { options: {
@ -114,16 +105,21 @@ function buildWebpackClientConfig(
}, },
{ {
test: /\.(js|jsx)$/, test: /\.(js|jsx)$/,
loader: 'babel-loader', use: [
{
loader: 'babel-loader',
options: {
plugins: babelPlugins,
},
},
path.resolve('scripts/TtagNonCacheableLoader.js'),
],
include: [ include: [
path.resolve('src'), path.resolve('src'),
...['image-q'].map((moduleName) => ( ...['image-q'].map((moduleName) => (
path.resolve('node_modules', moduleName) path.resolve('node_modules', moduleName)
)), )),
], ],
options: {
plugins: babelPlugins,
},
}, },
], ],
}, },
@ -168,7 +164,7 @@ function buildWebpackClientConfig(
}, },
}, },
recordsPath: path.join(__dirname, 'records.json'), recordsPath: path.resolve('records.json'),
stats: { stats: {
colors: true, colors: true,
@ -179,20 +175,19 @@ function buildWebpackClientConfig(
}, },
cache: (extract) ? false cache: (extract) ? false
: { : {
type: 'filesystem', type: 'filesystem',
name: (development) ? `${locale}-dev` : locale,
buildDependencies,
}, },
}; };
} }
function getAllAvailableLocals() { function getAllAvailableLocals() {
// return ['default', 'de', 'tr'];
const langDir = path.resolve('i18n'); const langDir = path.resolve('i18n');
const langs = fs.readdirSync(langDir) const langs = fs.readdirSync(langDir)
.filter((e) => (e.endsWith('.po') && !e.startsWith('ssr'))) .filter((e) => (e.endsWith('.po') && !e.startsWith('ssr')))
.map((l) => l.slice(0, -3)); .map((l) => l.slice(0, -3));
langs.push('default'); langs.unshift('default');
return langs; return langs;
} }