@mainset/bundler-webpack 0.3.7 → 0.4.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.
@@ -1 +1,4 @@
1
1
  export { generateEnvBasedWebpackConfig } from './generate-webpack-config.mjs';
2
+ // NOTE: re-exported so an app can extend the generated config without a
3
+ // direct {webpack-merge} dependency of its own.
4
+ export { merge as mergeWebpackConfig } from 'webpack-merge';
@@ -0,0 +1,2 @@
1
+ export { DOCKER_SAFE__MODULE_FEDERATION_CONFIG_CHUNK, SSR_STYLESHEETS_FILENAME, } from './module-federation.chunk.mjs';
2
+ export { generateModuleFederationCommonWebpackConfigFragment, generateModuleFederationSSRContainerWebpackConfig, generateModuleFederationSSRServerWebpackConfigFragment, generateModuleFederationWebappWebpackConfigFragment, } from './module-federation.fragment.mjs';
@@ -0,0 +1,16 @@
1
+ import { createRequire } from 'module';
2
+ // NOTE: {@module-federation/node} is loaded through its CommonJS build on
3
+ // purpose. Its ESM build aliases its own internal {require} calls to
4
+ // {__require} (a helper of its bundler), and StreamingTargetPlugin embeds some
5
+ // of its source functions verbatim ({fn.toString()}) into the GENERATED
6
+ // chunk-loading runtime — so the ESM build leaks a free {__require} into the
7
+ // app's bundle ("__require is not defined" at runtime). The CJS build's
8
+ // equivalents use plain {require}, which resolves fine.
9
+ const requireFromBundler = createRequire(import.meta.url);
10
+ const { NodeFederationPlugin, StreamingTargetPlugin } = requireFromBundler('@module-federation/node');
11
+ // NOTE: passed to NodeFederationPlugin as {runtimePlugins} explicitly, instead
12
+ // of its own {useRuntimePlugin: true} — that option resolves a path missing
13
+ // from the package's ESM build ({../runtimePlugin.mjs}). The package's
14
+ // exports map exposes the CJS variant, resolved here.
15
+ const NODE_FEDERATION_RUNTIME_PLUGIN_PATH = requireFromBundler.resolve('@module-federation/node/runtimePlugin');
16
+ export { NODE_FEDERATION_RUNTIME_PLUGIN_PATH, NodeFederationPlugin, StreamingTargetPlugin, };
@@ -0,0 +1,48 @@
1
+ // The file names a remote's build emits — part of its contract with whatever
2
+ // deploys and loads it.
3
+ const REMOTE_ENTRY_FILENAME__WEBAPP = 'remoteEntry.js';
4
+ const REMOTE_ENTRY_FILENAME__SSR = 'ssr-remoteEntry.js';
5
+ // NOTE: written next to the webapp build, but read by the hosts' SSR — deploy
6
+ // it with the server build (ssr-remoteEntry.js), not with the browser files,
7
+ // so it switches together with the server code that renders the markup.
8
+ const SSR_STYLESHEETS_FILENAME = 'ssr-stylesheets.json';
9
+ // NOTE: without this, the webapp entry consumes the shared singletons
10
+ // synchronously before Module Federation's share-scope negotiation gets an
11
+ // async tick to run, throwing RUNTIME-006 ("Invalid loadShareSync function
12
+ // call") on every load. {asyncStartup} wraps entry startup in an async
13
+ // boundary so the negotiation can complete first.
14
+ const ASYNC_STARTUP__MODULE_FEDERATION_CONFIG_CHUNK = {
15
+ experiments: { asyncStartup: true },
16
+ };
17
+ // NOTE: Module Federation's tooling writes into all three folders on every
18
+ // compile — the DTS plugin a scratch {tsconfig.<hash>.json} into
19
+ // node_modules/.federation, the manifest plugin {mf-manifest.json} into dist,
20
+ // and {@module-federation/error-codes} a diagnostics dump into .mf/ (on every
21
+ // reported error, at a hardcoded path). Each rewrite bumps mtime even with
22
+ // identical content, which a polling watcher reads as a source change: a
23
+ // self-sustaining rebuild loop, and a TS error in an exposed module surfaces
24
+ // as that loop instead of an error message. None of them is ever a source
25
+ // input, so they are excluded outright.
26
+ const WATCH_OPTIONS__MODULE_FEDERATION__WEBPACK_CONFIG_CHUNK = {
27
+ watchOptions: {
28
+ ignored: ['**/node_modules/**', '**/dist/**', '**/.mf/**'],
29
+ },
30
+ };
31
+ // Opt-in preset (pass it as {pluginOptions}) for running the dev build inside
32
+ // Docker on macOS/Windows: bind-mount file sharing doesn't propagate native fs
33
+ // events reliably, so webpack falls back to polling and can't tell "my own
34
+ // generated output changed" from a real edit.
35
+ // - dts: the default types folder ({@mf-types}) lands in the app root — the
36
+ // bind mount. Redirected into node_modules, which Docker setups usually
37
+ // mask with an anonymous volume.
38
+ // - dev: "hot types reload" hardcodes its output to {<app root>/.dev-server}
39
+ // (no option to move it), so it is turned off. Live reload of the remote's
40
+ // code is unaffected.
41
+ const DOCKER_SAFE__MODULE_FEDERATION_CONFIG_CHUNK = {
42
+ dts: {
43
+ generateTypes: { typesFolder: 'node_modules/.mf-types' },
44
+ consumeTypes: { typesFolder: 'node_modules/.mf-types' },
45
+ },
46
+ dev: { disableHotTypesReload: true },
47
+ };
48
+ export { ASYNC_STARTUP__MODULE_FEDERATION_CONFIG_CHUNK, DOCKER_SAFE__MODULE_FEDERATION_CONFIG_CHUNK, REMOTE_ENTRY_FILENAME__SSR, REMOTE_ENTRY_FILENAME__WEBAPP, SSR_STYLESHEETS_FILENAME, WATCH_OPTIONS__MODULE_FEDERATION__WEBPACK_CONFIG_CHUNK, };
@@ -0,0 +1,161 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { runtimePathById } from '@mainset/cli/runtime';
13
+ import { ModuleFederationPlugin } from '@module-federation/enhanced/webpack';
14
+ import fs from 'fs';
15
+ import path from 'path';
16
+ import { merge } from 'webpack-merge';
17
+ import ssrServerEnvBasedConfig from '../webpack-config/server.ssr.config.mjs';
18
+ import { NODE_FEDERATION_RUNTIME_PLUGIN_PATH, NodeFederationPlugin, StreamingTargetPlugin, } from './module-federation-node.mjs';
19
+ import { ASYNC_STARTUP__MODULE_FEDERATION_CONFIG_CHUNK, REMOTE_ENTRY_FILENAME__SSR, REMOTE_ENTRY_FILENAME__WEBAPP, WATCH_OPTIONS__MODULE_FEDERATION__WEBPACK_CONFIG_CHUNK, } from './module-federation.chunk.mjs';
20
+ import { RemoteStylesheetsPlugin } from './remote-stylesheets.plugin.mjs';
21
+ // NOTE: an SSR host's server entry has to reach its SSR config through a
22
+ // dynamic import — a static import of the shared deps (e.g. react-dom/server)
23
+ // fails Module Federation's share-scope negotiation ({loadShareSync failed}).
24
+ // That async boundary is app code, so it lives next to the SSR config by
25
+ // convention, the same way {ssr-server.config.mts} does.
26
+ const SSR_SERVER_ENTRY_PATH = path.join(runtimePathById.config, 'ssr-server.entry.mts');
27
+ // { landing: { webappEntry: 'https://…/remoteEntry.js' } }
28
+ // → { landing: 'landing@https://…/remoteEntry.js' }
29
+ const generatePluginRemotes = (remotes = {}, entryKey) => Object.fromEntries(Object.entries(remotes).map(([remoteName, remote]) => {
30
+ const remoteEntry = remote[entryKey];
31
+ if (!remoteEntry) {
32
+ throw new Error(`[bundler-webpack] Module Federation remote "${remoteName}" has no {${entryKey}}.`);
33
+ }
34
+ return [remoteName, `${remoteName}@${remoteEntry}`];
35
+ }));
36
+ // NOTE: eager on the server only — nothing there is lazy-loaded for payload
37
+ // size, and the SSR server consumes the shared deps synchronously as soon as it
38
+ // starts. Required together with {webpackMode: "eager"} on the dynamic import
39
+ // in {ssr-server.entry.mts}: that one alone inlines the module, so the shared
40
+ // dep is consumed before negotiation (RUNTIME-006); this one alone leaves a
41
+ // separate chunk the server would then have to load. The browser keeps the
42
+ // non-eager deps — there the async negotiation is both correct and wanted.
43
+ const generateEagerShared = (shared = {}) => Object.fromEntries(Object.entries(shared).map(([sharedName, sharedConfig]) => [
44
+ sharedName,
45
+ Object.assign(Object.assign({}, sharedConfig), { eager: true }),
46
+ ]));
47
+ // Merge into the config passed to {generateEnvBasedWebpackConfig} — it is
48
+ // needed by every compilation of an app that uses Module Federation.
49
+ const generateModuleFederationCommonWebpackConfigFragment = ({ name, }) => merge(WATCH_OPTIONS__MODULE_FEDERATION__WEBPACK_CONFIG_CHUNK, {
50
+ output: {
51
+ // NOTE: must differ between every app on the page — webpack names its
52
+ // global chunk array after it ({self.webpackChunk<uniqueName>}) and
53
+ // defaults it to package.json {name}. Two apps on the same array: the
54
+ // runtime loaded last takes it over, the other app's chunks register in
55
+ // the wrong runtime, and hydration fails ("Cannot read properties of
56
+ // undefined (reading 'call')").
57
+ uniqueName: name,
58
+ },
59
+ });
60
+ // Merge into the webapp (browser) compilation — in CSR the only one there is.
61
+ // NOTE: a remote built for SSR also publishes {ssr-stylesheets.json} for its
62
+ // hosts' SSR (see RemoteStylesheetsPlugin). Not in CSR — there is no server
63
+ // HTML to link it from.
64
+ const generateModuleFederationWebappWebpackConfigFragment = ({ name, exposes, remotes, shared, pluginOptions = {}, }) => {
65
+ const isSsrRemote = Boolean(exposes) && process.env.MS_CLI__WEBPACK_SERVE_MODE === 'ssr';
66
+ return {
67
+ plugins: [
68
+ new ModuleFederationPlugin(merge(Object.assign(Object.assign(Object.assign({ name }, (exposes && {
69
+ filename: REMOTE_ENTRY_FILENAME__WEBAPP,
70
+ exposes,
71
+ })), (remotes && {
72
+ remotes: generatePluginRemotes(remotes, 'webappEntry'),
73
+ })), { shared }), ASYNC_STARTUP__MODULE_FEDERATION_CONFIG_CHUNK, pluginOptions)),
74
+ ...(isSsrRemote ? [new RemoteStylesheetsPlugin()] : []),
75
+ ],
76
+ };
77
+ };
78
+ // Merge into an SSR HOST's server compilation (the one that renders pages and
79
+ // loads its remotes' server code). A remote that hosts nothing leaves its own
80
+ // server compilation as it is.
81
+ const generateModuleFederationSSRServerWebpackConfigFragment = ({ name, remotes, shared, pluginOptions = {}, }) => {
82
+ if (!fs.existsSync(SSR_SERVER_ENTRY_PATH)) {
83
+ throw new Error(`[bundler-webpack] an SSR host needs ${SSR_SERVER_ENTRY_PATH}, which imports ./ssr-server.config.mts dynamically ({webpackMode: "eager"}) — see generateModuleFederationSSRServerWebpackConfigFragment.`);
84
+ }
85
+ const pluginRemotes = generatePluginRemotes(remotes, 'ssrServerEntry');
86
+ const eagerShared = generateEagerShared(shared);
87
+ return {
88
+ // NOTE: 'async-node' (not plain 'node') is required by
89
+ // {@module-federation/node}'s runtime plugin.
90
+ target: 'async-node',
91
+ entry: { 'ssr-server.config': SSR_SERVER_ENTRY_PATH },
92
+ plugins: [
93
+ new NodeFederationPlugin(merge({
94
+ name,
95
+ remotes: pluginRemotes,
96
+ shared: eagerShared,
97
+ runtimePlugins: [NODE_FEDERATION_RUNTIME_PLUGIN_PATH],
98
+ }, pluginOptions), {}),
99
+ // NOTE: patches how async chunks the remotes split off are loaded in
100
+ // Node — fetched over HTTP instead of read from this app's disk.
101
+ new StreamingTargetPlugin({
102
+ name,
103
+ remotes: pluginRemotes,
104
+ shared: eagerShared,
105
+ }),
106
+ ],
107
+ };
108
+ };
109
+ // A REMOTE's extra compilation for SSR hosts: its exposed modules built as a
110
+ // CommonJS container ({ssr-remoteEntry.js}) a Node process can fetch and run.
111
+ // Returns a whole config (not a fragment): it reuses the SSR server base (its
112
+ // TS/SCSS loaders, CSS nulled out) WITHOUT its entry — the container must not
113
+ // build the app's own SSR server — and webpack-merge can't remove a key.
114
+ // Pass the same fragment as to {generateEnvBasedWebpackConfig}, extended with
115
+ // the server-facing {output.publicPath}.
116
+ const generateModuleFederationSSRContainerWebpackConfig = (extendedWebpackConfig, { name, exposes, remotes, shared, pluginOptions = {}, }) => {
117
+ if (!exposes) {
118
+ throw new Error(`[bundler-webpack] "${name}" exposes nothing — an SSR container is only built for a remote.`);
119
+ }
120
+ const { entry: _ssrServerEntry } = ssrServerEnvBasedConfig, ssrServerConfigWithoutEntry = __rest(ssrServerEnvBasedConfig, ["entry"]);
121
+ const pluginRemotes = generatePluginRemotes(remotes, 'ssrServerEntry');
122
+ return merge(ssrServerConfigWithoutEntry, extendedWebpackConfig, {
123
+ entry: {},
124
+ // NOTE: not the base's 'node' — a hardcoded 'node' target bakes in
125
+ // filesystem {require()} chunk loading before StreamingTargetPlugin can
126
+ // switch it to HTTP, which breaks loading an exposed module's async chunk
127
+ // from another process. Matches how {@module-federation/node}'s own
128
+ // server-side remote examples set up their compiler.
129
+ target: false,
130
+ output: {
131
+ // NOTE: next to the browser build, not in dist/private — the host's
132
+ // Node process fetches it over HTTP, so it has to be served.
133
+ path: path.join(runtimePathById.dist, 'public'),
134
+ library: { type: 'commonjs-module' },
135
+ },
136
+ experiments: { outputModule: false },
137
+ plugins: [
138
+ // NOTE: NodeFederationPlugin (not plain ModuleFederationPlugin) even
139
+ // for a remote that consumes nothing: the plain one leaves the exposed
140
+ // module's async chunk on filesystem loading, which fails for a
141
+ // consumer in another process.
142
+ new NodeFederationPlugin(merge({
143
+ name,
144
+ filename: REMOTE_ENTRY_FILENAME__SSR,
145
+ // NOTE: Node hosts fetch a remote entry and {require()}-wrap it,
146
+ // reading {module.exports} — the browser container's bare
147
+ // {var <name> = …} global evaporates once wrapped that way.
148
+ library: { type: 'commonjs-module' },
149
+ remotes: pluginRemotes,
150
+ exposes,
151
+ shared,
152
+ }, pluginOptions), {}),
153
+ new StreamingTargetPlugin({
154
+ name,
155
+ library: { type: 'commonjs-module' },
156
+ remotes: pluginRemotes,
157
+ }),
158
+ ],
159
+ });
160
+ };
161
+ export { generateModuleFederationCommonWebpackConfigFragment, generateModuleFederationSSRContainerWebpackConfig, generateModuleFederationSSRServerWebpackConfigFragment, generateModuleFederationWebappWebpackConfigFragment, };
@@ -0,0 +1,54 @@
1
+ import { SSR_STYLESHEETS_FILENAME } from './module-federation.chunk.mjs';
2
+ const PLUGIN_NAME = 'RemoteStylesheetsPlugin';
3
+ const MODULE_FEDERATION_MANIFEST_FILENAME = 'mf-manifest.json';
4
+ // Records, per exposed module, the stylesheets an SSR host must have in its
5
+ // page <head> before that module's markup is first painted — the file the
6
+ // host's SSR reads to avoid a flash of unstyled content (FOUC).
7
+ //
8
+ // Why a host needs it: the exposed module's CSS lives in the remote's async
9
+ // chunk and is only requested by Module Federation's browser runtime AFTER JS
10
+ // runs, while the host's SSR HTML already carries the markup. Nothing in that
11
+ // HTML points at the CSS, so the page paints unstyled until the chunk loads.
12
+ //
13
+ // NOTE: derived from Module Federation's own manifest (its `assets.css.sync`
14
+ // per expose) rather than re-walking the chunk graph, so "which CSS belongs to
15
+ // which expose" stays MF's answer. Not shipped as-is because the manifest is
16
+ // not a stable contract: the webapp and the SSR container are two
17
+ // compilations writing the SAME `mf-manifest.json` into the same folder (last
18
+ // one wins), and the SSR one has no CSS at all (CSS is nulled out on the
19
+ // server). Runs on the WEBAPP compilation only.
20
+ //
21
+ // Output ({ssr-stylesheets.json}), URLs exactly `publicPath + file` (so
22
+ // output.publicPath must be absolute, not 'auto'), which is what webpack's CSS
23
+ // loader compares against — a <link> with the same href is reused after
24
+ // hydration instead of being fetched twice:
25
+ // { "./routes": ["https://cdn.example/landing/prod/css/806.0116.min.css"] }
26
+ //
27
+ // NOTE: only `sync` CSS — what the module needs to render. CSS of its lazily
28
+ // loaded chunks (`async`) is requested when that chunk is.
29
+ class RemoteStylesheetsPlugin {
30
+ apply(compiler) {
31
+ const { Compilation, WebpackError, sources } = compiler.webpack;
32
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
33
+ compilation.hooks.processAssets.tap({
34
+ name: PLUGIN_NAME,
35
+ // NOTE: Module Federation emits its manifest at
36
+ // PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER (3000) — this has to run after.
37
+ stage: Compilation.PROCESS_ASSETS_STAGE_REPORT,
38
+ }, () => {
39
+ const manifestAsset = compilation.getAsset(MODULE_FEDERATION_MANIFEST_FILENAME);
40
+ if (!manifestAsset) {
41
+ compilation.errors.push(new WebpackError(`${PLUGIN_NAME}: ${MODULE_FEDERATION_MANIFEST_FILENAME} was not emitted — is Module Federation's manifest disabled?`));
42
+ return;
43
+ }
44
+ const { metaData, exposes } = JSON.parse(manifestAsset.source.source().toString());
45
+ const stylesheetsByExpose = Object.fromEntries(exposes.map(({ path, assets }) => [
46
+ path,
47
+ assets.css.sync.map((file) => `${metaData.publicPath}${file}`),
48
+ ]));
49
+ compilation.emitAsset(SSR_STYLESHEETS_FILENAME, new sources.RawSource(`${JSON.stringify(stylesheetsByExpose, null, 2)}\n`));
50
+ });
51
+ });
52
+ }
53
+ }
54
+ export { RemoteStylesheetsPlugin };
@@ -1 +1,2 @@
1
1
  export { generateEnvBasedWebpackConfig } from './generate-webpack-config.mjs';
2
+ export { merge as mergeWebpackConfig } from 'webpack-merge';
@@ -0,0 +1,3 @@
1
+ export { DOCKER_SAFE__MODULE_FEDERATION_CONFIG_CHUNK, SSR_STYLESHEETS_FILENAME, } from './module-federation.chunk.mjs';
2
+ export { generateModuleFederationCommonWebpackConfigFragment, generateModuleFederationSSRContainerWebpackConfig, generateModuleFederationSSRServerWebpackConfigFragment, generateModuleFederationWebappWebpackConfigFragment, } from './module-federation.fragment.mjs';
3
+ export type { ModuleFederationConfig, ModuleFederationRemote, ModuleFederationSharedConfig, } from './module-federation.types.mjs';
@@ -0,0 +1,3 @@
1
+ declare const NodeFederationPlugin: typeof import("@module-federation/node").NodeFederationPlugin, StreamingTargetPlugin: typeof import("@module-federation/node").StreamingTargetPlugin;
2
+ declare const NODE_FEDERATION_RUNTIME_PLUGIN_PATH: string;
3
+ export { NODE_FEDERATION_RUNTIME_PLUGIN_PATH, NodeFederationPlugin, StreamingTargetPlugin, };
@@ -0,0 +1,9 @@
1
+ import type { Configuration } from 'webpack';
2
+ import type { ModuleFederationPluginOptions } from './module-federation.types.mjs';
3
+ declare const REMOTE_ENTRY_FILENAME__WEBAPP = "remoteEntry.js";
4
+ declare const REMOTE_ENTRY_FILENAME__SSR = "ssr-remoteEntry.js";
5
+ declare const SSR_STYLESHEETS_FILENAME = "ssr-stylesheets.json";
6
+ declare const ASYNC_STARTUP__MODULE_FEDERATION_CONFIG_CHUNK: Partial<ModuleFederationPluginOptions>;
7
+ declare const WATCH_OPTIONS__MODULE_FEDERATION__WEBPACK_CONFIG_CHUNK: Configuration;
8
+ declare const DOCKER_SAFE__MODULE_FEDERATION_CONFIG_CHUNK: Partial<ModuleFederationPluginOptions>;
9
+ export { ASYNC_STARTUP__MODULE_FEDERATION_CONFIG_CHUNK, DOCKER_SAFE__MODULE_FEDERATION_CONFIG_CHUNK, REMOTE_ENTRY_FILENAME__SSR, REMOTE_ENTRY_FILENAME__WEBAPP, SSR_STYLESHEETS_FILENAME, WATCH_OPTIONS__MODULE_FEDERATION__WEBPACK_CONFIG_CHUNK, };
@@ -0,0 +1,7 @@
1
+ import type { Configuration } from 'webpack';
2
+ import type { ModuleFederationConfig } from './module-federation.types.mjs';
3
+ declare const generateModuleFederationCommonWebpackConfigFragment: ({ name, }: Pick<ModuleFederationConfig, "name">) => Configuration;
4
+ declare const generateModuleFederationWebappWebpackConfigFragment: ({ name, exposes, remotes, shared, pluginOptions, }: ModuleFederationConfig) => Configuration;
5
+ declare const generateModuleFederationSSRServerWebpackConfigFragment: ({ name, remotes, shared, pluginOptions, }: ModuleFederationConfig) => Configuration;
6
+ declare const generateModuleFederationSSRContainerWebpackConfig: (extendedWebpackConfig: Configuration, { name, exposes, remotes, shared, pluginOptions, }: ModuleFederationConfig) => Configuration;
7
+ export { generateModuleFederationCommonWebpackConfigFragment, generateModuleFederationSSRContainerWebpackConfig, generateModuleFederationSSRServerWebpackConfigFragment, generateModuleFederationWebappWebpackConfigFragment, };
@@ -0,0 +1,16 @@
1
+ import type { ModuleFederationPlugin } from '@module-federation/enhanced/webpack';
2
+ type ModuleFederationPluginOptions = ConstructorParameters<typeof ModuleFederationPlugin>[0];
3
+ type ModuleFederationSharedObject = Exclude<NonNullable<ModuleFederationPluginOptions['shared']>, unknown[]>;
4
+ type ModuleFederationSharedConfig = Exclude<ModuleFederationSharedObject[string], string>;
5
+ type ModuleFederationRemote = {
6
+ webappEntry: string;
7
+ ssrServerEntry?: string;
8
+ };
9
+ type ModuleFederationConfig = {
10
+ name: string;
11
+ exposes?: Record<string, string>;
12
+ remotes?: Record<string, ModuleFederationRemote>;
13
+ shared?: Record<string, ModuleFederationSharedConfig>;
14
+ pluginOptions?: Partial<ModuleFederationPluginOptions>;
15
+ };
16
+ export type { ModuleFederationConfig, ModuleFederationPluginOptions, ModuleFederationRemote, ModuleFederationSharedConfig, };
@@ -0,0 +1,5 @@
1
+ import type { Compiler } from 'webpack';
2
+ declare class RemoteStylesheetsPlugin {
3
+ apply(compiler: Compiler): void;
4
+ }
5
+ export { RemoteStylesheetsPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mainset/bundler-webpack",
3
- "version": "0.3.7",
3
+ "version": "0.4.0",
4
4
  "description": "Bundler for web apps",
5
5
  "homepage": "https://github.com/mainset/dev-stack-fe/tree/main/packages/bundler-webpack",
6
6
  "bugs": {
@@ -23,6 +23,10 @@
23
23
  "types": "./dist/types/index.d.mts",
24
24
  "import": "./dist/esm/index.mjs"
25
25
  },
26
+ "./module-federation": {
27
+ "types": "./dist/types/module-federation/index.d.mts",
28
+ "import": "./dist/esm/module-federation/index.mjs"
29
+ },
26
30
  "./global-types": "./src/@types/bundler.d.ts"
27
31
  },
28
32
  "dependencies": {
@@ -31,6 +35,8 @@
31
35
  "@babel/preset-env": "^8.0.2",
32
36
  "@babel/preset-react": "^8.0.1",
33
37
  "@babel/preset-typescript": "^8.0.1",
38
+ "@module-federation/enhanced": "^2.9.2",
39
+ "@module-federation/node": "^2.7.52",
34
40
  "babel-loader": "^10.1.1",
35
41
  "copy-webpack-plugin": "^14.0.0",
36
42
  "css-loader": "^7.1.4",
@@ -49,8 +55,8 @@
49
55
  "webpack-merge": "^6.0.1"
50
56
  },
51
57
  "devDependencies": {
52
- "@mainset/cli": "^0.7.2",
53
- "@mainset/dev-stack-fe": "^0.2.3"
58
+ "@mainset/dev-stack-fe": "^0.2.3",
59
+ "@mainset/cli": "^0.7.4"
54
60
  },
55
61
  "peerDependencies": {
56
62
  "@mainset/cli": ">=0.5.0 <1.0.0",