diff --git a/ace-loader/src/gen-abc.js b/ace-loader/src/gen-abc.js index ba4dfc6c9a3d9d6385e859e724ceb5817db66138..ef97166079b8ac46dd4312a2e2b54a685bd21311 100644 --- a/ace-loader/src/gen-abc.js +++ b/ace-loader/src/gen-abc.js @@ -24,10 +24,6 @@ function js2abcByWorkers(jsonInput, cmd) { let singleCmd = `${cmd} "${input}"`; childProcess.execSync(singleCmd); - if (fs.existsSync(input)) { - fs.unlinkSync(input); - } - const abcFile = input.replace(/\.js$/, '.abc'); if (fs.existsSync(abcFile)) { const abcFileNew = abcFile.replace(/_.abc$/, '.abc'); diff --git a/ace-loader/src/genAbc-plugin.js b/ace-loader/src/genAbc-plugin.js index fbb6a9936ae3a5caaafc3afa51e51bd61428eeb3..80a47bf387fdcb9ac7f5d4fee2e36684e15942a8 100644 --- a/ace-loader/src/genAbc-plugin.js +++ b/ace-loader/src/genAbc-plugin.js @@ -17,6 +17,7 @@ const fs = require('fs'); const path = require('path'); const cluster = require('cluster'); const process = require('process'); +const crypto = require('crypto'); const forward = '(global.___mainEntry___ = function (globalObjects) {' + '\n' + ' var define = globalObjects.define;' + '\n' + @@ -35,6 +36,8 @@ const forward = '(global.___mainEntry___ = function (globalObjects) {' + '\n' + const last = '\n' + '})(this.__appProto__);' + '\n' + '})'; const firstFileEXT = '_.js'; const genAbcScript = 'gen-abc.js'; +const hashFile = 'gen_hash.json'; +const ARK = '/ark/'; let output; let isWin = false; let isMac = false; @@ -42,6 +45,9 @@ let isDebug = false; let arkDir; let nodeJs; let intermediateJsBundle = []; +let fileterIntermediateJsBundle = []; +let hashJsonObject = {}; +let buildPathInfo = ""; class GenAbcPlugin { constructor(output_, arkDir_, nodeJs_, isDebug_) { @@ -78,6 +84,7 @@ class GenAbcPlugin { }) }); compiler.hooks.afterEmit.tap('GenAbcPluginMultiThread', () => { + buildPathInfo = output; invokeWorkerToGenAbc(); }); } @@ -151,8 +158,9 @@ function invokeWorkerToGenAbc() { js2abc = path.join(arkDir, 'build-mac', 'src', 'index.js'); } + filterIntermediateJsBundleByHashJson(buildPathInfo, intermediateJsBundle); const maxWorkerNumber = 3; - const splitedBundles = splitJsBundlesBySize(intermediateJsBundle, maxWorkerNumber); + const splitedBundles = splitJsBundlesBySize(fileterIntermediateJsBundle, maxWorkerNumber); const workerNumber = maxWorkerNumber < splitedBundles.length ? maxWorkerNumber : splitedBundles.length; const cmdPrefix = `${nodeJs} --expose-gc "${js2abc}" ${param} `; @@ -180,7 +188,105 @@ function invokeWorkerToGenAbc() { } cluster.on('exit', (worker, code, signal) => {}); + + process.on('exit', (code) => { + writeHashJson(); + }); + } +} + + +function filterIntermediateJsBundleByHashJson(buildPath, inputPaths) { + for (let i = 0; i < inputPaths.length; ++i) { + fileterIntermediateJsBundle.push(inputPaths[i]); + } + const hashFilePath = genHashJsonPath(buildPath); + if (hashFilePath.length == 0) { + return ; } + let updateJsonObject = {}; + let jsonObject = {}; + let jsonFile = ""; + if (fs.existsSync(hashFilePath)) { + jsonFile = fs.readFileSync(hashFilePath).toString(); + jsonObject = JSON.parse(jsonFile); + fileterIntermediateJsBundle = []; + for (let i = 0; i < inputPaths.length; ++i) { + let input = inputPaths[i].path; + let abcPath = input.replace(/_.js$/, '.abc'); + if (fs.existsSync(input) && fs.existsSync(abcPath)) { + const hashInputContentData = toHashData(input); + const hashAbcContentData = toHashData(abcPath); + if (jsonObject[input] === hashInputContentData && jsonObject[abcPath] === hashAbcContentData) { + updateJsonObject[input] = hashInputContentData; + updateJsonObject[abcPath] = hashAbcContentData; + fs.unlinkSync(input); + } else { + fileterIntermediateJsBundle.push(inputPaths[i]); + } + } else { + fileterIntermediateJsBundle.push(inputPaths[i]); + } + } + } + + hashJsonObject = updateJsonObject; +} + +function writeHashJson() { + for (let i = 0; i < fileterIntermediateJsBundle.length; ++i) { + let input = fileterIntermediateJsBundle[i].path; + let abcPath = input.replace(/_.js$/, '.abc'); + if (fs.existsSync(input) && fs.existsSync(abcPath)) { + const hashInputContentData = toHashData(input); + const hashAbcContentData = toHashData(abcPath); + hashJsonObject[input] = hashInputContentData; + hashJsonObject[abcPath] = hashAbcContentData; + } + if (fs.existsSync(input)) { + fs.unlinkSync(input); + } + } + const hashFilePath = genHashJsonPath(buildPathInfo); + if (hashFilePath.length == 0) { + return ; + } + fs.writeFileSync(hashFilePath, JSON.stringify(hashJsonObject)); +} + +function genHashJsonPath(buildPath) { + buildPath = toUnixPath(buildPath); + if (process.env.cachePath) { + if (!fs.existsSync(process.env.cachePath) || !fs.statSync(process.env.cachePath).isDirectory()) { + return ''; + } + return path.join(process.env.cachePath, hashFile); + } else if (buildPath.indexOf(ARK) >= 0) { + const dataTmps = buildPath.split(ARK); + const hashPath = path.join(dataTmps[0], ARK); + if (!fs.existsSync(hashPath) || !fs.statSync(hashPath).isDirectory()) { + return ''; + } + return path.join(hashPath, hashFile); + } else { + return ''; + } +} + +function toUnixPath(data) { + if (/^win/.test(require('os').platform())) { + const fileTmps = data.split(path.sep); + const newData = path.posix.join(...fileTmps); + return newData; + } + return data; +} + +function toHashData(path) { + const content = fs.readFileSync(path); + const hash = crypto.createHash('sha256'); + hash.update(content); + return hash.digest('hex'); } module.exports = GenAbcPlugin;