Skip to content

Commit 5560c2d

Browse files
perf(ng): only write tiled data when source file hashes change
- the Tiled game data step is kind of slow to run for every source file change in the codebase. - keep a hash of the listed files that game data comes from, and only run the data generation script when they change.
1 parent 5c8a238 commit 5560c2d

File tree

1 file changed

+57
-10
lines changed

1 file changed

+57
-10
lines changed

src/webpack/game-data-plugin/index.js

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,76 @@
33
const { exec } = require("child_process");
44
const webpack = require("webpack");
55
const { cwd } = require("process");
6-
const { readFileSync, writeFileSync } = require("fs");
6+
const { readFileSync, writeFileSync, createReadStream } = require("fs");
7+
const { createHash } = require("crypto");
8+
9+
const GAME_DATA_COMMAND =
10+
"npx ts-node --transpile-only --project src/tsconfig.write-game-data.json src/write-game-data.ts";
711

812
const PLUGIN_NAME = "write-tiled-game-data";
913

1014
/** Tiled Editor project JSON file */
1115
const PROJECT_FILE = "angular-rpg.tiled-project";
1216

17+
/** Game data is only written when these files change */
18+
const SOURCE_FILES = [
19+
"./src/app/models/game-data/armors.ts",
20+
"./src/app/models/game-data/fixed-encounters.ts",
21+
"./src/app/models/game-data/items.ts",
22+
"./src/app/models/game-data/magic.ts",
23+
"./src/app/models/game-data/random-encounters.ts",
24+
"./src/app/models/game-data/weapons.ts",
25+
];
26+
27+
const SEEN_HASHES = {};
28+
29+
/** Hash the source files used in write-game-data.ts and only run when they change */
30+
function shouldWriteData() {
31+
function checksumFile(filename) {
32+
return new Promise((resolve, reject) => {
33+
const hash = createHash("sha1");
34+
const stream = createReadStream(filename);
35+
stream.on("error", (err) => reject(err));
36+
stream.on("data", (chunk) => hash.update(chunk));
37+
stream.on("end", () => resolve(hash.digest("hex")));
38+
});
39+
}
40+
return Promise.all(SOURCE_FILES.map((filename) => checksumFile(filename))).then(
41+
(hashes) => {
42+
let should = false;
43+
SOURCE_FILES.forEach((filename, index) => {
44+
const hash = hashes[index];
45+
if (!SEEN_HASHES[filename]) {
46+
SEEN_HASHES[filename] = hash;
47+
should = true;
48+
}
49+
if (SEEN_HASHES[filename] !== hash) {
50+
should = true;
51+
}
52+
SEEN_HASHES[filename] = hash;
53+
});
54+
return should;
55+
}
56+
);
57+
}
58+
1359
module.exports = class GameDataPlugin {
1460
apply(compiler) {
15-
var self = this;
1661
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
1762
compilation.hooks.processAssets.tapAsync(
1863
{
1964
name: PLUGIN_NAME,
2065
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
2166
},
2267
(assets, callback) => {
23-
console.log("Writing game data files...");
24-
console.log("CWD = " + cwd());
25-
26-
exec(
27-
"npx ts-node --project src/tsconfig.write-game-data.json src/write-game-data.ts",
28-
(error, stdout, stderr) => {
68+
shouldWriteData().then((should) => {
69+
if (!should) {
70+
console.log("Skipping Tiled write because source files unchanged");
71+
callback();
72+
return;
73+
}
74+
console.log("Writing Tiled data files");
75+
exec(GAME_DATA_COMMAND, (error, stdout, stderr) => {
2976
if (error) {
3077
console.log(`error: ${error.message}`);
3178
callback();
@@ -68,8 +115,8 @@ module.exports = class GameDataPlugin {
68115
console.log("Writing to: " + PROJECT_FILE);
69116
}
70117
callback();
71-
}
72-
);
118+
});
119+
});
73120
}
74121
);
75122
});

0 commit comments

Comments
 (0)