Skip to content

Commit

Permalink
1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangHongEn committed Nov 23, 2022
1 parent f8b07b1 commit 2bc0273
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 37 deletions.
32 changes: 10 additions & 22 deletions lib/plugin.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* 注释中wpm意思是通过http引入的远程包
*/
const pluginName = "MFWebpack4"
const pluginName = "ModuleFederationPlugin"

const { Template } = require("webpack")
const { ConcatSource } = require("webpack-sources");
Expand All @@ -13,9 +13,7 @@

const importWpmLoaderPath = require.resolve("./import-wpm-loader")
const entryInjectLoaderPath = require.resolve("./entry-inject-loader")
const webpack = require("webpack")
const resolveRequest = require("wpmjs/src/utils/resolveRequest")
const { stringifyHasFun, injectRefreshLoader, getUsedWpmPackages, getEntrysPath, cacheUtil } = require("./utils/utils");
const { injectRefreshLoader, getUsedWpmPackages, getEntrysPath, cacheUtil } = require("./utils/utils");
const addEntry = require("./utils/addEntry")
const {getInitConfigModule, modulePath: virtualInitConfigPath} = require("./virtualModule/initConfig")
const {getSetSharedModule, modulePath: virtualSetSharedPath} = require("./virtualModule/setShared")
Expand All @@ -24,12 +22,9 @@
const resolveCwd = require("resolve-cwd");
const { expandShared } = require("./utils/expandShared");
const {entryResources} = require("./entry-inject-loader")
const SyncBailHook = require('tapable').SyncBailHook;

// https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js
/**
* import http
*/
module.exports = class MFWebpack4 {
module.exports = class ModuleFederationPlugin {
constructor (options = {}) {
this.options = {
remotes: options.remotes || {},
Expand All @@ -41,13 +36,17 @@ const {entryResources} = require("./entry-inject-loader")
shared: options.shared || {},
exposes: options.exposes || {}
}
this._options = options
options = this.options
options.shared = expandShared(options.shared, options.shareScope)
if (!options.name) {
throw new Error("name is required")
}
this.jsonpFunction = ""
this.wpmInitConfig = {}
this.hooks = {
runtimeFetchContainer: new SyncBailHook(['url'])
}
this.genWpmInitConfig()
}

Expand All @@ -68,20 +67,8 @@ const {entryResources} = require("./entry-inject-loader")
this.interceptImport(compiler)
// 7. 使webpack jsonp chunk等待依赖加载
this.patchJsonpChunk(compiler)
this.systemParse(compiler)
}

systemParse(compiler) {
const options = compiler.options
if (!options.module) {
options.module = {}
}
if (!options.module.rules) {
options.module.rules = []
}
options.module.rules.push({ parser: { system: false } })
}


genWpmInitConfig() {
const options = this.options
const remotes = options.remotes || {}
Expand Down Expand Up @@ -376,6 +363,7 @@ const {entryResources} = require("./entry-inject-loader")
new VirtualModulesPlugin({
[virtualLocalSharedPath]: getSharedModule(this),
}).apply(compiler)
// runtimeFetchContainer.call
new VirtualModulesPlugin({
[virtualSetSharedPath]: getSetSharedModule(this),
}).apply(compiler)
Expand Down
114 changes: 114 additions & 0 deletions lib/sdk/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
module.exports = function getWpmjs() {
const usemf = require('usemf')
const resolveRequest = require('semverhook/src/utils/resolveRequest')
const obj = {
idUrlMap: {
},
idDefineMap: {
// id: {
// // "promise"返回的是mf的规范{get(){},init(){}}
// remoteType: "mf" | "promise",
// name,
// }
},
idModuleMap: {},
idModulePromiseMap: {},
get (id) {
return this.idModuleMap[id]
},
wait (pkgs) {
if (!(pkgs instanceof Array)) {
throw new Error("wait(pkgs)入参需要是数组")
}
if (pkgs.length === 0) {
return Promise.resolve()
}
return Promise.all(pkgs.map((pkg) => {
return this.import(pkg)
}))
},
getMFContainer(id, customGetContainer) {
const request = resolveRequest(id)
const remoteType = this.idDefineMap[request.name].remoteType
// mf模块
const config = this.idDefineMap[request.name]
return usemf.getContainer({
url: this.idUrlMap[request.name],
name: config.name,
customGetContainer: remoteType === "promise" ?
() => new Function(`return ${this.idUrlMap[request.name]}`)() :
customGetContainer,
})
},
/**
* dep发起的请求, 不会进此api
* id: @scope....
* id: https?://xxx.com/xxxxx
* id: mfshare:scope:version:react
* @param {*} id
* @returns
*/
import(id) {
if (this.idModulePromiseMap[id]) return this.idModulePromiseMap[id]
const importPromise = Promise.resolve(
(async () => {
if (id.startsWith("mfshare:")) {
return this._importShare(id)
}
const request = resolveRequest(id)
const remoteType = this.idDefineMap[request.name].remoteType
// mf模块
const config = this.idDefineMap[request.name]
return this._resolveMfEntry(usemf.import({
url: this.idUrlMap[request.name],
name: config.name,
customGetContainer: remoteType === "promise" ? () => new Function(`return ${this.idUrlMap[request.name]}`)() : undefined,
}), request)
})()
)
return this.idModulePromiseMap[id] = importPromise.then(res => {
this.idModuleMap[id] = res
return res
})
},
async _importShare(id) {
id = id.replace("mfshare:", "")
const [scope, pkg, version] = id.indexOf(":") > -1 ? id.split(":") : id.split("/")
const fn = await usemf.getShareScopes()[scope][pkg][version].get()
return fn()
},
/**
* 解析mf入口
* @param {*} modulePromise
* @param {*} id
* @returns
*/
async _resolveMfEntry(loadModule, request) {
await loadModule.continerInitPromise
const {entry} = request
if (entry) {
return loadModule("./" + entry)
}
return loadModule()
},
setConfig,
}

function setConfig(customConfig) {
customConfig = customConfig || {}
const {
idUrlMap = {},
idDefineMap = {},
} = customConfig
Object.keys(idUrlMap).forEach(key => {
if (key in this.idUrlMap) return
this.idUrlMap[key] = idUrlMap[key]
})
Object.keys(idDefineMap).forEach(key => {
if (key in this.idDefineMap) return
this.idDefineMap[key] = idDefineMap[key]
})
}

return obj
}
4 changes: 0 additions & 4 deletions lib/virtualModule/exposes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ const path = require("path")
const {modulePath: virtualSetSharedPath} = require("./setShared")
const {modulePath: virtualInitConfigPath} = require("./initConfig")

// initcontainer 选择使用哪个依赖
// 先single 再 version 再strict required
// wpmjs缓存入口的父级包

module.exports.modulePath = path.join(process.cwd(), "$_mfplugin_virtualExposes/index.js")
module.exports.getExposesModule = function (pluginInstance) {
const {options} = pluginInstance
Expand Down
13 changes: 8 additions & 5 deletions lib/virtualModule/initConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ const path = require("path")
module.exports.modulePath = path.join(process.cwd(), "$_mfplugin_virtualInitConfig/index.js")
const {modulePath: virtualSetSharedPath} = require("./setShared")
const {modulePath: virtualLocalSharedPath} = require("./localShared")
const getWpmjsFn = require("../sdk").toString()

module.exports.getInitConfigModule = function (pluginInstance) {
const {options} = pluginInstance
return `
${getWpmjsFn}
const wpmjs = getWpmjs()
/* eslint-disable */
require("wpmjs/dist/index-nosystem.js")
const localShared = require(${JSON.stringify(virtualLocalSharedPath)})
const {getUsedShare} = require(${JSON.stringify(virtualSetSharedPath)})
function pkgFilter(pkg) {
Expand All @@ -23,26 +25,27 @@ module.exports.getInitConfigModule = function (pluginInstance) {
}
if (!window["__mfplugin__${options.name}"]) {
window["__mfplugin__${options.name}"] = {
wpmjs,
initSharedPromise: null,
chunkMap: {},
get(pkg = "") {
return window.wpmjs.get(pkgFilter(pkg))
return wpmjs.get(pkgFilter(pkg))
},
import(pkg = "") {
return window.wpmjs.import(pkgFilter(pkg))
return wpmjs.import(pkgFilter(pkg))
},
async wait(pkgs) {
await this.initSharedPromise
pkgs = pkgs || []
return Promise.all([
window.wpmjs.wait(pkgs.map(pkgFilter))
wpmjs.wait(pkgs.map(pkgFilter))
])
}
}
}
const {initShared} = require(${JSON.stringify(virtualSetSharedPath)})
const initConfig = ${JSON.stringify(pluginInstance.wpmInitConfig)}
window.wpmjs.setConfig(initConfig)
wpmjs.setConfig(initConfig)
window["__mfplugin__initSharedPromise__${options.name}"] = initShared()
`
}
12 changes: 9 additions & 3 deletions lib/virtualModule/setShared.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,15 @@ module.exports.getSetSharedModule = function (pluginInstance) {
const plugin = window["__mfplugin__${options.name}"]
if (!plugin.initSharedPromise) {
plugin.initSharedPromise = Promise.all([${Object.keys(pluginInstance.wpmInitConfig.idUrlMap).map(id => {
return `window.wpmjs.getMFContainer("${id}").then(container => {
return container.init(window.usemf.getShareScopes()["${options.shareScope}"])
})`
const customGetContainer = pluginInstance.hooks.runtimeFetchContainer.call(id, pluginInstance.wpmInitConfig.idUrlMap[id])
return `
plugin.wpmjs.getMFContainer("${id}",
${customGetContainer}
)
.then(container => {
return container.init(window.usemf.getShareScopes()["${options.shareScope}"])
})
`
}).join(",")}])
}
return plugin.initSharedPromise
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@module-federation/webpack-4",
"version": "1.1.0",
"name": "mf-webpack4",
"version": "1.2.0",
"description": "Webpack 4 Module Federation Plugin",
"repository": {
"type": "git",
Expand Down Expand Up @@ -28,7 +28,8 @@
"pkg-dir": "5",
"resolve-cwd": "^3.0.0",
"webpack-virtual-modules": "^0.4.4",
"wpmjs": "^2.4.0"
"usemf": "^0.4.16",
"semverhook": "^1.1.0"
},
"peerDependencies": {
"loader-utils": "^1.4.0",
Expand Down

0 comments on commit 2bc0273

Please sign in to comment.