diff --git a/.claude/agents/module-federation-example-enhancer.md b/.claude/agents/module-federation-example-enhancer.md index 7f74356772f..c6d5df1f886 100644 --- a/.claude/agents/module-federation-example-enhancer.md +++ b/.claude/agents/module-federation-example-enhancer.md @@ -11,6 +11,7 @@ Your primary resource is the Module Federation documentation at https://module-f 1. **Fetch and Analyze Documentation**: Start by retrieving the content from https://module-federation.io/llms.txt to understand the current documentation structure. Identify relevant markdown files and sublinks that contain information about the latest Module Federation features, APIs, and patterns. 2. **Deep Dive into Module Federation Specifics**: Based on the example you're improving, explore specific documentation sections about: + - Module Federation configuration options and APIs - Latest @module-federation/enhanced features - Federation-specific patterns and best practices @@ -19,12 +20,14 @@ Your primary resource is the Module Federation documentation at https://module-f - Shared dependency optimization 3. **Analyze the Existing Module Federation Implementation**: Carefully examine the provided code to: + - Identify outdated Module Federation patterns or deprecated APIs - Spot opportunities for Module Federation-specific optimizations - Recognize missing Module Federation features that could enhance functionality - Assess the federation architecture for improvement potential 4. **Apply Module Federation Enhancements**: Transform the example by: + - Upgrading to @module-federation/enhanced if using legacy webpack plugin - Implementing modern Module Federation configuration patterns - Adding federation-specific runtime plugins where beneficial @@ -33,6 +36,7 @@ Your primary resource is the Module Federation documentation at https://module-f - Updating to current Module Federation APIs and patterns 5. **Focus Areas (DO enhance):** + - Module Federation configuration files (webpack.config.js, rspack.config.js) - Federation-specific source code patterns - Remote loading and consumption patterns @@ -42,6 +46,7 @@ Your primary resource is the Module Federation documentation at https://module-f - Module Federation hooks and utilities 6. **Avoid Areas (DO NOT enhance unless directly related to Module Federation):** + - General webpack performance optimizations unrelated to federation - Security hardening not specific to Module Federation - Docker configurations and deployment concerns diff --git a/.claude/agents/readme-updater.md b/.claude/agents/readme-updater.md index 52e115bf916..a6fcc96b54d 100644 --- a/.claude/agents/readme-updater.md +++ b/.claude/agents/readme-updater.md @@ -9,24 +9,28 @@ You are an expert technical documentation specialist with deep expertise in anal When analyzing a project, you will: 1. **Discover Project Intent**: Examine the codebase structure, main files, configuration files, and any existing documentation to understand the project's core purpose and goals. Look for: + - Main entry points and primary functionality - Package dependencies that hint at the project's nature - Comments and docstrings that explain intent - File and folder naming patterns 2. **Understand How It Works**: Analyze the technical implementation by: + - Identifying the main components and their interactions - Tracing the flow of data and control through the application - Recognizing design patterns and architectural decisions - Understanding external dependencies and integrations 3. **Identify Use Cases**: Determine practical applications by: + - Analyzing functionality to infer intended users and scenarios - Looking for example files or test cases that demonstrate usage - Considering the problem domain the project addresses - Identifying both primary and secondary use cases 4. **Document Setup and Execution**: Extract or infer: + - Required dependencies and prerequisites - Installation steps - Configuration requirements @@ -38,19 +42,20 @@ When analyzing a project, you will: - If multiple directories are mentioned, check each for README files - Preserve any valuable existing content while updating outdated information - Structure the README with clear sections including: - * Project title and brief description - * Purpose and intent - * Key features - * How it works (high-level architecture) - * Use cases with examples - * Prerequisites - * Installation instructions - * Usage instructions with examples - * Configuration options (if applicable) - * Contributing guidelines (if found in the project) - * License information (if found) + - Project title and brief description + - Purpose and intent + - Key features + - How it works (high-level architecture) + - Use cases with examples + - Prerequisites + - Installation instructions + - Usage instructions with examples + - Configuration options (if applicable) + - Contributing guidelines (if found in the project) + - License information (if found) Best practices you follow: + - Write in clear, concise language accessible to your target audience - Use markdown formatting effectively (headers, code blocks, lists) - Include code examples and command-line snippets in code blocks @@ -60,6 +65,7 @@ Best practices you follow: - Update only what needs updating - preserve valuable existing content When you cannot determine certain information: + - Make reasonable inferences based on common patterns - Clearly mark sections that may need manual verification with comments like `` - Provide template sections for information you cannot extract diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2b94c86b951..f931d2932a4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -89,4 +89,4 @@ jobs: - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: - category: "/language:${{matrix.language}}" + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/on-pull-request.yml b/.github/workflows/on-pull-request.yml index 484e3ddd588..4305559af5c 100644 --- a/.github/workflows/on-pull-request.yml +++ b/.github/workflows/on-pull-request.yml @@ -5,22 +5,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -env: - FILES_TO_DELETE: | - sudo rm -rf "/usr/share/dotnet" - sudo rm -rf "/usr/share/swift" - sudo rm -rf "/usr/local/share/boost" - sudo rm -rf /opt/ghc - sudo rm -rf "/usr/local/share/boost" - sudo rm -rf "/usr/local/lib/android/sdk" - sudo rm -rf "/opt/hostedtoolcache/Python" - sudo rm -rf "/opt/hostedtoolcache/go" - sudo rm -rf "/opt/hostedtoolcache/CodeQL" - sudo rm -rf "/var/lib/gems" - sudo rm -rf "$AGENT_TOOLSDIRECTORY" - sudo apt-get clean -y - sudo apt-get autoremove -y - jobs: # Stop previous runs stop-previous-run: @@ -57,32 +41,23 @@ jobs: runs-on: ubuntu-22.04 needs: stop-previous-run steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 - - name: Check if forked master is up to date - id: check-forked-master if: github.repository_owner == 'module-federation' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - echo "${{ github.repository_owner }}" - git remote add base https://github.com/${{github.repository}} - git remote -v - git fetch --all - export FORKED_MASTER_SHA=$(git log -n 1 --pretty=format:"%H" origin/${{ github.event.pull_request.base.ref}}) - export BASE_MASTER_SHA=$(git log -n 1 --pretty=format:"%H" base/${{ github.event.pull_request.base.ref }}) - echo "$FORKED_MASTER_SHA" - echo "$BASE_MASTER_SHA" - - if [ "$FORKED_MASTER_SHA" == "$BASE_MASTER_SHA" ]; - then + BASE_REF="${{ github.event.pull_request.base.ref }}" + FORK_REPO="${{ github.event.pull_request.head.repo.full_name }}" + BASE_REPO="${{ github.repository }}" + + FORKED_SHA=$(gh api "repos/${FORK_REPO}/commits/${BASE_REF}" --jq '.sha') + BASE_SHA=$(gh api "repos/${BASE_REPO}/commits/${BASE_REF}" --jq '.sha') + + echo "Fork SHA: $FORKED_SHA" + echo "Base SHA: $BASE_SHA" + + if [ "$FORKED_SHA" == "$BASE_SHA" ]; then echo "The forked master is up to date with the base master branch" - exit 0 else echo "The forked master branch is not up to date with the base master branch, Please update your fork!" exit 1 @@ -101,18 +76,10 @@ jobs: with: repository: ${{ github.event.pull_request.head.repo.full_name }} ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 + fetch-depth: 1 - - name: Free disk space - shell: bash - run: | - echo "Freeing disk space on runner..." - while IFS= read -r cmd; do - [ -z "$cmd" ] && continue - echo ">> $cmd" - bash -lc "$cmd" || true - done <<< "$FILES_TO_DELETE" - df -h + - name: Fetch origin/master for diff + run: git fetch origin master --depth=1 - name: Get Playwright version id: playwright-version @@ -122,11 +89,8 @@ jobs: version="$(node -p "String(require('./package.json').devDependencies['@playwright/test']||'').replace(/^[^0-9]*/, '')")" echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - run_install: false + - name: Enable corepack + run: corepack enable - name: Setup Node.js with caching uses: actions/setup-node@v4 @@ -135,6 +99,9 @@ jobs: cache: 'pnpm' cache-dependency-path: '**/pnpm-lock.yaml' + - name: Re-enable corepack after setup-node + run: corepack enable + - name: Get pnpm store directory id: pnpm-cache shell: bash @@ -184,6 +151,7 @@ jobs: needs: [setup-matrix] if: ${{ needs.setup-matrix.outputs.matrix != '{"container":[]}' }} runs-on: ubuntu-22.04 + timeout-minutes: 45 strategy: fail-fast: false matrix: ${{fromJson(needs.setup-matrix.outputs.matrix)}} @@ -196,17 +164,6 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} fetch-depth: 1 - - name: Free disk space - shell: bash - run: | - echo "Freeing disk space on runner..." - while IFS= read -r cmd; do - [ -z "$cmd" ] && continue - echo ">> $cmd" - bash -lc "$cmd" || true - done <<< "$FILES_TO_DELETE" - df -h - - name: Get Playwright version id: playwright-version shell: bash @@ -214,11 +171,8 @@ jobs: version="$(node -p "String(require('./package.json').devDependencies['@playwright/test']||'').replace(/^[^0-9]*/, '')")" echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - run_install: false + - name: Enable corepack + run: corepack enable - name: Setup Node.js with caching id: setup-node @@ -228,6 +182,9 @@ jobs: cache: 'pnpm' cache-dependency-path: '**/pnpm-lock.yaml' + - name: Re-enable corepack after setup-node + run: corepack enable + - name: Get pnpm store directory id: pnpm-cache shell: bash diff --git a/.github/workflows/on-push.yml b/.github/workflows/on-push.yml index bbfa25ef81e..a5dfaada0cb 100644 --- a/.github/workflows/on-push.yml +++ b/.github/workflows/on-push.yml @@ -8,22 +8,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -env: - FILES_TO_DELETE: | - sudo rm -rf "/usr/share/dotnet" - sudo rm -rf "/usr/share/swift" - sudo rm -rf "/usr/local/share/boost" - sudo rm -rf /opt/ghc - sudo rm -rf "/usr/local/share/boost" - sudo rm -rf "/usr/local/lib/android/sdk" - sudo rm -rf "/opt/hostedtoolcache/Python" - sudo rm -rf "/opt/hostedtoolcache/go" - sudo rm -rf "/opt/hostedtoolcache/CodeQL" - sudo rm -rf "/var/lib/gems" - sudo rm -rf "$AGENT_TOOLSDIRECTORY" - sudo apt-get clean -y - sudo apt-get autoremove -y - jobs: # Stop previous runs stop-previous-run: @@ -44,9 +28,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 + fetch-depth: 1 - name: Get Playwright version id: playwright-version @@ -55,9 +37,6 @@ jobs: version="$(node -p "String(require('./package.json').devDependencies['@playwright/test']||'').replace(/^[^0-9]*/, '')")" echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Free up some space - run: ${{ env.FILES_TO_DELETE }} - # Hash pnpm-lock.yaml files to use it as a cache key, if pnpm-lock.yaml files are changed, the cache will be invalidated - name: Check pnpm hash id: yarn-hash @@ -65,11 +44,8 @@ jobs: yarnHash="$(npx hash-files -f '["**/pnpm-lock.yaml"]' -a sha256)" echo "yarnHash=$yarnHash" >> $GITHUB_OUTPUT - - name: Setup pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - run_install: false + - name: Enable corepack + run: corepack enable - name: Setup Node.js with caching uses: actions/setup-node@v4 @@ -78,6 +54,9 @@ jobs: cache: 'pnpm' cache-dependency-path: '**/pnpm-lock.yaml' + - name: Re-enable corepack after setup-node + run: corepack enable + - name: Get pnpm store directory id: pnpm-cache shell: bash @@ -99,7 +78,7 @@ jobs: with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}-headless-shell - + - name: Set Playwright cache status run: echo "PLAYWRIGHT_CACHE_HIT=${{ steps.playwright-cache.outputs.cache-hit }}" >> $GITHUB_ENV diff --git a/.gitignore b/.gitignore index 54a3ca991ce..ecce3d74b96 100644 --- a/.gitignore +++ b/.gitignore @@ -141,3 +141,15 @@ buildServer /comprehensive-demo-react*/**/public/*.css *.map +# Module Federation build outputs +**/mf-manifest.json +**/mf-stats.json +**/.__mf__temp/ + +# react-sharedworker build output +/react-sharedworker/host/build/ +/react-sharedworker/module/build/ + +# Server-side-render-only compiled output +/server-side-render-only/**/public/server/ + diff --git a/.npmrc b/.npmrc index 74649d01d37..6dbaad3638d 100644 --- a/.npmrc +++ b/.npmrc @@ -1,6 +1,3 @@ child-concurrency=8 registry=https://registry.npmjs.org/ - -# Use a hoisted node_modules layout to reduce Webpack/Rspack resolution issues -# caused by pnpm's content-addressable store + symlinked dependency graph. -node-linker=hoisted +strict-peer-dependencies=false diff --git a/.vscode/launch.json b/.vscode/launch.json index cd4d5eb2410..e913111c1e5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,4 +1,4 @@ { - "version": "0.2.0", - "configurations": [] -} \ No newline at end of file + "version": "0.2.0", + "configurations": [] +} diff --git a/README.md b/README.md index 5e033d2df09..30f5ec2448e 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,6 @@ This repository is to showcase examples of how Webpack 5's new Module Federation - Module federation enhances collections: [Universe](https://github.com/module-federation/universe) - Module Federation Docs: [Module Federation Docs](https://module-federation.io/) - - ## List of Examples Click here to see the detailed list of examples in this repo [Full Examples List](./output.md) diff --git a/advanced-api/automatic-vendor-sharing/README.md b/advanced-api/automatic-vendor-sharing/README.md index a1c1a4d8374..15b17385def 100644 --- a/advanced-api/automatic-vendor-sharing/README.md +++ b/advanced-api/automatic-vendor-sharing/README.md @@ -29,12 +29,14 @@ Automatic Vendor Sharing is a Module Federation feature that intelligently analy ## Why is it Important? ### Traditional Problems + - **Bundle Duplication**: Each microfrontend bundles its own copy of shared libraries (React, Lodash, etc.) - **Version Conflicts**: Different apps using different versions of the same library - **Network Overhead**: Multiple downloads of the same dependencies - **Cache Inefficiency**: Browser can't cache shared dependencies effectively ### Automatic Vendor Sharing Solutions + - **Intelligent Sharing**: Automatically shares compatible dependencies - **Reduced Bundle Sizes**: Up to 70% reduction in total JavaScript payload - **Faster Loading**: Shared dependencies cached across microfrontends @@ -74,7 +76,8 @@ This example features two React applications (`app1` and `app2`) that: ## Quick Start ### Prerequisites -- Node.js 16+ + +- Node.js 16+ - pnpm (recommended) or npm/yarn ### Installation & Running @@ -92,6 +95,7 @@ pnpm --filter automatic-vendor-sharing_app2 start ``` ### Available URLs + - **App 1**: [http://localhost:3001](http://localhost:3001) - **App 2**: [http://localhost:3002](http://localhost:3002) @@ -112,6 +116,7 @@ pnpm serve ## Architecture Overview ### File Structure + ``` automatice-vendor-sharing/ ├── app1/ @@ -133,6 +138,7 @@ automatice-vendor-sharing/ ``` ### Technology Stack + - **React 18**: Latest React with concurrent features - **Module Federation Enhanced**: Latest MF with AutomaticVendorFederation - **TypeScript**: Type safety for federated modules @@ -189,12 +195,12 @@ shared: { ### AutomaticVendorFederation Options -| Option | Description | Example | -|--------|-------------|----------| -| `exclude` | Dependencies to never share automatically | `['@module-federation/enhanced']` | -| `ignoreVersion` | Dependencies where version mismatches are acceptable | `['react', 'react-dom']` | -| `shareStrategy` | How to resolve version conflicts | `'loaded-first'`, `'version-first'` | -| `eager` | Load dependencies immediately vs on-demand | `false` (recommended for production) | +| Option | Description | Example | +| --------------- | ---------------------------------------------------- | ------------------------------------ | +| `exclude` | Dependencies to never share automatically | `['@module-federation/enhanced']` | +| `ignoreVersion` | Dependencies where version mismatches are acceptable | `['react', 'react-dom']` | +| `shareStrategy` | How to resolve version conflicts | `'loaded-first'`, `'version-first'` | +| `eager` | Load dependencies immediately vs on-demand | `false` (recommended for production) | ### Share Strategies @@ -228,33 +234,37 @@ shared: { ### AutomaticVendorFederation Benefits -| Aspect | Manual Sharing | Automatic Sharing | -|--------|---------------|------------------| -| **Setup Time** | Hours of configuration | Minutes | -| **Maintenance** | Update for every new dependency | Zero maintenance | -| **Error Rate** | High (manual version management) | Low (automatic detection) | -| **Bundle Optimization** | Inconsistent | Consistently optimized | -| **Version Conflicts** | Manual resolution required | Automatic resolution | -| **New Dependencies** | Must manually configure | Automatically included | +| Aspect | Manual Sharing | Automatic Sharing | +| ----------------------- | -------------------------------- | ------------------------- | +| **Setup Time** | Hours of configuration | Minutes | +| **Maintenance** | Update for every new dependency | Zero maintenance | +| **Error Rate** | High (manual version management) | Low (automatic detection) | +| **Bundle Optimization** | Inconsistent | Consistently optimized | +| **Version Conflicts** | Manual resolution required | Automatic resolution | +| **New Dependencies** | Must manually configure | Automatically included | ## Common Use Cases ### 1. Microfrontend Architecture + - **Multiple Teams**: Each team owns independent applications - **Shared Libraries**: Common design system, utilities, or frameworks - **Independent Deployment**: Teams deploy without coordinating dependencies ### 2. Plugin Systems + - **Core Application**: Main app with plugin architecture - **Third-party Plugins**: External modules that extend functionality - **Dependency Sharing**: Plugins share core app dependencies ### 3. Multi-Brand Applications + - **Shared Components**: Common UI components across brands - **Brand-specific Features**: Unique functionality per brand - **Optimized Loading**: Shared dependencies reduce load times ### 4. Progressive Migration + - **Legacy Integration**: Gradually modernize legacy applications - **Technology Mixing**: Combine different frontend frameworks - **Risk Mitigation**: Incremental migration with shared dependencies @@ -320,6 +330,7 @@ shared: { **Symptom**: React hooks errors or "Multiple versions of React" warnings **Solution**: + ```javascript // Ensure singleton configuration react: { @@ -333,11 +344,13 @@ react: { **Symptom**: "Loading chunk failed" or network errors **Diagnosis**: + - Check if remote application is running - Verify CORS headers are configured - Ensure remote URL is accessible **Solution**: + ```javascript // Add proper error boundaries @@ -350,6 +363,7 @@ react: { **Symptom**: TypeScript errors about missing modules **Solution**: + ```typescript // Add proper type declarations declare module 'app2/Button' { @@ -363,6 +377,7 @@ declare module 'app2/Button' { **Symptom**: Works in development but fails in production **Diagnosis**: + - Check `publicPath` configuration - Verify production URLs are correct - Ensure proper CORS configuration @@ -370,6 +385,7 @@ declare module 'app2/Button' { ### Debug Tools #### 1. Runtime Plugin Logging + ```javascript // Enable detailed logging in development if (process.env.NODE_ENV === 'development') { @@ -378,6 +394,7 @@ if (process.env.NODE_ENV === 'development') { ``` #### 2. Bundle Analysis + ```bash # Analyze bundle composition npm run analyze @@ -387,6 +404,7 @@ npx webpack-bundle-analyzer dist/static/js/*.js ``` #### 3. Network Monitoring + - Use browser DevTools Network tab - Monitor for failed chunk loads - Check timing of shared dependency loads @@ -408,7 +426,7 @@ const customShareStrategy = (localVersion, remoteVersion) => { ```javascript // Runtime remote URL resolution const getRemoteUrl = () => { - return process.env.NODE_ENV === 'production' + return process.env.NODE_ENV === 'production' ? 'https://app2.production.com/remoteEntry.js' : 'http://localhost:3002/remoteEntry.js'; }; @@ -425,8 +443,8 @@ module.exports = { new ModuleFederationPlugin({ library: { type: isServer ? 'commonjs-module' : 'var' }, // ... other MF config - }) - ] + }), + ], }; ``` diff --git a/advanced-api/automatic-vendor-sharing/app1/public/index.html b/advanced-api/automatic-vendor-sharing/app1/public/index.html index e7a195eac0d..0f13cb64d0f 100644 --- a/advanced-api/automatic-vendor-sharing/app1/public/index.html +++ b/advanced-api/automatic-vendor-sharing/app1/public/index.html @@ -1,4 +1,4 @@ - + diff --git a/advanced-api/automatic-vendor-sharing/app1/rspack.config.js b/advanced-api/automatic-vendor-sharing/app1/rspack.config.js index f0f5b9413af..43aef2be22c 100644 --- a/advanced-api/automatic-vendor-sharing/app1/rspack.config.js +++ b/advanced-api/automatic-vendor-sharing/app1/rspack.config.js @@ -1,6 +1,4 @@ -const { - HtmlRspackPlugin, -} = require('@rspack/core'); +const { HtmlRspackPlugin } = require('@rspack/core'); const { ModuleFederationPlugin } = require('@module-federation/enhanced/rspack'); const path = require('path'); diff --git a/advanced-api/automatic-vendor-sharing/app1/src/App.js b/advanced-api/automatic-vendor-sharing/app1/src/App.js index 77f75f3d8e3..c2c7bff0fb9 100644 --- a/advanced-api/automatic-vendor-sharing/app1/src/App.js +++ b/advanced-api/automatic-vendor-sharing/app1/src/App.js @@ -6,25 +6,29 @@ const RemoteButton = React.lazy(() => import('app2/Button')); // Enhanced loading component with visual feedback const LoadingFallback = ({ message = 'Loading remote module...' }) => ( -
-
+
+
{message}