UNPKG

fuse-box

Version:

Fuse-Box a bundler that does it right

266 lines (264 loc) • 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const ModuleCollection_1 = require("./core/ModuleCollection"); const Config_1 = require("./Config"); const realm_utils_1 = require("realm-utils"); const fsExtra = require("fs-extra"); const fs = require("fs"); const path = require("path"); const MEMORY_CACHE = {}; class ModuleCache { constructor(context) { this.context = context; this.cachedDeps = { tree: {}, flat: {}, }; } initialize() { this.cacheFolder = path.join(Config_1.Config.TEMP_FOLDER, "cache", Config_1.Config.FUSEBOX_VERSION, this.context.output.getUniqueHash()); this.permanentCacheFolder = path.join(this.cacheFolder, "permanent"); fsExtra.ensureDirSync(this.permanentCacheFolder); this.staticCacheFolder = path.join(this.cacheFolder, "static"); fsExtra.ensureDirSync(this.staticCacheFolder); this.cacheFile = path.join(this.cacheFolder, "deps.json"); if (fs.existsSync(this.cacheFile)) { try { this.cachedDeps = require(this.cacheFile); } catch (e) { this.cachedDeps = { tree: {}, flat: {}, }; } } } setPermanentCache(key, contents) { key = encodeURIComponent(key); let filePath = path.join(this.permanentCacheFolder, key); fs.writeFile(filePath, contents, () => { }); MEMORY_CACHE[filePath] = contents; } getPermanentCache(key) { key = encodeURIComponent(key); let filePath = path.join(this.permanentCacheFolder, key); if (MEMORY_CACHE[filePath]) { return MEMORY_CACHE[filePath]; } if (fs.existsSync(filePath)) { const contents = fs.readFileSync(filePath).toString(); MEMORY_CACHE[filePath] = contents; return contents; } } getStaticCacheKey(file) { return encodeURIComponent(this.context.bundle.name + file.absPath); } encodeCacheFileName(str) { let ext = path.extname(str); if (ext !== ".js") { str = str + ".js"; } return encodeURIComponent(str); } getStaticCache(file) { let stats = fs.statSync(file.absPath); let fileName = this.encodeCacheFileName(file.info.fuseBoxPath); let memCacheKey = this.getStaticCacheKey(file); let data; if (MEMORY_CACHE[memCacheKey]) { data = MEMORY_CACHE[memCacheKey]; if (data.mtime !== stats.mtime.getTime()) { return; } return data; } else { let dest = path.join(this.staticCacheFolder, fileName); if (fs.existsSync(dest)) { try { data = require(dest); } catch (e) { console.log(e); return; } if (data.mtime !== stats.mtime.getTime()) { return; } MEMORY_CACHE[memCacheKey] = data; return data; } } } writeStaticCache(file, sourcemaps) { let fileName = this.encodeCacheFileName(file.info.fuseBoxPath); let memCacheKey = this.getStaticCacheKey(file); let dest = path.join(this.staticCacheFolder, fileName); let stats = fs.statSync(file.absPath); let cacheData = { contents: file.contents, dependencies: file.analysis.dependencies, sourceMap: sourcemaps || {}, headerContent: file.headerContent, mtime: stats.mtime.getTime() }; if (file.devLibsRequired) { cacheData.devLibsRequired = file.devLibsRequired; } let data = `module.exports = { contents: ${JSON.stringify(cacheData.contents)}, dependencies: ${JSON.stringify(cacheData.dependencies)}, sourceMap: ${JSON.stringify(cacheData.sourceMap)}, headerContent: ${JSON.stringify(cacheData.headerContent)}, mtime: ${cacheData.mtime}, devLibsRequired : ${JSON.stringify(cacheData.devLibsRequired)} };`; MEMORY_CACHE[memCacheKey] = cacheData; fs.writeFileSync(dest, data); } resolve(files) { let through = []; let valid4Caching = []; const moduleFileCollection = new Map(); files.forEach(file => { let info = file.info.nodeModuleInfo; if (!moduleFileCollection.get(info.name)) { moduleFileCollection.set(info.name, new Map()); } moduleFileCollection.get(info.name).set(file.info.fuseBoxPath, file); }); files.forEach(file => { let info = file.info.nodeModuleInfo; let key = `${info.name}@${info.version}`; let cachePath = path.join(this.cacheFolder, encodeURIComponent(key)); let cached = this.cachedDeps.flat[key]; if (!cached || !fs.existsSync(cachePath)) { through.push(file); } else { if (cached.version !== info.version || cached.files.indexOf(file.info.fuseBoxPath) === -1) { through.push(file); for (let i = 0; i < cached.files.length; i++) { let cachedFileName = cached.files[i]; let f = moduleFileCollection.get(info.name).get(cachedFileName); if (f) { through.push(f); } } let index = valid4Caching.indexOf(key); if (index !== -1) { valid4Caching.splice(index, 1); } } else { if (valid4Caching.indexOf(key) === -1) { valid4Caching.push(key); } } } }); const required = []; const operations = []; let cacheReset = false; const getAllRequired = (key, json) => { if (required.indexOf(key) === -1) { if (json) { let collection = new ModuleCollection_1.ModuleCollection(this.context, json.name); let cacheKey = encodeURIComponent(key); collection.cached = true; collection.cachedName = key; collection.cacheFile = path.join(this.cacheFolder, cacheKey); operations.push(new Promise((resolve, reject) => { if (MEMORY_CACHE[collection.cacheFile]) { collection.cachedContent = MEMORY_CACHE[collection.cacheFile]; return resolve(); } if (fs.existsSync(collection.cacheFile)) { fs.readFile(collection.cacheFile, (err, result) => { collection.cachedContent = result.toString(); MEMORY_CACHE[collection.cacheFile] = collection.cachedContent; return resolve(); }); } else { valid4Caching = []; cacheReset = true; return resolve(); } })); this.context.addNodeModule(key, collection); required.push(key); if (json.deps) { for (let k in json.deps) { if (json.deps.hasOwnProperty(k)) { getAllRequired(k, json.deps[k]); } } } } } }; valid4Caching.forEach(key => { getAllRequired(key, this.cachedDeps.tree[key]); }); return Promise.all(operations).then(() => { if (cacheReset) { this.context.resetNodeModules(); return files; } return through; }); } buildMap(rootCollection) { let json = this.cachedDeps; const traverse = (modules, root) => { return realm_utils_1.each(modules, (collection) => { if (collection.traversed) { return; } let dependencies = {}; let flatFiles; if (collection.cached) { return; } let key = `${collection.info.name}@${collection.info.version}`; if (!json.flat[key]) { json.flat[key] = { name: collection.name, version: collection.info.version, files: [], }; } flatFiles = json.flat[key].files; collection.dependencies.forEach(file => { if (flatFiles.indexOf(file.info.fuseBoxPath) < 0) { flatFiles.push(file.info.fuseBoxPath); } }); root[key] = { deps: dependencies, name: collection.info.name, version: collection.info.version, }; collection.traversed = true; return traverse(collection.nodeModules, dependencies); }); }; traverse(rootCollection.nodeModules, json.tree).then(() => { fs.writeFile(this.cacheFile, JSON.stringify(json, undefined, 2), () => { }); }); } set(info, contents) { return new Promise((resolve, reject) => { const cacheKey = encodeURIComponent(`${info.name}@${info.version}`); const targetName = path.join(this.cacheFolder, cacheKey); MEMORY_CACHE[cacheKey] = contents; fs.writeFile(targetName, contents, (err) => { return resolve(); }); }); } } exports.ModuleCache = ModuleCache; //# sourceMappingURL=ModuleCache.js.map