2019-01-15 21:00:11 +08:00
|
|
|
const fs = require('fs');
|
2018-10-03 22:57:57 +08:00
|
|
|
const path = require('path');
|
|
|
|
const workerFarm = require('worker-farm');
|
|
|
|
const async = require('async');
|
2019-11-20 23:00:19 +08:00
|
|
|
let buildingInProgress = false;
|
|
|
|
let currentBuildingModule = '';
|
2020-11-01 19:48:04 +08:00
|
|
|
|
|
|
|
// some modules will not like the custom stack trace logic
|
|
|
|
const ops = Error.prepareStackTrace;
|
|
|
|
Error.prepareStackTrace = undefined;
|
|
|
|
|
2018-10-03 22:57:57 +08:00
|
|
|
const webpackBuildTask = {
|
2019-11-20 23:00:19 +08:00
|
|
|
shouldBuild(resourceName) {
|
|
|
|
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config');
|
|
|
|
|
|
|
|
if (numMetaData > 0) {
|
|
|
|
for (let i = 0; i < numMetaData; i++) {
|
|
|
|
const configName = GetResourceMetadata(resourceName, 'webpack_config');
|
|
|
|
|
|
|
|
if (shouldBuild(configName)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
function loadCache(config) {
|
|
|
|
const cachePath = `cache/${resourceName}/${config.replace(/\//g, '_')}.json`;
|
|
|
|
|
|
|
|
try {
|
|
|
|
return JSON.parse(fs.readFileSync(cachePath, {encoding: 'utf8'}));
|
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function shouldBuild(config) {
|
|
|
|
const cache = loadCache(config);
|
|
|
|
|
|
|
|
if (!cache) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const file of cache) {
|
|
|
|
const stats = getStat(file.name);
|
|
|
|
|
|
|
|
if (!stats ||
|
|
|
|
stats.mtime !== file.stats.mtime ||
|
|
|
|
stats.size !== file.stats.size ||
|
|
|
|
stats.inode !== file.stats.inode) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getStat(path) {
|
|
|
|
try {
|
|
|
|
const stat = fs.statSync(path);
|
|
|
|
|
|
|
|
return stat ? {
|
|
|
|
mtime: stat.mtimeMs,
|
|
|
|
size: stat.size,
|
|
|
|
inode: stat.ino,
|
|
|
|
} : null;
|
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
build(resourceName, cb) {
|
|
|
|
let buildWebpack = async () => {
|
|
|
|
let error = null;
|
|
|
|
const configs = [];
|
2020-11-01 19:48:04 +08:00
|
|
|
const promises = [];
|
2019-11-20 23:00:19 +08:00
|
|
|
const numMetaData = GetNumResourceMetadata(resourceName, 'webpack_config');
|
|
|
|
|
|
|
|
for (let i = 0; i < numMetaData; i++) {
|
|
|
|
configs.push(GetResourceMetadata(resourceName, 'webpack_config', i));
|
|
|
|
}
|
2020-11-01 19:48:04 +08:00
|
|
|
|
2019-11-20 23:00:19 +08:00
|
|
|
for (const configName of configs) {
|
|
|
|
const configPath = GetResourcePath(resourceName) + '/' + configName;
|
|
|
|
|
|
|
|
const cachePath = `cache/${resourceName}/${configName.replace(/\//g, '_')}.json`;
|
|
|
|
|
|
|
|
try {
|
|
|
|
fs.mkdirSync(path.dirname(cachePath));
|
|
|
|
} catch {
|
|
|
|
}
|
|
|
|
|
|
|
|
const config = require(configPath);
|
|
|
|
|
|
|
|
const workers = workerFarm(require.resolve('./webpack_runner'));
|
|
|
|
|
|
|
|
if (config) {
|
|
|
|
const resourcePath = path.resolve(GetResourcePath(resourceName));
|
|
|
|
|
|
|
|
while (buildingInProgress) {
|
2020-11-01 19:48:04 +08:00
|
|
|
console.log(`webpack is busy: we are waiting to compile ${resourceName} (${configName})`);
|
2019-11-20 23:00:19 +08:00
|
|
|
await sleep(3000);
|
|
|
|
}
|
2020-11-01 19:48:04 +08:00
|
|
|
|
2019-11-20 23:00:19 +08:00
|
|
|
buildingInProgress = true;
|
|
|
|
currentBuildingModule = resourceName;
|
2020-11-01 19:48:04 +08:00
|
|
|
|
|
|
|
promises.push(new Promise((resolve, reject) => {
|
|
|
|
workers({
|
|
|
|
configPath,
|
|
|
|
resourcePath,
|
|
|
|
cachePath
|
|
|
|
}, (err, outp) => {
|
|
|
|
workerFarm.end(workers);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
console.error(err.stack || err);
|
|
|
|
if (err.details) {
|
|
|
|
console.error(err.details);
|
|
|
|
}
|
|
|
|
|
|
|
|
buildingInProgress = false;
|
|
|
|
currentBuildingModule = '';
|
|
|
|
currentBuildingScript = '';
|
|
|
|
reject("worker farm webpack errored out");
|
|
|
|
return;
|
2019-11-20 23:00:19 +08:00
|
|
|
}
|
|
|
|
|
2020-11-01 19:48:04 +08:00
|
|
|
if (outp.errors) {
|
|
|
|
for (const error of outp.errors) {
|
|
|
|
console.log(error);
|
|
|
|
}
|
|
|
|
buildingInProgress = false;
|
|
|
|
currentBuildingModule = '';
|
|
|
|
currentBuildingScript = '';
|
|
|
|
reject("webpack got an error");
|
|
|
|
return;
|
2019-11-20 23:00:19 +08:00
|
|
|
}
|
2020-11-01 19:48:04 +08:00
|
|
|
|
|
|
|
console.log(`${resourceName}: built ${configName}`);
|
|
|
|
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
}));
|
2019-11-20 23:00:19 +08:00
|
|
|
}
|
|
|
|
}
|
2020-11-01 19:48:04 +08:00
|
|
|
|
|
|
|
try {
|
|
|
|
await Promise.all(promises);
|
|
|
|
} catch (e) {
|
|
|
|
error = e.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
buildingInProgress = false;
|
|
|
|
currentBuildingModule = '';
|
|
|
|
|
2019-11-20 23:00:19 +08:00
|
|
|
if (error) {
|
|
|
|
cb(false, error);
|
|
|
|
} else cb(true);
|
|
|
|
};
|
|
|
|
buildWebpack().then();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function sleep(ms) {
|
|
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
2018-10-03 22:57:57 +08:00
|
|
|
}
|
|
|
|
|
2019-11-20 23:00:19 +08:00
|
|
|
RegisterResourceBuildTaskFactory('z_webpack', () => webpackBuildTask);
|