webpack-plugin-mf 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ default: () => mf
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+ function mf(options = {}) {
27
+ const {
28
+ role = "host",
29
+ name = "app",
30
+ filename = "remoteEntry.js",
31
+ remotes = [],
32
+ exposes = [],
33
+ shared = []
34
+ } = options;
35
+ return async () => {
36
+ const webpackPath = require.resolve("webpack", { paths: [process.cwd()] });
37
+ const webpackMod = require(webpackPath);
38
+ const MFPlugin = webpackMod.container.ModuleFederationPlugin;
39
+ const remotesMap = {};
40
+ for (const r of remotes) {
41
+ const alias = r.alias ?? r.name;
42
+ remotesMap[alias] = `${r.name}@${r.entry}`;
43
+ }
44
+ const exposesMap = {};
45
+ for (const e of exposes) {
46
+ exposesMap[e.expose] = e.module;
47
+ }
48
+ const sharedConfig = {};
49
+ for (const dep of shared) {
50
+ let version = "*";
51
+ try {
52
+ const pkg = require(`${dep}/package.json`);
53
+ version = `^${pkg.version}`;
54
+ } catch {
55
+ }
56
+ sharedConfig[dep] = { singleton: true, requiredVersion: version };
57
+ }
58
+ const isRemote = role === "remote" || role === "both";
59
+ const isHost = role === "host" || role === "both";
60
+ return {
61
+ output: {
62
+ publicPath: "auto"
63
+ },
64
+ plugins: [
65
+ new MFPlugin({
66
+ name,
67
+ filename: isRemote ? filename : void 0,
68
+ remotes: isHost ? remotesMap : void 0,
69
+ exposes: isRemote ? exposesMap : void 0,
70
+ shared: sharedConfig
71
+ })
72
+ ]
73
+ };
74
+ };
75
+ }
@@ -0,0 +1,91 @@
1
+ import { WebpackPresetPlugin } from 'webpack-common';
2
+ export { WebpackConfig, WebpackPresetPlugin } from 'webpack-common';
3
+
4
+ type MfRole = 'host' | 'remote' | 'both';
5
+ interface RemoteEntry {
6
+ /** 远端应用名称,用于 import("remoteName/Component") */
7
+ name: string;
8
+ /** 远端 remoteEntry.js 的 URL */
9
+ entry: string;
10
+ /** 暴露的模块别名,默认 name */
11
+ alias?: string;
12
+ }
13
+ interface ExposeEntry {
14
+ /** 暴露路径,如 './Button' */
15
+ expose: string;
16
+ /** 本地模块路径,如 './src/components/Button' */
17
+ module: string;
18
+ }
19
+ interface MfPluginOptions {
20
+ /**
21
+ * 当前应用角色
22
+ * - 'host': 消费其他应用的模块
23
+ * - 'remote': 暴露自己的模块给其他应用
24
+ * - 'both': 同时作为 host 和 remote
25
+ * 默认 'host'
26
+ */
27
+ role?: MfRole;
28
+ /**
29
+ * 当前应用名称(作为 remote 时必填)
30
+ */
31
+ name?: string;
32
+ /**
33
+ * remoteEntry 文件名,默认 'remoteEntry.js'
34
+ */
35
+ filename?: string;
36
+ /**
37
+ * 消费的远端应用列表(host 模式)
38
+ */
39
+ remotes?: RemoteEntry[];
40
+ /**
41
+ * 对外暴露的模块(remote 模式)
42
+ */
43
+ exposes?: ExposeEntry[];
44
+ /**
45
+ * 共享依赖(自动从 package.json 读取版本)
46
+ */
47
+ shared?: string[];
48
+ }
49
+ /**
50
+ * Module Federation webpack preset plugin
51
+ *
52
+ * @example Host 应用(消费远端模块)
53
+ * ```ts
54
+ * import { defineConfig } from 'webpack-common'
55
+ * import react from 'webpack-plugin-react'
56
+ * import mf from 'webpack-plugin-mf'
57
+ *
58
+ * export default defineConfig({
59
+ * presets: [
60
+ * react(),
61
+ * mf({
62
+ * role: 'host',
63
+ * remotes: [
64
+ * { name: 'remoteApp', entry: 'http://localhost:3001/remoteEntry.js' },
65
+ * ],
66
+ * shared: ['react', 'react-dom'],
67
+ * }),
68
+ * ],
69
+ * })
70
+ * ```
71
+ *
72
+ * @example Remote 应用(暴露模块)
73
+ * ```ts
74
+ * export default defineConfig({
75
+ * presets: [
76
+ * react(),
77
+ * mf({
78
+ * role: 'remote',
79
+ * name: 'remoteApp',
80
+ * exposes: [
81
+ * { expose: './Button', module: './src/components/Button' },
82
+ * ],
83
+ * shared: ['react', 'react-dom'],
84
+ * }),
85
+ * ],
86
+ * })
87
+ * ```
88
+ */
89
+ declare function mf(options?: MfPluginOptions): WebpackPresetPlugin;
90
+
91
+ export { type ExposeEntry, type MfPluginOptions, type MfRole, type RemoteEntry, mf as default };
@@ -0,0 +1,91 @@
1
+ import { WebpackPresetPlugin } from 'webpack-common';
2
+ export { WebpackConfig, WebpackPresetPlugin } from 'webpack-common';
3
+
4
+ type MfRole = 'host' | 'remote' | 'both';
5
+ interface RemoteEntry {
6
+ /** 远端应用名称,用于 import("remoteName/Component") */
7
+ name: string;
8
+ /** 远端 remoteEntry.js 的 URL */
9
+ entry: string;
10
+ /** 暴露的模块别名,默认 name */
11
+ alias?: string;
12
+ }
13
+ interface ExposeEntry {
14
+ /** 暴露路径,如 './Button' */
15
+ expose: string;
16
+ /** 本地模块路径,如 './src/components/Button' */
17
+ module: string;
18
+ }
19
+ interface MfPluginOptions {
20
+ /**
21
+ * 当前应用角色
22
+ * - 'host': 消费其他应用的模块
23
+ * - 'remote': 暴露自己的模块给其他应用
24
+ * - 'both': 同时作为 host 和 remote
25
+ * 默认 'host'
26
+ */
27
+ role?: MfRole;
28
+ /**
29
+ * 当前应用名称(作为 remote 时必填)
30
+ */
31
+ name?: string;
32
+ /**
33
+ * remoteEntry 文件名,默认 'remoteEntry.js'
34
+ */
35
+ filename?: string;
36
+ /**
37
+ * 消费的远端应用列表(host 模式)
38
+ */
39
+ remotes?: RemoteEntry[];
40
+ /**
41
+ * 对外暴露的模块(remote 模式)
42
+ */
43
+ exposes?: ExposeEntry[];
44
+ /**
45
+ * 共享依赖(自动从 package.json 读取版本)
46
+ */
47
+ shared?: string[];
48
+ }
49
+ /**
50
+ * Module Federation webpack preset plugin
51
+ *
52
+ * @example Host 应用(消费远端模块)
53
+ * ```ts
54
+ * import { defineConfig } from 'webpack-common'
55
+ * import react from 'webpack-plugin-react'
56
+ * import mf from 'webpack-plugin-mf'
57
+ *
58
+ * export default defineConfig({
59
+ * presets: [
60
+ * react(),
61
+ * mf({
62
+ * role: 'host',
63
+ * remotes: [
64
+ * { name: 'remoteApp', entry: 'http://localhost:3001/remoteEntry.js' },
65
+ * ],
66
+ * shared: ['react', 'react-dom'],
67
+ * }),
68
+ * ],
69
+ * })
70
+ * ```
71
+ *
72
+ * @example Remote 应用(暴露模块)
73
+ * ```ts
74
+ * export default defineConfig({
75
+ * presets: [
76
+ * react(),
77
+ * mf({
78
+ * role: 'remote',
79
+ * name: 'remoteApp',
80
+ * exposes: [
81
+ * { expose: './Button', module: './src/components/Button' },
82
+ * ],
83
+ * shared: ['react', 'react-dom'],
84
+ * }),
85
+ * ],
86
+ * })
87
+ * ```
88
+ */
89
+ declare function mf(options?: MfPluginOptions): WebpackPresetPlugin;
90
+
91
+ export { type ExposeEntry, type MfPluginOptions, type MfRole, type RemoteEntry, mf as default };
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/index.ts
9
+ function mf(options = {}) {
10
+ const {
11
+ role = "host",
12
+ name = "app",
13
+ filename = "remoteEntry.js",
14
+ remotes = [],
15
+ exposes = [],
16
+ shared = []
17
+ } = options;
18
+ return async () => {
19
+ const webpackPath = __require.resolve("webpack", { paths: [process.cwd()] });
20
+ const webpackMod = __require(webpackPath);
21
+ const MFPlugin = webpackMod.container.ModuleFederationPlugin;
22
+ const remotesMap = {};
23
+ for (const r of remotes) {
24
+ const alias = r.alias ?? r.name;
25
+ remotesMap[alias] = `${r.name}@${r.entry}`;
26
+ }
27
+ const exposesMap = {};
28
+ for (const e of exposes) {
29
+ exposesMap[e.expose] = e.module;
30
+ }
31
+ const sharedConfig = {};
32
+ for (const dep of shared) {
33
+ let version = "*";
34
+ try {
35
+ const pkg = __require(`${dep}/package.json`);
36
+ version = `^${pkg.version}`;
37
+ } catch {
38
+ }
39
+ sharedConfig[dep] = { singleton: true, requiredVersion: version };
40
+ }
41
+ const isRemote = role === "remote" || role === "both";
42
+ const isHost = role === "host" || role === "both";
43
+ return {
44
+ output: {
45
+ publicPath: "auto"
46
+ },
47
+ plugins: [
48
+ new MFPlugin({
49
+ name,
50
+ filename: isRemote ? filename : void 0,
51
+ remotes: isHost ? remotesMap : void 0,
52
+ exposes: isRemote ? exposesMap : void 0,
53
+ shared: sharedConfig
54
+ })
55
+ ]
56
+ };
57
+ };
58
+ }
59
+ export {
60
+ mf as default
61
+ };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "webpack-plugin-mf",
3
+ "version": "0.1.0",
4
+ "description": "Webpack preset plugin for Module Federation (micro-frontend)",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
20
+ "dev": "tsup src/index.ts --format esm,cjs --dts --watch"
21
+ },
22
+ "dependencies": {
23
+ "webpack-common": "workspace:*",
24
+ "webpack-merge": "^6.0.0"
25
+ },
26
+ "peerDependencies": {
27
+ "@module-federation/enhanced": ">=0.1.0",
28
+ "webpack": "^5.0.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "@module-federation/enhanced": {
32
+ "optional": true
33
+ }
34
+ },
35
+ "devDependencies": {
36
+ "@module-federation/enhanced": "^2.0.0",
37
+ "@types/node": "^22.0.0",
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.0.0",
40
+ "webpack": "^5.0.0"
41
+ },
42
+ "license": "MIT",
43
+ "module": "dist/index.js"
44
+ }