const { ModuleAnalyser } = require("deep-scope-analyser"); // const version = require("./package.json").version; const pluginName = "WebpackDeepScopeAnalysisPlugin"; class WebpackDeepScopeAnalysisPlugin { constructor() { this.moduleMap = new WeakMap(); } apply(compiler) { compiler.hooks.compilation.tap( pluginName, (compilation, { normalModuleFactory }) => { compilation.hooks.dependencyReference.tap( pluginName, (depRef, dep, module) => { if (dep.type === "harmony import specifier") { const moduleScopeAnalyser = this.moduleMap.get(module); if (typeof moduleScopeAnalyser === "undefined") { return depRef; } let { usedExports } = dep.originModule; if (usedExports === false) usedExports = []; if ( usedExports && dep.id && !dep.namespaceObjectAsContext && Array.isArray(usedExports) ) { const exportInfo = moduleScopeAnalyser.generateExportInfo(usedExports); if (dep.request in exportInfo) { const names = exportInfo[dep.request]; if (names === true) { return depRef; } else if (names.indexOf(dep.id) >= 0) { return depRef; } else { return null; } } else { return null; } } } }, ); const handler = (parser, parserOptions) => { if ( typeof parserOptions.harmony !== "undefined" && !parserOptions.harmony ) { return; } parser.hooks.program.tap(pluginName, (ast, comments) => { const { module } = parser.state; const resourceName = module.resource; if (!this.moduleMap.has(module)) { const analyser = new ModuleAnalyser(resourceName, module); analyser.analyze(ast, { comments, }); this.moduleMap.set(module, analyser); } }); }; normalModuleFactory.hooks.parser .for("javascript/auto") .tap(pluginName, handler); normalModuleFactory.hooks.parser .for("javascript/esm") .tap(pluginName, handler); }, ); } } module.exports = { default: WebpackDeepScopeAnalysisPlugin, ModuleAnalyser, };