const fs = require('fs-extra'); const { generateAsset } = require('./utils'); const t = require('@babel/types'); const babelGenerator = require('@babel/generator'); const babelParser = require('@babel/parser'); const { default: babelTraverse } = require('@babel/traverse'); const getWxMpRuntime = require('../runtime/index'); // TODO 这个工作应该放在loader中做,后续优化 class AddWxMpRuntimePlugin { apply (compiler) { compiler.hooks.emit.tapPromise('AddWxMpRuntimePlugin', compilation => { return new Promise((resolve, reject) => { try { // 收集独立分包路径下面的所有js文件 // js文件都存储在 compilation.assets中 , 因为需要注入 require(`${pkgRoot/common/index.js}`) const thisCompilationAssets = compilation.assets; const independentPkgsInfo = Object.values(process.UNI_SUBPACKAGES).filter(info => info.independent) || []; const independentPkgRoots = independentPkgsInfo.map(info => `${info.root}`); if (!independentPkgRoots.length) { resolve(); } const mpRuntimePath = getWxMpRuntime(); const wxMpRuntimeContent = fs.readFileSync(mpRuntimePath, 'utf8'); const ast = babelParser.parse(wxMpRuntimeContent, { sourceType: 'module', plugins: ['classProperties'], }); babelTraverse(ast, { VariableDeclaration (path) { const v = path.node.declarations[0]; const name = v.id.name; const value = v.init; if (name === 'independentRoots' && t.isArrayExpression(value)) { value.elements = independentPkgRoots.map(pkgRoot => t.StringLiteral(pkgRoot)); } }, }); const { code } = babelGenerator.default(ast); const runtimeAssetsInfo = generateAsset(code); const mpRuntimeRelativePath = 'common/wxMpRuntime.js'; // 处理app.js const appJsName = 'app.js'; thisCompilationAssets[mpRuntimeRelativePath] = runtimeAssetsInfo; const assetInfo = thisCompilationAssets[appJsName]; if (!assetInfo) { return resolve(); } const content = assetInfo.source(); thisCompilationAssets[appJsName] = generateAsset(`require('./common/wxMpRuntime.js');${content}`); // 处理独立分包 independentPkgRoots.forEach(pkgRoot => { thisCompilationAssets[`${pkgRoot}/${mpRuntimeRelativePath}`] = runtimeAssetsInfo; const entryJsName = `${pkgRoot}/common/index.js`; const assetInfo = thisCompilationAssets[entryJsName]; let content = assetInfo.source(); content = generateAsset(`require('./wxMpRuntime.js');${content}`); thisCompilationAssets[entryJsName] = content; }); resolve(); } catch (e) { console.error('AddWxMpRuntimePlugin', e); reject(e); } }); }); } } module.exports = AddWxMpRuntimePlugin;