微前端架构中为何构建时频繁生成重复的moduleId?

摘要:在我们的 vue-mfe 微前端项目中,出现了重复的 moduleId。第一次我们的解决办法是使用增大 hash-module-ids 的 hashDigestLength 到 8 位,vue-cli3 默认是 4 位,Webpack 默认
在我们的 vue-mfe 微前端项目中,出现了重复的 moduleId。第一次我们的解决办法是使用增大 hash-module-ids 的 hashDigestLength 到 8 位,vue-cli3 默认是 4 位,Webpack 默认也是 4 位。但是随着 SubApp 资源的增多,还是出现了重复。于是不得不排查了下生成重复的 moduleId 的原因: 案例 在construction SubApp 的 portal.entry.js 中使用了 import commonService from './service/commonService',而在material SubApp portal.entry.js 中也存在相同路径的引用import commonService from './service/commonService'。 然后在 construction 和material 两个 SubApp 之间就出现了冲突,比如说先加载construction,那么material加载的commonService就是先前被加载的moduleCache[modueId]。 Q1: 为什么会出现相同的 modueId 在不同的 webpack 构建上下文中? 因为 webpack hashModuleId 的构建方式是基于当前相对路径生成 moduleId,分别看下文档和代码: 文档: This plugin will cause hashes to be based on the relative path of the module, generating a four character string as the module id. Suggested for use in production. 代码: apply(compiler) { const options = this.options; compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => { const usedIds = new Set(); compilation.hooks.beforeModuleIds.tap( "HashedModuleIdsPlugin", modules => { for (const module of modules) { if (module.id === null && module.libIdent) { // 这就是相对路径位置,调用 module.libIdent 方法 const id = module.libIdent({ context: this.options.context || compiler.options.context }); const hash = createHash(options.hashFunction); hash.update(id); const hashId = /** @type {string} */ (hash.digest( options.hashDigest )); let len = options.hashDigestLength; while (usedIds.has(hashId.substr(0, len))) len++; module.id = hashId.substr(0, len); usedIds.add(module.id); } } } ); }); } 而调用 module.libIdent 方法返回是这样的字符串: 有 loader 的会加上 loader 路径: css:./node_modules/css-loader/index.js?!./node_modules/postcss-loader/src/index.js?!./src/components/virtual-table/table.css", js: ./node_modules/css-loader/lib/css-base.js 而在我们的 SubApp 项目中因为两个路径一致,则生成的 hashId 就成了一样一样的了。
阅读全文