https://github.com/gravity-ui/app-builder
https://github.com/gravity-ui/app-builder
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/gravity-ui/app-builder
- Owner: gravity-ui
- License: mit
- Created: 2022-09-09T07:03:04.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2026-04-03T09:45:22.000Z (3 months ago)
- Last Synced: 2026-04-03T15:23:32.892Z (3 months ago)
- Language: TypeScript
- Homepage:
- Size: 2.83 MB
- Stars: 29
- Watchers: 4
- Forks: 8
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Codeowners: CODEOWNERS
- Authors: AUTHORS
Awesome Lists containing this project
README
# @gravity-ui/app-builder · [](https://www.npmjs.com/package/@gravity-ui/app-builder) [](https://github.com/gravity-ui/app-builder/actions/workflows/ci.yml?query=branch:main)
Develop and build your client-server projects, powered by typescript and webpack.
## Install
```shell
npm install --save-dev @gravity-ui/app-builder
```
## Usage
`@gravity-ui/app-builder` provides CLI (`npx app-builder`). You can view available commands with the `--help` flag.
### Develop your project
```sh
npx app-builder dev # to view supported options add the --help flag.
```
### Build your project
```sh
npx app-builder build # to view supported options add the --help flag.
```
### Configuration
You can use any of these files:
- app-builder.config.ts
- app-builder.config.js
- app-builder.config.json
- app-builder property in your package.json
You can also specify a custom filename using the `--config` flag
#### TypeScript/JavaScript
```ts
import {defineConfig} from '@gravity-ui/app-builder';
export default defineConfig({
client: {
// client settings
},
server: {
// server settings
},
});
```
#### Conditional config
If the config needs to be conditionally determined, it can export a function instead:
```ts
import {defineConfig} from '@gravity-ui/app-builder';
export default defineConfig(
async function (
/** @type dev | build */
command,
/**
* values specified with --env flag
*
* @type {[k in string]: string}
*
* @example
* With follow command:
* app-build dev --env=path.to.member1=value1 --env=path.to.member2=value2
* you get:
* env = {path: {to: {member1: 'value1', member2: 'value2'}}}
*/
env,
) {
return {
verbose: command === 'dev',
client: {
// client settings
},
server: {
// server settings
},
};
},
);
export default config;
```
#### package.json
```json
{
"app-builder": {
"client": {
// client settings
},
"server": {
// server settings
}
},
"scripts": {
"dev": "app-builder dev",
"build": "app-builder build"
}
}
```
### Common
- `target` (`client | server`) — select compilation unit.
- `verbose` (`boolean`) - turn on verbose output.
#### Environment Variables
`app-builder` automatically injects environment variables during the build process that are available in your application code:
- `process.env.PUBLIC_PATH` — automatically set to the resolved public path value (including CDN URLs if configured). This allows your application code to dynamically access the correct resource URLs at runtime.
```ts
// In your application code, you can access:
const publicPath = process.env.PUBLIC_PATH; // e.g., "https://cdn.example.com/build/" or "/build/"
// Useful for dynamically loading assets or configuring Module Federation
const assetUrl = `${process.env.PUBLIC_PATH}images/logo.png`;
```
**Note**: On the server side, `process.env.PUBLIC_PATH` is only available when using SWC compiler (`compiler: 'swc'`). With TypeScript compiler, this variable is not injected.
- `process.env.NODE_ENV` — current environment (`'development'` | `'production'`)
- `process.env.IS_SSR` — boolean flag indicating if code is running in SSR context
### Server
`app-builder` compiles server with typescript.
Default folder for server code is `src/server`. There is must be file `tsconfig.json`
```json
{
"compilerOptions": {
"outDir": "../../dist/server"
}
}
```
and `index.ts` - server entrypoint.
`outDir` - must be configured to place compiled files to `{rootDir}/dist/server`.
The server is started with the command `node {rootDir}/dist/server/index.js`.
#### Options
All server settings are used only in dev mode:
- `port` (`number | true`) — specify port that server listens. The port will be used to
pass through requests from the client to the server. If set to `true`, the port will be selected automatically.
The server is started with the command `APP_PORT=${port} node dist/${outputPath}/index.js --port ${port}`.
- `watch` (`string[]`) — by default `app-builder` monitors only `src/server` directory.
If you need to watch other directories, specify them here.
- `watchThrottle` (`number`) — use to add an extra throttle, or delay restarting.
- `inspect/inspectBrk` (`number | true`) — listen for a debugging client on specified port.
If specified `true`, try to listen on `9229`.
- `compiler` (`'typescript' | 'swc'`) — choose TypeScript compiler for server code compilation.
Default is `'typescript'`. Set to `'swc'` for faster compilation with SWC.
- `outputPath` (`string`) — custom output path for compiled server code relative to `dist` directory.
Default: `server`. Use this when your `server` entrypoint changed from `dist/server` to a different location (e.g., `package/src/server` for path `dist/package/src/server` in monorepo setups).
### Client
`app-builder` bundles client with [webpack](https://webpack.js.org). Client code must be in `src/ui` folder.
`src/ui/entries` - each file in this folder is used as entrypoint. `dist/public/build` is output directory for bundles.
#### Options
All paths must be specified relative `rootDir` of the project.
- `modules` (`string[]`) — Tell webpack what directories should be searched when resolving modules. `modules` automatically
populates with `baseUrl` from `src/ui/tsconfig.json`.
- `alias` (`Record`) — Create aliases to import or require certain modules more easily, [more](https://webpack.js.org/configuration/resolve/#resolvealias)
With this `{rootDir}/src/ui/tsconfig.json`:
```json
{
"compilerOptions": {
"baseDir": ".",
"paths": {
"~units": ["units/*"]
}
}
}
```
`modules` will contain `["{rootDir}/src"]` and aliases - `{"~units": ["{rootDir}/src/units"]}`;
- `includes` (`string[]`) — additional compilation paths. Example: `includes: ['node_modules/my-lib', 'src/shared']`
- `images` (`string[]`) — Additional paths for images. Example: `images: ['node_modules/my-lib/img']`
- `icons` (`string[]`) — Additional paths for svg icons. By default, all svgs with paths including `icons/` will be processed.
Example: `icons: [node_modules/@fortawesome/fontawesome-pro/svgs]`
- `publicPathPrefix` (`string`) — publicPath prefix, will be added to `/build/`
- `publicPath` (`string`) — publicPath for bundler, this option has higher priority than publicPathPrefix
- `outputPath` (`string`) — Build directory for output, default: `dist/public/build` and `dist/ssr` - for SSR
- `assetsManifestFile` (`string`) — File name for assets manifest, default: `assets-manifest.json`
- `symlinks` (`boolean`) — Follow symbolic links while looking for a file. [more](https://webpack.js.org/configuration/resolve/#resolvesymlinks)
- `externals` — specify dependencies that shouldn't be resolved by webpack, but should become dependencies of the resulting bundle. [more](https://webpack.js.org/configuration/externals/)
- `node` — include polyfills or mocks for various node stuff. [more](https://webpack.js.org/configuration/node/)
- `fallback` — Redirect module requests when normal resolving fails. [more](https://webpack.js.org/configuration/resolve/#resolvefallback)
- `polyfill` — allow enable Node.js `process` object polyfill.
- `hiddenSourceMap` (`boolean=true`) - if `false` - source maps will be generated for prod builds
- `disableSourceMapGeneration` (`boolean`) — disable sourcemap generation;
- `definitions` — add additional options to DefinePlugin. [more](https://webpack.js.org/plugins/define-plugin/#usage)
- `newJsxTransform` (`boolean=true`) — use new JSX Transform.
- `svgr` (`SvgrConfig`) — svgr plugin options. [more](https://react-svgr.com/docs/options/)
- `entry` (`string | string[] | Record`) — entry for bundler, overrides entry which is generated from entries directory
- `entryFilter` (`string[]`) — filter used entrypoints.
- `excludeFromClean` (`string[]`) — do not clean provided paths before build.
- `forkTsCheker` (`false | ForkTsCheckerWebpackPluginOptions`) - config for ForkTsCheckerWebpackPlugin [more](https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#options). If `false`, ForkTsCheckerWebpackPlugin will be disabled.
- `cache` (`boolean | FileCacheOptions | MemoryCacheOptions`) — Cache the generated webpack modules and chunks to improve build speed. [more](https://webpack.js.org/configuration/cache/)
- `bundler` (`'webpack' | 'rspack'`) - Option to choose a bundler.
- `javaScriptLoader` (`'babel' | 'swc'`) - Option to choose a JavaScript loader.
- `babel` (`(config: babel.TransformOptions, options: {configType: 'development' | 'production'; isSsr: boolean}) => babel.TransformOptions | Promise`) - Allow override the default babel transform options.
- `babelCacheDirectory` (`boolean | string`) — Set directory for babel-loader cache (`default: node_modules/.cache/babel-loader``)
- `swc` (`(config: SwcConfig, options: {configType: 'development' | 'production'; isSsr: boolean}) => SwcConfig | Promise`) - Allow override the default swc configuration.
- `webpack` (`(config: webpack.Configuration, options: {configType: 'development' | 'production'; isSsr: boolean}) => webpack.Configuration | Promise`) - Allow override the default webpack configuration.
- `rspack` (`(config: rspack.Configuration, options: {configType: 'development' | 'production'; isSsr: boolean}) => rspack.Configuration | Promise`) - Allow override the default rspack configuration.
- `ssr` - build SSR bundle. The SSR entries should be inside `src/ui/ssr` directory and match the client entries.
- `noExternal` (`string | RegExp | (string | RegExp)[] | true`) - prevent listed dependencies from being externalized for SSR. By default, all dependencies are externalized.
- `moduleType`: (`'commonjs' | 'esm'`) - library type for the SSR bundle, by default `commonjs`.
##### Dev build
- `devServer` (`Object`) — webpack dev server options.
- `ipc` (`string`) — the Unix socket to listen to. If `ipc` and `port` are not defined, then the socket `{rootDir}/dist/run/client.sock` is used.
- `port` (`number | true`) — specify a port number to listen for requests on. If `true`, the free port will be selected automatically.
- `webSocketPath` (`string`) — tells clients connected to devServer to use the provided path to connect. Default is `${publicPathPrefix}/build/sockjs-node`.
- `webSocketClientPort` (`number`) - tells clients to connect to devServer using this port from a browser. Default is `${devServer.port}`
- `type` (`'https'`) — allow to serve over HTTPS.
- `options` (`import('https').ServerOptions`) — allow to provide your own certificate.
- `watchOptions` — a set of options used to customize watch mode, [more](https://webpack.js.org/configuration/watch/#watchoptions)
- `watchPackages` (`boolean`) - watch all changes in `node_modules`.
- `reactRefresh` (`false | (options: ReactRefreshPluginOptions) => ReactRefreshPluginOptions`) — disable or configure `react-refresh` in dev mode, [more](https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/API.md#options)
- `detectCircularDependencies` (`true | CircularDependenciesOptions`) - detect modules with circular dependencies, [more](https://github.com/aackerman/circular-dependency-plugin)
- `lazyCompilation` (`true | LazyCompilationConfig`) — enable experimental [lazy compilation](https://webpack.js.org/configuration/experiments/#experimentslazycompilation) feature
- `true` — enable feature
- `LazyCompilationConfig`
- `port` (`number`) — port where to listen to from the server
- `entries` (`boolean=true`) — if `false` - disables lazy compilation for `src/ui/entries` folder content
##### Production build
- `analyzeBundle` (`true | statoscope`) — tools to analyze bundle.
- `true` — enable [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) plugin. Report generated to `dist/public/build/stats.html`
- `statoscope` — enable [statoscope](https://github.com/statoscope/statoscope) plugin. Reports generated to `dist/public/build/stats.json` and `dist/public/build/report.json`
- `reactProfiling` (`boolean`) — use react profiler API in production, this option also disable minimization. The API is required by React developers tools for profile.
- `statoscopeConfig` (`Options`) — `@statoscope/webpack-plugin` [configuration options](https://github.com/statoscope/statoscope/tree/master/packages/webpack-plugin#usage). Might be used to override the defaults. Requires `analyzeBundle: statoscope`.
- `cdn` (`CdnUploadConfig | CdnUploadConfig[]`) - upload bundled client files to CDN.
- `bucket` (`string`) — bucket name
- `prefix` (`string`) — path to files inside the bucket
- `region` (`string`) — AWS region or any string
- `endpoint` (`string`) - cdn host to upload files
- `publicPath` (`string`) - public path to access files from the browser
- `compress` (`boolean`) - upload also gzip and brotli compressed versions of files
- `additionalPattern` (`string[]`) — patterns for uploading additional files. By default, only files generated by webpack are loaded.
- `sentryConfig` (`Options`) — `@sentry/webpack-plugin` [configuration options](https://www.npmjs.com/package/@sentry/webpack-plugin/v/2.7.1).
##### Optimization
- `vendors` (`string[] | (defaultVendors: string[]) => string[]`) — additional libraries or a function returning libraries for a vendor chunk;
- `momentTz` — [settings](https://www.npmjs.com/package/moment-timezone-data-webpack-plugin) for moment-timezone (by default data is truncated);
- `contextReplacement` (`object`)
- `highlight.js` (`string[]`) — list of language names to include, e.g. `['javascript', 'python', 'bash']`;
- `locale`: (`string[]=['ru']`) — list of `moment.js` or `day.js` locales to include, e.g. `['de', 'es']`. Locale `En` is always present.
- `safari10` (`boolean`) — Enables `safari10` terser's option. [Terser options](https://github.com/terser/terser#minify-options)
- `transformCssWithLightningCss` (`boolean`) — use [Lighting CSS](https://lightningcss.dev) to transform and minimize css instead of PostCSS and cssnano
- `lightningCssMinimizerOptions` (`(options: LightningCssMinimizerRspackPluginOptions) => LightningCssMinimizerRspackPluginOptions`) - modify or return a custom [LightningCssMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/lightning-css-minimizer-rspack-plugin)
- `terser` (`(options: TerserOptions) => TerserOptions`) - modify or return a custom [Terser options](https://github.com/terser/terser#minify-options).
##### Monaco editor support
- `monaco` (`object`) — use [monaco-editor-webpack-plugin](https://github.com/microsoft/monaco-editor/tree/main/webpack-plugin#monaco-editor-webpack-loader-plugin)
- `fileName` (`string`) — custom filename template for worker scripts.
- `languages` (`string[]`) - include only a subset of the languages supported. If you don't need support for all languages, set needed languages explicitly, since it may significantly affect build time.
- `features` (`string[]`) - include only a subset of the editor features.
- `customLanguages` (`IFeatureDefinition[]`) - include custom languages (outside of the ones shipped with the `monaco-editor`).
##### WebWorker support
Web workers allow you to run JavaScript code in a separate thread from the main UI thread.
This can improve the performance and responsiveness of your web application by offloading
intensive tasks to the background.
To create a web worker, you need to write a script file that defines the logic of the worker. For example,
this file (my.worker.ts) implements a simple function that adds two numbers and sends the result back to the main thread:
```ts
// my.worker.ts
self.onmessage = async (ev) => {
const {a = 0, b = 0} = ev.data || {};
const result = a + b;
self.postMessage({
result,
});
};
```
`app-builder` provides built-in support for web workers for files with the `.worker.[jt]s` suffix. You can choose
between two variants of getting web workers by setting the `webWorkerHandle` option:
- `loader` (default) - use the `worker-loader` to import web workers.
Content of worker file will be included in main bundle as blob. This variant does not
support dynamic imports inside worker. For example:
```ts
// main.ts
import MyWorker from './my.worker.ts';
const worker = new MyWorker();
```
In this variant, you need to add some type declarations for the worker files::
```ts
// worker.d.ts
declare module '*.worker.ts' {
class WebpackWorker extends Worker {}
export default WebpackWorker;
}
```
- `cdn-compat` - use the webpack 5 web workers [syntax](https://webpack.js.org/guides/web-workers/#syntax)
to import web workers. This variant allows to use dynamic imports inside worker and load worker bundle from CDN. For example:
```ts
import {Worker} from '@gravity-ui/app-builder/worker';
const MyWorker = new Worker(new URL('./my.worker', import.meta.url));
```
- `none` - disable worker-specific handling.
To use the web worker in your main script, you need to communicate with it using the postMessage and onmessage methods. For example:
```ts
// main.ts
const worker = '...'; // Worker creation, first or second variant
worker.onmessage = ({data: {result}}) => {
console.log(result);
};
worker.postMessage({a: 1, b: 2});
```
##### Module Federation
Module Federation is a Webpack 5 feature that enables micro-frontend architecture, where JavaScript applications can dynamically load code from each other at runtime.
`app-builder` uses `@module-federation/enhanced` for advanced Module Federation support.
- `moduleFederation` (`object`) — Module Federation configuration
- `name` (`string`) — unique name of the application in the Module Federation ecosystem. Required parameter.
- `version` (`string`) — application version. When specified, the entry file will be named `entry-{version}.js` instead of `entry.js`.
- `disableManifest` (`boolean`) — disable manifest file generation. When `true`, uses regular `.js` files for remote entry instead of manifest files. Default is `false`.
- `remotes` (`string[]`) — list of remote application names that this application can load. This is a simplified alternative to `originalRemotes` that automatically generates remote URLs based on your public path configuration.
**How it works:**
- In **development mode**: Remote URLs are automatically generated using the pattern `{commonPublicPath}{remoteName}/entry.js` (or manifest files if enabled)
- In **production mode**: You need to ensure remote applications are deployed and accessible at the expected URLs
- Remote entry files are loaded at runtime to provide federated modules from other micro-frontends
**File naming patterns** (depends on configuration):
- With `disableManifest: false` (default): `mf-manifest.json` or `mf-manifest-[version].json` (with versioning)
- With `disableManifest: true`: `entry.js` or `entry-[version].js` (with versioning)
**Example:**
```ts
// Simple configuration - URLs auto-generated in development
remotes: ['header', 'navigation', 'footer'];
// Results in loading from (in development):
// - https://localhost:3000/header/mf-manifest.json
// - https://localhost:3000/navigation/mf-manifest.json
// - https://localhost:3000/footer/mf-manifest.json
```
**Development vs Production:**
- **Development**: App-builder automatically starts all remote applications and generates their URLs
- **Production**: Remote applications must be independently deployed and accessible at the generated URLs
**Integration with other options:**
- Works with `enabledRemotes` to selectively enable remotes in development
- Affected by `remotesRuntimeVersioning` for versioned file names
- File format controlled by `disableManifest` option
For more complex scenarios requiring custom URLs or cross-environment configurations, use `originalRemotes` instead.
- `enabledRemotes` (`string[]`) — list of enabled remotes for module federation. **Development mode only**. If not specified, all remotes from the `remotes` array will be enabled by default.
**Purpose:**
- Allows selective enabling/disabling of specific remotes during development
- Useful for debugging, testing individual micro-frontends, or working with partial system setups
- Helps reduce development startup time by loading only needed remotes
- Can be overridden via CLI flag: `--mf-remotes header footer`
**Loading behavior:**
**When CDN is disabled:**
- **Enabled remotes**: Loaded from local development server with version-specific paths
- **Disabled remotes**: Loaded from `cdnPublicPath` (if configured), otherwise fallback to local paths
**When CDN is enabled:**
- **All remotes**: Use common public path, `enabledRemotes` selection has no effect on URLs
**In production builds:**
- This option is completely ignored, all configured remotes are included in the bundle
**Example:**
```ts
// Load all available remotes (header, navigation, footer)
remotes: ['header', 'navigation', 'footer'];
// Enable only specific remotes in development
enabledRemotes: ['header', 'footer']; // navigation will be skipped
```
**CLI Override:**
```bash
# Override enabledRemotes from command line
npx app-builder dev --mf-remotes header navigation
```
**Note:** This option has no effect in production builds - all configured remotes will be included in the production bundle configuration.
- `originalRemotes` (`RemotesObject`) — full configuration of remote applications in Module Federation Plugin format. Use this when you need explicit control over remote URLs or for cross-environment deployments.
**When to use:**
- Custom remote URLs (different domains, ports, paths)
- Cross-environment loading (staging, production CDN URLs)
- Complex deployment scenarios
- When `remotes` auto-generation doesn't meet your needs
**Format:**
```ts
originalRemotes: {
remoteName: 'remoteName@remoteUrl',
}
```
**Examples:**
```ts
originalRemotes: {
header: 'header@https://cdn.example.com/header/entry.js',
footer: 'footer@https://cdn.example.com/footer/entry.js',
}
```
**Note:** When `originalRemotes` is specified, the `remotes` option is ignored. Use either `remotes` OR `originalRemotes`, not both.
- `remotesRuntimeVersioning` (`boolean`) — enables runtime versioning for remote applications. When enabled, remote entry files include version information in their filenames, allowing for cache busting and version-specific loading.
**How it affects file names:**
- With `disableManifest: false`: `mf-manifest-[version].json` instead of `mf-manifest.json`
- With `disableManifest: true`: `entry-[version].js` instead of `entry.js`
- Version is taken from the remote application's `version` configuration
**Benefits:**
- **Cache busting**: Different versions get different URLs, preventing browser caching issues
- **Rollback capability**: Can load specific versions of remotes
- **Deployment safety**: Gradual rollouts with version-specific remote loading
**Important considerations:**
- **Without CDN**: Version is inlined immediately during build time, as single build cannot contain multiple application versions
- **With CDN**: True runtime versioning is possible, versions are resolved dynamically at runtime
- **Recommendation**: Use `remotesRuntimeVersioning` together with CDN configuration for full dynamic versioning capabilities
**Example with versioning enabled:**
```ts
// Host application
{
moduleFederation: {
name: 'shell',
remotes: ['header', 'navigation'],
remotesRuntimeVersioning: true, // Enable versioning
}
}
// Remote application (header)
{
moduleFederation: {
name: 'header',
version: '2.1.0', // This version appears in filename
exposes: { './Header': './src/Header' }
}
}
// Results in loading: header/mf-manifest-2.1.0.json
```
**Runtime behavior:**
- The version is resolved at runtime from the remote's manifest or entry file
- Enables loading different versions of the same remote in different environments
- Works with both `remotes` and `originalRemotes` configurations
- `isolateAssets` (`boolean`) - put all assets to a folder with the name of Module Federation app name
- `isolateStyles` (`object`) — CSS style isolation settings to prevent conflicts between micro-frontends.
- `getPrefix` (`(entryName: string) => string`) — function to generate CSS class prefix.
- `prefixSelector` (`(prefix: string, selector: string, prefixedSelector: string, filePath: string) => string`) — function to add prefix to CSS selectors.
- Also supports all standard options from [@module-federation/enhanced](https://module-federation.io/), except `name` and `remotes`, such as:
- `filename` — entry file name (default `entry.js`)
- `exposes` — modules that this application exports
- `shared` — shared dependencies between applications
- `runtimePlugins` — plugins for Module Federation runtime
**Host Application Configuration Example:**
Host applications consume remote modules from other micro-frontends:
```ts
export default defineConfig({
client: {
moduleFederation: {
name: 'shell',
// Simple remotes configuration
remotes: ['header', 'footer', 'sidebar'],
shared: {
react: {singleton: true, requiredVersion: '^18.0.0'},
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
lodash: {singleton: true},
},
},
},
});
```
**Advanced Host Configuration:**
```ts
export default defineConfig({
client: {
moduleFederation: {
name: 'main-shell',
version: '2.1.0',
// Detailed remotes configuration
originalRemotes: {
header: 'header@https://cdn.example.com/header/entry.js',
footer: 'footer@https://cdn.example.com/footer/entry.js',
userProfile: 'userProfile@https://cdn.example.com/user-profile/entry.js',
},
remotesRuntimeVersioning: true,
isolateStyles: {
getPrefix: (entryName) => `.app-${entryName}`,
prefixSelector: (prefix, selector, prefixedSelector, filePath) => {
if (
[prefix, ':root', 'html', 'body', '.g-root', '.remote-app'].some((item) =>
selector.startsWith(item),
) ||
filePath.includes('@gravity-ui/chartkit')
) {
return selector;
}
return prefixedSelector;
},
},
shared: {
react: {singleton: true, requiredVersion: '^18.0.0'},
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
lodash: {singleton: true},
},
},
},
});
```
**Remote Application Configuration Example:**
Remote applications expose their modules for consumption by host applications:
```ts
export default defineConfig({
client: {
moduleFederation: {
name: 'header',
// Expose modules for other applications
exposes: {
'./Header': './src/components/Header',
'./Navigation': './src/components/Navigation',
'./UserMenu': './src/components/UserMenu',
},
shared: {
react: {singleton: true, requiredVersion: '^18.0.0'},
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
lodash: {singleton: true},
},
},
},
});
```
**Bidirectional Configuration Example:**
Applications can be both host and remote simultaneously:
```ts
export default defineConfig({
client: {
moduleFederation: {
name: 'dashboard',
version: '1.5.0',
// Consume remote modules
remotes: ['charts', 'notifications'],
// Expose own modules
exposes: {
'./DashboardLayout': './src/layouts/DashboardLayout',
'./DataTable': './src/components/DataTable',
},
shared: {
react: {singleton: true, requiredVersion: '^18.0.0'},
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
lodash: {singleton: true},
},
},
},
});
```
**Advanced Remotes Configuration Examples:**
```ts
export default defineConfig({
client: {
moduleFederation: {
name: 'advanced-shell',
version: '3.0.0',
// Example 1: Simple remotes for development
remotes: ['header', 'sidebar', 'footer', 'analytics'],
// Example 2: Enable only specific remotes in development
enabledRemotes: ['header', 'sidebar'], // Only these will load in dev mode
// Example 3: Runtime versioning with manifests (production-ready)
remotesRuntimeVersioning: true, // Enables version-specific loading
disableManifest: false, // Use mf-manifest-[version].json files
shared: {
react: {singleton: true, requiredVersion: '^18.0.0'},
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
},
},
},
});
// Alternative: Explicit URLs for production
export default defineConfig({
client: {
moduleFederation: {
name: 'production-shell',
// Use originalRemotes for explicit control
originalRemotes: {
// Static CDN URLs
header: 'header@https://cdn.company.com/header/mf-manifest-2.1.0.json',
sidebar: 'sidebar@https://cdn.company.com/sidebar/entry-1.5.0.js',
// Dynamic remote loading
analytics: `promise new Promise((resolve) => {
const remoteUrl = process.env.NODE_ENV === 'production'
? 'https://analytics.cdn.com/entry.js'
: 'http://localhost:3003/entry.js';
resolve(\`analytics@\${remoteUrl}\`);
})`,
},
shared: {
react: {singleton: true, requiredVersion: '^18.0.0'},
'react-dom': {singleton: true, requiredVersion: '^18.0.0'},
},
},
},
});
```
**Development Workflow with Remotes:**
```bash
# Start host application with all remotes
npx app-builder dev
# Start host with only specific remotes (faster development)
npx app-builder dev --mf-remotes header sidebar
# The above is equivalent to setting enabledRemotes in config:
# enabledRemotes: ['header', 'sidebar']
```