2b037ee146
If we don't block on SDK builds, then the riot-web build fails due to half-built dependencies. This needs to be done at two levels: the js-sdk because it is used by both the react-sdk and riot-web, and at the react-sdk because riot-web needs it. This means our build process is synchronous for js -> react -> riot, at least for the initial build. This does increase the startup time, particularly because the file watch timer is at 5 seconds. The timer is used to detect a storm of file changes in the underlying SDKs and give the build process some room to compile larger files if needed. The file watcher is accompanied by a "canary signal file" to prevent the build-blocking script from unblocking too early. Both the js and react SDKs build when `npm install` is run, so we ensure that we only listen for the `npm start` build for each SDK. This is all done at the riot level instead of at the individual SDK levels (where we could use a canary file to signal up the stack) because: * babel (used by the js-sdk) doesn't really provide an "end up build" signal * webpack is a bit of a nightmare to get it to behave at times * this blocking approach is really only applicable to riot-web, although may be useful to some other projects. Hopefully that all makes sense.
69 lines
No EOL
2.1 KiB
JavaScript
69 lines
No EOL
2.1 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const child_process = require('child_process');
|
|
|
|
|
|
const task = process.argv[2];
|
|
if (task !== "build" && task !== "watch") {
|
|
console.error("Expected a task of 'build' or 'watch'");
|
|
process.exit(1);
|
|
}
|
|
|
|
const sdkName = process.argv[3];
|
|
if (!sdkName) {
|
|
console.error("Missing SDK name");
|
|
process.exit(1);
|
|
}
|
|
|
|
const sdkPath = path.dirname(require.resolve(`matrix-${sdkName}-sdk/package.json`));
|
|
console.log(sdkPath);
|
|
|
|
// We only want to build the SDK if it looks like it was `npm link`ed
|
|
if (fs.existsSync(path.join(sdkPath, '.git'))) {
|
|
console.log("Installing develop dependencies");
|
|
const devEnv = Object.assign({}, process.env, {NODE_ENV: "development"});
|
|
child_process.execSync("npm install --only=dev", {
|
|
env: devEnv,
|
|
cwd: sdkPath,
|
|
});
|
|
|
|
// Because webpack is made of fail
|
|
if (sdkName === "js") {
|
|
console.log("Installing source-map-loader");
|
|
child_process.execSync("npm install source-map-loader", {
|
|
env: devEnv,
|
|
cwd: sdkPath,
|
|
});
|
|
}
|
|
|
|
console.log("Sending signal that other processes may unblock");
|
|
triggerCanarySignal(sdkName);
|
|
|
|
console.log("Performing task: " + task);
|
|
child_process.execSync(`npm ${task === "build" ? "run build" : "start"}`, {
|
|
env: process.env,
|
|
cwd: sdkPath,
|
|
});
|
|
}
|
|
|
|
function triggerCanarySignal(sdkName) {
|
|
const tmpPath = path.resolve(".tmp");
|
|
|
|
try {
|
|
fs.mkdirSync(tmpPath);
|
|
} catch (e) {
|
|
if (e.code !== 'EEXIST') {
|
|
console.error(e);
|
|
throw "Failed to create temporary directory";
|
|
}
|
|
}
|
|
|
|
// Note: we intentionally create then delete the file to work around
|
|
// a file watching problem where if the file exists on startup it may
|
|
// fire a "created" event for the file. By having the behaviour be "do
|
|
// something on delete" we avoid accidentally firing the signal too
|
|
// early.
|
|
const canaryPath = path.join(tmpPath, sdkName);
|
|
fs.closeSync(fs.openSync(canaryPath, 'w'));
|
|
fs.unlinkSync(canaryPath);
|
|
} |