diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 00000000000..e5b6d8d6a67 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 00000000000..dd554b2e465 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [ + [ + "@module-federation/runtime", + "@module-federation/enhanced", + "@module-federation/webpack-bundler-runtime", + "@module-federation/sdk" + ] + ], + "ignorePatterns": ["^alpha|^beta"], + "linked": [], + "access": "restricted", + "baseBranch": "canary", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.changeset/nice-days-learn.md b/.changeset/nice-days-learn.md new file mode 100644 index 00000000000..b050f26b138 --- /dev/null +++ b/.changeset/nice-days-learn.md @@ -0,0 +1,5 @@ +--- +'@module-federation/runtime': patch +--- + +fix: add runtime api diff --git a/.eslintrc.json b/.eslintrc.json index 904908e2e12..bf90b98a5e4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -48,7 +48,7 @@ "files": ["*.json"], "parser": "jsonc-eslint-parser", "rules": { - "@nx/dependency-checks": "error" + "@nx/dependency-checks": "off" } } ] diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml new file mode 100644 index 00000000000..83d6f8a4c67 --- /dev/null +++ b/.github/pr-labeler.yml @@ -0,0 +1,10 @@ +'change: feat': + - '/^(feat|types|style)/' +'change: fix': + - '/^fix/' +'change: perf': + - '/^perf/' +'change: breaking': + - '/^breaking change/' +'change: docs': + - '/^docs/' diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 8db5c79c148..4d72d550073 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -17,10 +17,21 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Install Pnpm + run: corepack enable + - name: Setup Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'pnpm' + - name: Install cypress + run: npx cypress install - uses: nrwl/nx-set-shas@v3 - - run: npm ci - + - run: pnpm install - run: npx nx format:check - - run: npx nx affected -t lint --parallel=3 --exclude='*,!tag:package' + - run: npx nx affected -t build --parallel=10 --exclude='*,!tag:package' + - run: npx nx affected -t lint --parallel=7 --exclude='*,!tag:package' - run: npx nx affected -t test --parallel=3 --exclude='*,!tag:package' - - run: npx nx affected -t build --parallel=3 --exclude='*,!tag:package' + - run: npx nx run-many --target=serve --projects=3000-home,3001-shop,3002-checkout --parallel=3 & echo "done" + - run: sleep 6 && npx nx run-many --target=test:e2e --projects=3000-home,3001-shop,3002-checkout --parallel=1 + - run: lsof -ti tcp:3000,3001,3002 | xargs kill diff --git a/.github/workflows/pr-label.yaml b/.github/workflows/pr-label.yaml new file mode 100644 index 00000000000..f5a2d36410f --- /dev/null +++ b/.github/workflows/pr-label.yaml @@ -0,0 +1,20 @@ +name: PR Labeler + +on: + pull_request_target: + types: + - opened + - edited + +jobs: + change-labeling: + name: Labeling for changes + runs-on: ubuntu-latest + steps: + - uses: github/issue-labeler@v3.2 + with: + repo-token: '${{ secrets.GITHUB_TOKEN }}' + configuration-path: .github/pr-labeler.yml + enable-versioned-regex: 0 + include-title: 1 + sync-labels: 1 diff --git a/.github/workflows/release-pull-request.yml b/.github/workflows/release-pull-request.yml new file mode 100644 index 00000000000..10604a8bd9e --- /dev/null +++ b/.github/workflows/release-pull-request.yml @@ -0,0 +1,52 @@ +name: Release Pull Request + +on: + workflow_dispatch: + inputs: + version: + type: choice + description: 'Release Type (next, beta, alpha, latest)' + required: true + default: 'latest' + options: + - next + - beta + - alpha + - latest + +jobs: + release: + name: Create Release Pull Request + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@master + with: + # This makes Actions fetch only one branch to release + fetch-depth: 10 + + - name: Install Pnpm + run: corepack enable + + - name: Setup Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'pnpm' + + - name: Install Dependencies + run: pnpm install --ignore-scripts + + - name: Create Release Pull Request + uses: web-infra-dev/actions@v2 + with: + # this expects you to have a script called release which does a build for your packages and calls changeset publish + version: ${{ github.event.inputs.version || 'latest' }} + versionNumber: 'auto' + type: 'pull request' + tools: 'changeset' + env: + GITHUB_TOKEN: ${{ secrets.REPO_SCOPED_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + REPOSITORY: ${{ github.repository }} + REF: ${{ github.ref }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000..8d7b835312d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,105 @@ +name: Release +on: + workflow_dispatch: + inputs: + version: + type: choice + description: 'Release Version (next, beta, alpha, latest)' + required: true + default: 'next' + options: + - next + - beta + - alpha + - latest + branch: + description: 'Release Branch (confirm release branch)' + required: true + default: 'canary' + issue_comment: + types: [created] + +permissions: + id-token: write + +jobs: + issue_comment: + name: Release with comment + if: github.event.issue.pull_request && contains(github.event.comment.body, '!canary') + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + fetch-depth: 1 + ref: refs/pull/${{ github.event.issue.number }}/head + + - name: Install Pnpm + run: corepack enable + + - name: Setup Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'pnpm' + + - name: Install deps + run: pnpm install + + - name: Build and test Packages + run: npx nx affected -t pre-release --parallel=3 --exclude='*,!tag:package' --base=origin/canary --head=${{ github.ref }} + + - name: Release + uses: web-infra-dev/actions@v2 + with: + version: 'next' + type: 'release' + branch: '' + tools: 'changeset' + env: + GITHUB_TOKEN: ${{ secrets.REPO_SCOPED_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + REPOSITORY: ${{ github.repository }} + PULL_REQUEST_NUMBER: ${{ github.event.issue.number }} + COMMENT: ${{ toJson(github.event.comment) }} + + release: + name: Release + if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'push' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 25 + + - name: Install Pnpm + run: corepack enable + + - name: Setup Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: '18' + cache: 'pnpm' + + - name: Install deps + run: pnpm install + + - name: Build and test Packages + run: | + git fetch origin canary + npx nx affected -t pre-release --parallel=3 --exclude='*,!tag:package' --base=origin/canary --head=${{ github.ref }} + + - name: Release + uses: web-infra-dev/actions@v2 + with: + version: ${{ github.event.inputs.version || 'next' }} + branch: ${{ github.event.inputs.branch }} + type: 'release' + tools: 'changeset' + env: + GITHUB_TOKEN: ${{ secrets.REPO_SCOPED_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + REPOSITORY: ${{ github.repository }} + REF: ${{ github.ref }} diff --git a/.github/workflows/trigger-release.yml b/.github/workflows/trigger-release-abandon.yml similarity index 96% rename from .github/workflows/trigger-release.yml rename to .github/workflows/trigger-release-abandon.yml index df71c52f687..8db0194c122 100644 --- a/.github/workflows/trigger-release.yml +++ b/.github/workflows/trigger-release-abandon.yml @@ -11,10 +11,13 @@ on: - affected - all - nextjs-mf + - runtime + - sdk - node - storybook-addon - typescript - utils + - webpack-bundler-runtime - native-federation-typescript - native-federation-tests - enhanced diff --git a/.gitignore b/.gitignore index 4de67118892..a471817418b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ /build /@mf-types /docs - +/.nx # dependencies node_modules @@ -45,3 +45,7 @@ Thumbs.db .next .netlify migrations.json + +# build contnt +packages/**/dist +apps/**/dist \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 65653485755..53d9c3f0a17 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,30 +1,113 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { - "command": "npm run start:next", - "name": "Run npm start:next", + "command": "npm run nx", + "name": "Run nx", "request": "launch", "type": "node-terminal" }, { - "type": "node", + "command": "npm run commit", + "name": "Run commit", "request": "launch", - "name": "gpt:pr", - "skipFiles": ["/**"], - "program": "${workspaceFolder}/gpt/index.js", - "args": ["--pr"] + "type": "node-terminal" + }, + { + "command": "npm run docs", + "name": "Run docs", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run e2e:test", + "name": "Run e2e:test", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run lint", + "name": "Run lint", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run test", + "name": "Run test", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run build", + "name": "Run build", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run lint-fix", + "name": "Run lint-fix", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run trigger-release", + "name": "Run trigger-release", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run serve:next", + "name": "Run serve:next", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run serve:website", + "name": "Run serve:website", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run build:website", + "name": "Run build:website", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run extract-i18n:website", + "name": "Run extract-i18n:website", + "request": "launch", + "type": "node-terminal" }, { - "type": "node", + "command": "npm run postinstall", + "name": "Run postinstall", "request": "launch", - "name": "gpt:commit", - "skipFiles": ["/**"], - "program": "${workspaceFolder}/gpt/index.js", - "args": ["--commit"] + "type": "node-terminal" + }, + { + "command": "npm run sync:types:webpack", + "name": "Run sync:types:webpack", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run sync:pullMFTypes", + "name": "Run sync:pullMFTypes", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run app:next:dev", + "name": "Run app:next:dev", + "request": "launch", + "type": "node-terminal" + }, + { + "command": "npm run app:next:prod", + "name": "Run app:next:prod", + "request": "launch", + "type": "node-terminal" } ] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e73e4d7420..18775ffe397 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,18 +1,142 @@ -# Thanks you for your contribution! +# Module Federation Contributing Guide -## commits +Thank you for your interest in contributing to Module Federation! Before starting your contribution, please take a moment to read the following guidelines. -- must be followed by conventional commits -- could be achieved by using git commitizen (embedded in this repo). +## Sending a Pull Request -## version release +1. [Fork](https://help.github.com/articles/fork-a-repo/) the Module Federation repository into your own GitHub account. +2. [Clone](https://help.github.com/articles/cloning-a-repository/) the repository to your local machine. +3. Checkout a new branch from `main` or `canary`. +4. Set up the development environment. Refer to the "Setup Development Environment" section below for guidance. +5. If you've fixed a bug or added code that should be tested, add some tests. +6. Ensure all tests pass. See the "Testing" section below for more information. +7. Run `nx format:write` and `nx affected -t lint --parallel=7 --exclude='*,!tag:package'` to check and fix the code style. +8. If you've changed Node.js packages, run `npm run commit` for semantic versioning and commit. +9. Submit the Pull Request, ensuring all CI runs pass. +10. Your Pull Request will be reviewed by the maintainers soon. + +**Note:** +- Keep your PRs concise, addressing a single issue or feature. +- Include a detailed description in your PR and link to related issues. + +## Setup Development Environment + +### Install Node.js + +We recommend using Node.js 18 LTS. Check your Node.js version with `node -v`. + +To install Node.js, use [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm): + +```bash +# Install Node.js 18 LTS +nvm install 18 --lts +nvm alias default 18 +nvm use 18 +``` + +### Install Dependencies + +```sh +# Enable pnpm with corepack, only available on Node.js >= `v14.19.0` +corepack enable +``` + +Add nx to global + +```bash +pnpm add nx@latest -g +``` + +First, install NX globally: + +```sh +pnpm install +``` + +What this will do: + +- Install all dependencies +- Create symlinks between packages in the monorepo + + +## Testing + +Testing is a crucial part of the development process in Module Federation. Here's how you can run tests: + +### Running All Tests + +To execute all test suites in the project, use: + +```sh +npx nx run-many -t test --parallel=3 +``` + +This command runs every test across all projects in the repository. + +### Running Tests for Specific Projects + +If you need to run tests for a specific project, use: + +```sh +npx nx run-many -t test --parallel=3 --projects=PROJECT-NAME +``` + +Replace `PROJECT-NAME` with the actual name of the project you want to test. The `--parallel=3` flag allows simultaneous execution of up to 3 test suites, improving the overall testing speed. + +### Running Impacted Tests + +To run tests only for the projects affected by recent changes, use: + +```sh +npx nx affected -t test --parallel=3 --exclude='*,!tag:package' +``` + +This command ensures that only relevant tests are executed, saving time and resources. + + +## Submitting Changes + +### Add a Changeset + +Universe is using [Changesets](https://github.com/changesets/changesets) to manage the versioning and changelogs. + +If you've changed some packages, you need add a new changeset for the changes. Please run `changeset` command to select the changed packages and add the changeset info. + +```sh +pnpm run changeset +``` + +![image](https://github.com/module-federation/universe/assets/27547179/15505abf-8b0b-450f-b2d0-ffdc52e710a4) + + +### Committing your Changes + +Commit your changes to your forked repo, and [create a pull request](https://help.github.com/articles/creating-a-pull-request/). + +### Format of PR titles + +The format of PR titles follow Conventional Commits. + +An example: + +``` +feat(plugin-swc): Add `xxx` config +^ ^ ^ +| | |__ Subject +| |_______ Scope +|____________ Type +``` + + +## Release + +Module Federation uses GitHub Actions for automated versioning and publishing: + +## Action release + +* next: The timestamp version will be created when you release with the next version, which is suitable for testing on your own +* beta|alpha: Suitable for releasing test versions +* latest: Suitable for releasing stable versions in the trunk branch + +![image](https://github.com/module-federation/universe/assets/27547179/18580135-3326-4bff-9ba1-0570f40f9e2a) -- to release a version, please follow this command: - - `nx run PROJECT-NAME:version --releaseAs=MAJOR/MINOR/PATCH` - - find more options [here](https://github.com/jscutlery/semver#specify-the-level-of-change) -- this command will perform couple of operations. - - tag your commit with the relevant version. - - create changelog using semantic commits. - - bump the version of the project. - - if other projects depends on the current released project, they will be bumped as well. - - if case of bumping nextjs-mf project, NPM publish operation will be performed as well. diff --git a/README.md b/README.md index f5c48195ba4..39d670602ea 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,12 @@ Come and chat with us on [Discord](https://discord.com/invite/T8c6yAxkbv)! The M Please read the [Contributing Guide](https://github.com/module-federation/universe/blob/canary/CONTRIBUTING.md). -## 🙌 Code of Conduct +# Credits + +Thanks to: + +- The [vite-plugin-federation](https://github.com/originjs/vite-plugin-federation) project created by [@ruleeeer](https://github.com/ruleeeer), `@module-federation/runtime` fork `vite-plugin-federation` semver logic used to verify version + +# 🙌 Code of Conduct This repo has adopted the Code of Conduct. Please check [Code of Conduct](./CODE_OF_CONDUCT.md) for more details. diff --git a/apps/3000-home/.eslintrc.json b/apps/3000-home/.eslintrc.json index 2053b0f6903..ccc1a074c6a 100644 --- a/apps/3000-home/.eslintrc.json +++ b/apps/3000-home/.eslintrc.json @@ -1,5 +1,6 @@ { "extends": [ + "plugin:cypress/recommended", "plugin:@nx/react-typescript", "next", "next/core-web-vitals", @@ -20,6 +21,10 @@ { "files": ["*.js", "*.jsx"], "rules": {} + }, + { + "files": ["*.cy.{ts,js,tsx,jsx}", "cypress/**/*.{ts,js,tsx,jsx}"], + "rules": {} } ], "rules": { diff --git a/apps/3000-home/components/SharedNav.tsx b/apps/3000-home/components/SharedNav.tsx index 1960644a9c0..5a0a910975d 100644 --- a/apps/3000-home/components/SharedNav.tsx +++ b/apps/3000-home/components/SharedNav.tsx @@ -5,12 +5,8 @@ import './menu'; const SharedNav = () => { const { asPath, push } = useRouter(); - // is used here as a demo for tracking loading status of remote container - // const homeRemote = useMFRemote('home_app'); - // const shopRemote = useMFRemote('shop'); - // const checkoutRemote = useMFRemote('checkout'); - let activeMenu; + if (asPath === '/' || asPath.startsWith('/home')) { activeMenu = '/'; } else if (asPath.startsWith('/shop')) { @@ -19,8 +15,36 @@ const SharedNav = () => { activeMenu = '/checkout'; } - // const badgeColor = (remoteData) => - // remoteData.error ? 'red' : remoteData.loaded ? 'green' : 'yellow'; + const menuItems = [ + { + className: 'home-menu-link', + label: ( + <> + Home 3000 + + ), + key: '/', + onMouseEnter: () => {}, + }, + { + className: 'shop-menu-link', + label: ( + <> + Shop 3001 + + ), + key: '/shop', + }, + { + className: 'checkout-menu-link', + label: ( + <> + Checkout 3002 + + ), + key: '/checkout', + }, + ]; return ( @@ -32,40 +56,7 @@ const SharedNav = () => { onClick={({ key }) => { push(key); }} - items={[ - { - label: ( - <> - Home 3000 - - ), - key: '/', - onMouseEnter: () => { - // prefetch remote container on HOVER manually - // if you use `next/link` it prefetches remoteEntry automatically - // but here Antd.Menu does not use Link, so do it manually - // homeRemote.remote.getContainer(); - }, - }, - { - label: ( - <> - Shop 3001 - - ), - key: '/shop', - // onMouseEnter: () => shopRemote.remote.getContainer(), - }, - { - label: ( - <> - Checkout 3002 - - ), - key: '/checkout', - // onMouseEnter: () => checkoutRemote.remote.getContainer(), - }, - ]} + items={menuItems} />