From 1b33835b14f89d73dba979c5dcded15b7f653ca8 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Sun, 21 Jul 2024 18:35:43 +0800 Subject: [PATCH] home app fragment --- examples/basic-css/package.json | 4 +- .../components/SharedNav.tsx | 77 ++++++++++ .../federation-single-app/components/menu.tsx | 37 +++++ .../components/thing.module.css | 3 + .../cypress/e2e/app.cy.ts | 144 ++++++++++++++++++ .../cypress/fixtures/example.json | 5 + .../cypress/support/app.po.ts | 3 + .../cypress/support/commands.ts | 35 +++++ .../cypress/support/e2e.ts | 17 +++ .../cypress/tsconfig.json | 20 +++ examples/federation-single-app/next-env.d.ts | 5 + examples/federation-single-app/next.config.js | 71 +++++++++ examples/federation-single-app/package.json | 29 ++++ examples/federation-single-app/pages/_app.tsx | 70 +++++++++ .../federation-single-app/pages/_document.js | 26 ++++ .../federation-single-app/pages/api/test.js | 3 + .../pages/home/exposed-pages.tsx | 19 +++ .../pages/home/test-broken-remotes.tsx | 22 +++ .../pages/home/test-remote-hook.tsx | 16 ++ .../pages/home/test-shared-nav.tsx | 9 ++ .../federation-single-app/pages/index.tsx | 139 +++++++++++++++++ .../federation-single-app/public/.gitkeep | 0 .../federation-single-app/public/favicon.ico | Bin 0 -> 15086 bytes .../federation-single-app/public/webpack.png | Bin 0 -> 13941 bytes .../federation-single-app/public/webpack.svg | 5 + examples/federation-single-app/remotes.d.ts | 5 + examples/federation-single-app/tsconfig.json | 19 +++ 27 files changed, 781 insertions(+), 2 deletions(-) create mode 100644 examples/federation-single-app/components/SharedNav.tsx create mode 100644 examples/federation-single-app/components/menu.tsx create mode 100644 examples/federation-single-app/components/thing.module.css create mode 100644 examples/federation-single-app/cypress/e2e/app.cy.ts create mode 100644 examples/federation-single-app/cypress/fixtures/example.json create mode 100644 examples/federation-single-app/cypress/support/app.po.ts create mode 100644 examples/federation-single-app/cypress/support/commands.ts create mode 100644 examples/federation-single-app/cypress/support/e2e.ts create mode 100644 examples/federation-single-app/cypress/tsconfig.json create mode 100644 examples/federation-single-app/next-env.d.ts create mode 100644 examples/federation-single-app/next.config.js create mode 100644 examples/federation-single-app/package.json create mode 100644 examples/federation-single-app/pages/_app.tsx create mode 100644 examples/federation-single-app/pages/_document.js create mode 100644 examples/federation-single-app/pages/api/test.js create mode 100644 examples/federation-single-app/pages/home/exposed-pages.tsx create mode 100644 examples/federation-single-app/pages/home/test-broken-remotes.tsx create mode 100644 examples/federation-single-app/pages/home/test-remote-hook.tsx create mode 100644 examples/federation-single-app/pages/home/test-shared-nav.tsx create mode 100644 examples/federation-single-app/pages/index.tsx create mode 100644 examples/federation-single-app/public/.gitkeep create mode 100644 examples/federation-single-app/public/favicon.ico create mode 100644 examples/federation-single-app/public/webpack.png create mode 100644 examples/federation-single-app/public/webpack.svg create mode 100644 examples/federation-single-app/remotes.d.ts create mode 100644 examples/federation-single-app/tsconfig.json diff --git a/examples/basic-css/package.json b/examples/basic-css/package.json index 9fa64a28dc..9ec917d4c9 100644 --- a/examples/basic-css/package.json +++ b/examples/basic-css/package.json @@ -1,8 +1,8 @@ { "private": true, "scripts": { - "dev": "next", - "build": "next build", + "dev": "RSPACK_CONFIG_VALIDATE=loose-silent next", + "build": "cross-env RSPACK_CONFIG_VALIDATE=loose-silent NEXT_TELEMETRY_DISABLED=1 node --trace-deprecation --enable-source-maps ../../packages/next/dist/bin/next build", "start": "next start" }, "dependencies": { diff --git a/examples/federation-single-app/components/SharedNav.tsx b/examples/federation-single-app/components/SharedNav.tsx new file mode 100644 index 0000000000..5e8c4886a2 --- /dev/null +++ b/examples/federation-single-app/components/SharedNav.tsx @@ -0,0 +1,77 @@ +import React from "react"; +import { Menu, Layout } from "antd"; +import { useRouter } from "next/router"; +import "./menu"; + +const SharedNav = () => { + const { asPath, push } = useRouter(); + let activeMenu; + + if (asPath === "/" || asPath.startsWith("/home")) { + activeMenu = "/"; + } else if (asPath.startsWith("/shop")) { + activeMenu = "/shop"; + } else if (asPath.startsWith("/checkout")) { + activeMenu = "/checkout"; + } + + 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 ( + +
nextjs-mf
+ { + push(key); + }} + items={menuItems} + /> + + + ); +}; + +export default SharedNav; diff --git a/examples/federation-single-app/components/menu.tsx b/examples/federation-single-app/components/menu.tsx new file mode 100644 index 0000000000..0158f80b1a --- /dev/null +++ b/examples/federation-single-app/components/menu.tsx @@ -0,0 +1,37 @@ +import type { ItemType } from "antd/es/menu/interface"; + +import { useRouter } from "next/router"; +import { Menu } from "antd"; + +const menuItems: ItemType[] = [ + { label: "Main home", key: "/" }, + { label: "Test hook from remote", key: "/home/test-remote-hook" }, + { label: "Test broken remotes", key: "/home/test-broken-remotes" }, + { label: "Exposed pages", key: "/home/exposed-pages" }, + { + label: "Exposed components", + type: "group", + children: [{ label: "home/SharedNav", key: "/home/test-shared-nav" }], + }, +]; + +export default function AppMenu() { + const router = useRouter(); + + return ( + <> +
+ Home App Menu +
+ router.push(key)} + items={menuItems} + /> + + ); +} diff --git a/examples/federation-single-app/components/thing.module.css b/examples/federation-single-app/components/thing.module.css new file mode 100644 index 0000000000..dc4e7ca0a6 --- /dev/null +++ b/examples/federation-single-app/components/thing.module.css @@ -0,0 +1,3 @@ +.tjhin { + display: flex; +} diff --git a/examples/federation-single-app/cypress/e2e/app.cy.ts b/examples/federation-single-app/cypress/e2e/app.cy.ts new file mode 100644 index 0000000000..db3e39cd52 --- /dev/null +++ b/examples/federation-single-app/cypress/e2e/app.cy.ts @@ -0,0 +1,144 @@ +import { getH1, getH3 } from "../support/app.po"; + +describe("3000-home/", () => { + beforeEach(() => cy.visit("/")); + + describe("Warmup Next", () => { + xit("warms pages concurrently", () => { + const urls = [ + "/shop", + "/checkout", + "/checkout/test-title", + "/checkout/test-check-button", + "/api/test", + ]; + urls.forEach((url) => { + cy.request(url); // This makes a GET request, not a full page visit + }); + }); + }); + + describe("Welcome message", () => { + it("should display welcome message", () => { + getH1().contains("This is SPA combined"); + }); + }); + + describe("Image checks", () => { + xit("should check that the home-webpack-png and shop-webpack-png images are not 404", () => { + // Get the src attribute of the home-webpack-png image + cy.debug() + .get("img.home-webpack-png") + .invoke("attr", "src") + .then((src) => { + cy.log(src); + cy.request(src).its("status").should("eq", 200); + }); + + // Get the src attribute of the shop-webpack-png image + cy.get("img.shop-webpack-png") + .invoke("attr", "src") + .then((src) => { + // Send a GET request to the src URL + cy.request(src).its("status").should("eq", 200); + }); + }); + }); + + describe("Routing checks", () => { + it("check that clicking back and forwards in client side routeing still renders the content correctly", () => { + cy.visit("/shop"); + cy.wait(3000); + cy.url().should("include", "/shop"); + getH1().contains("Shop Page"); + //eslint-disable-next-line + cy.wait(3000); + cy.get(".home-menu-link").contains("Home 3000"); + cy.get(".home-menu-link").click(); + cy.wait(2000); + cy.url().should("include", "/"); + cy.wait(700); + getH1().contains("This is SPA combined"); + }); + }); + + describe("3000-home/checkout", () => { + beforeEach(() => { + cy.visit("/checkout"); + cy.visit("/"); + cy.visit("/checkout"); + }); + + describe("Welcome message", () => { + it("should display welcome message", () => { + getH1().contains("checkout page"); + }); + }); + + describe("Tag checks", () => { + it("should check that a .description + pre tag exists", () => { + cy.get(".description").should("exist"); + cy.get("main pre").should("exist"); + }); + }); + + describe("3000-home/checkout/test-title", () => { + beforeEach(() => cy.visit("/checkout/test-title")); + + it("should display welcome message", () => { + getH3().contains("This title came"); + }); + }); + + describe("3000-home/checkout/test-check-button", () => { + beforeEach(() => cy.visit("/checkout/test-check-button")); + + it("should display welcome message", () => { + cy.get("button").contains("Button"); + }); + }); + }); + + describe("3000-home/shop", () => { + beforeEach(() => cy.visit("/shop")); + + describe("Welcome message", () => { + it("should display welcome message", () => { + getH1().contains("Shop Page"); + }); + }); + + describe("Image checks", () => { + xit("should check that shop-webpack-png images are not 404", () => { + // Get the src attribute of the shop-webpack-png image + cy.get("img.shop-webpack-png") + .invoke("attr", "src") + .then((src) => { + // Send a GET request to the src URL + cy.request(src).its("status").should("eq", 200); + }); + }); + it("should check that shop-webpack-png images are not 404 between route clicks", () => { + cy.visit("/"); + cy.visit("/shop"); + cy.url().should("include", "/shop"); + getH1().contains("Shop Page"); + cy.get(".home-menu-link").click(); + //eslint-disable-next-line + cy.wait(2999); + cy.get("img.shop-webpack-png") + .invoke("attr", "src") + .then((src) => { + // Send a GET request to the src URL + cy.request(src).its("status").should("eq", 200); + }); + }); + }); + + describe("Tag checks", () => { + it("should check that a .description + pre tag exists", () => { + cy.get(".description + pre").should("exist"); + }); + }); + }); +}); diff --git a/examples/federation-single-app/cypress/fixtures/example.json b/examples/federation-single-app/cypress/fixtures/example.json new file mode 100644 index 0000000000..02e4254378 --- /dev/null +++ b/examples/federation-single-app/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/examples/federation-single-app/cypress/support/app.po.ts b/examples/federation-single-app/cypress/support/app.po.ts new file mode 100644 index 0000000000..e1f6920408 --- /dev/null +++ b/examples/federation-single-app/cypress/support/app.po.ts @@ -0,0 +1,3 @@ +export const getH1 = () => cy.get("h1"); +export const getH2 = () => cy.get("h2"); +export const getH3 = () => cy.get("h3"); diff --git a/examples/federation-single-app/cypress/support/commands.ts b/examples/federation-single-app/cypress/support/commands.ts new file mode 100644 index 0000000000..649d8a3a2d --- /dev/null +++ b/examples/federation-single-app/cypress/support/commands.ts @@ -0,0 +1,35 @@ +/// + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** + +// eslint-disable-next-line @typescript-eslint/no-namespace +declare namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + login(email: string, password: string): void; + } +} + +// -- This is a parent command -- +Cypress.Commands.add("login", (email, password) => { + console.log("Custom command example: Login", email, password); +}); +// +// -- This is a child command -- +// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/examples/federation-single-app/cypress/support/e2e.ts b/examples/federation-single-app/cypress/support/e2e.ts new file mode 100644 index 0000000000..ddf01ba5e0 --- /dev/null +++ b/examples/federation-single-app/cypress/support/e2e.ts @@ -0,0 +1,17 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.ts using ES2015 syntax: +import "./commands"; diff --git a/examples/federation-single-app/cypress/tsconfig.json b/examples/federation-single-app/cypress/tsconfig.json new file mode 100644 index 0000000000..0285a6e4c6 --- /dev/null +++ b/examples/federation-single-app/cypress/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "allowJs": true, + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["cypress", "node"], + "sourceMap": false + }, + "include": [ + "**/*.ts", + "**/*.js", + "../cypress.config.ts", + "../**/*.cy.ts", + "../**/*.cy.tsx", + "../**/*.cy.js", + "../**/*.cy.jsx", + "../**/*.d.ts" + ] +} diff --git a/examples/federation-single-app/next-env.d.ts b/examples/federation-single-app/next-env.d.ts new file mode 100644 index 0000000000..4f11a03dc6 --- /dev/null +++ b/examples/federation-single-app/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/federation-single-app/next.config.js b/examples/federation-single-app/next.config.js new file mode 100644 index 0000000000..819160b0a8 --- /dev/null +++ b/examples/federation-single-app/next.config.js @@ -0,0 +1,71 @@ +const { withNx } = require("@nx/next/plugins/with-nx"); +const NextFederationPlugin = require("@module-federation/nextjs-mf"); + +/** + * @type {import('@nx/next/plugins/with-nx').WithNxOptions} + **/ +const nextConfig = { + nx: { + // Set this to true if you would like to to use SVGR + // See: https://github.com/gregberge/svgr + svgr: false, + }, + webpack(config, options) { + const { isServer } = options; + config.watchOptions = { + ignored: ["**/node_modules/**", "**/@mf-types/**"], + }; + // used for testing build output snapshots + const remotes = { + checkout: `checkout@http://localhost:3002/_next/static/${ + isServer ? "ssr" : "chunks" + }/remoteEntry.js`, + home_app: `home_app@http://localhost:3000/_next/static/${ + isServer ? "ssr" : "chunks" + }/remoteEntry.js`, + shop: `shop@http://localhost:3001/_next/static/${ + isServer ? "ssr" : "chunks" + }/remoteEntry.js`, + }; + + config.plugins.push( + new NextFederationPlugin({ + name: "home_app", + filename: "static/chunks/remoteEntry.js", + remotes: { + shop: remotes.shop, + checkout: remotes.checkout, + }, + exposes: { + "./SharedNav": "./components/SharedNav", + "./menu": "./components/menu", + }, + shared: { + "lodash/": {}, + antd: { + requiredVersion: "5.19.1", + version: "5.19.1", + }, + "@ant-design/": { + singleton: true, + }, + }, + extraOptions: { + debug: false, + exposePages: true, + enableImageLoaderFix: true, + enableUrlLoaderFix: true, + }, + }), + ); + config.plugins.push({ + name: "xxx", + apply(compiler) { + compiler.options.devtool = false; + }, + }); + return config; + }, +}; + +module.exports = withNx(nextConfig); diff --git a/examples/federation-single-app/package.json b/examples/federation-single-app/package.json new file mode 100644 index 0000000000..1ec9664326 --- /dev/null +++ b/examples/federation-single-app/package.json @@ -0,0 +1,29 @@ +{ + "name": "@module-federation/3000-home", + "version": "1.0.0", + "private": true, + "dependencies": { + "next": "latest", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "antd": "5.19.1", + "@ant-design/cssinjs": "^1.21.0", + "buffer": "5.7.1", + "encoding": "0.1.13", + "eslint-scope": "7.2.2", + "events": "3.3.0", + "js-cookie": "3.0.5", + "lodash": "4.17.21", + "node-fetch": "2.7.0", + "schema-utils": "3.3.0", + "terser-webpack-plugin": "5.3.10", + "typescript": "5.3.3", + "upath": "2.0.1", + "url": "0.11.3", + "util": "0.12.5" + }, + "scripts": { + "dev": "RSPACK_CONFIG_VALIDATE=loose-silent next", + "build": "cross-env RSPACK_CONFIG_VALIDATE=loose-silent NEXT_TELEMETRY_DISABLED=1 node --trace-deprecation --enable-source-maps ../../packages/next/dist/bin/next build" + } +} diff --git a/examples/federation-single-app/pages/_app.tsx b/examples/federation-single-app/pages/_app.tsx new file mode 100644 index 0000000000..d5aace4470 --- /dev/null +++ b/examples/federation-single-app/pages/_app.tsx @@ -0,0 +1,70 @@ +import * as React from "react"; +import { useState } from "react"; +import App from "next/app"; +import { Layout, version, ConfigProvider } from "antd"; +import { StyleProvider } from "@ant-design/cssinjs"; +import Router, { useRouter } from "next/router"; + +const SharedNav = React.lazy(() => import("../components/SharedNav")); +import HostAppMenu from "../components/menu"; +function MyApp(props) { + const { Component, pageProps } = props; + const { asPath } = useRouter(); + const [MenuComponent, setMenuComponent] = useState(() => HostAppMenu); + const handleRouteChange = async (url) => { + if (url.startsWith("/shop")) { + } else if (url.startsWith("/checkout")) { + } else { + setMenuComponent(() => HostAppMenu); + } + }; + // handle first route hit. + React.useEffect(() => { + handleRouteChange(asPath); + }, [asPath]); + + //handle route change + React.useEffect(() => { + // Step 3: Subscribe on events + Router.events.on("routeChangeStart", handleRouteChange); + return () => { + Router.events.off("routeChangeStart", handleRouteChange); + }; + }, []); + return ( + + + + + + + + + + + + + + + + antd@{version} + + + + + + + ); +} + +MyApp.getInitialProps = async (ctx) => { + return App.getInitialProps(ctx); +}; + +export default MyApp; diff --git a/examples/federation-single-app/pages/_document.js b/examples/federation-single-app/pages/_document.js new file mode 100644 index 0000000000..8733f63205 --- /dev/null +++ b/examples/federation-single-app/pages/_document.js @@ -0,0 +1,26 @@ +import React from "react"; +import Document, { Html, Head, Main, NextScript } from "next/document"; + +class MyDocument extends Document { + static async getInitialProps(ctx) { + const initialProps = await Document.getInitialProps(ctx); + + return { + ...initialProps, + }; + } + + render() { + return ( + + + +
+ + + + ); + } +} + +export default MyDocument; diff --git a/examples/federation-single-app/pages/api/test.js b/examples/federation-single-app/pages/api/test.js new file mode 100644 index 0000000000..7b8d9c753c --- /dev/null +++ b/examples/federation-single-app/pages/api/test.js @@ -0,0 +1,3 @@ +export default function handler(req, res) { + res.status(200).json({ name: "John Doe" }); +} diff --git a/examples/federation-single-app/pages/home/exposed-pages.tsx b/examples/federation-single-app/pages/home/exposed-pages.tsx new file mode 100644 index 0000000000..ec81a13fe1 --- /dev/null +++ b/examples/federation-single-app/pages/home/exposed-pages.tsx @@ -0,0 +1,19 @@ +/* eslint-disable */ +import { useState, useEffect } from "react"; + +export default function ExposedPages() { + const [pageMap] = useState(""); + const [pageMapV2] = useState(""); + + return ( + <> +

This app exposes the following pages:

+ +

./pages-map

+
{JSON.stringify(pageMap, undefined, 2)}
+ +

./pages-map-v2

+
{JSON.stringify(pageMapV2, undefined, 2)}
+ + ); +} diff --git a/examples/federation-single-app/pages/home/test-broken-remotes.tsx b/examples/federation-single-app/pages/home/test-broken-remotes.tsx new file mode 100644 index 0000000000..42538b0b0b --- /dev/null +++ b/examples/federation-single-app/pages/home/test-broken-remotes.tsx @@ -0,0 +1,22 @@ +/* eslint-disable */ +import Link from "next/link"; + +export default function TestBrokenRemotes() { + return ( +
+

This page is a test for broken remoteEntries.js

+ +

+ Check unresolved host –{" "} + /unresolved-host (on + http://localhost:3333/_next/static/chunks/remoteEntry.js) +

+

+ Check wrong response for remoteEntry –{" "} + /wrong-entry (on + http://localhost:3000/_next/static/chunks/remoteEntryWrong + .js) +

+
+ ); +} diff --git a/examples/federation-single-app/pages/home/test-remote-hook.tsx b/examples/federation-single-app/pages/home/test-remote-hook.tsx new file mode 100644 index 0000000000..b1fe373343 --- /dev/null +++ b/examples/federation-single-app/pages/home/test-remote-hook.tsx @@ -0,0 +1,16 @@ +import { NextPage } from "next"; + +const TestRemoteHook: NextPage = () => { + return ( + <> +
+ Page with custom remote hook. You must see text in red box below: +
+
+ blank text for now +
+ + ); +}; + +export default TestRemoteHook; diff --git a/examples/federation-single-app/pages/home/test-shared-nav.tsx b/examples/federation-single-app/pages/home/test-shared-nav.tsx new file mode 100644 index 0000000000..a9a7dd4f5b --- /dev/null +++ b/examples/federation-single-app/pages/home/test-shared-nav.tsx @@ -0,0 +1,9 @@ +import SharedNav from "../../components/SharedNav"; + +export default function TestSharedNav() { + return ( +
+ +
+ ); +} diff --git a/examples/federation-single-app/pages/index.tsx b/examples/federation-single-app/pages/index.tsx new file mode 100644 index 0000000000..9234d53701 --- /dev/null +++ b/examples/federation-single-app/pages/index.tsx @@ -0,0 +1,139 @@ +/* eslint-disable */ +import React from "react"; +import Head from "next/head"; + +const Home = () => { + return ( + <> + + Home + + + +

+ This is SPA combined from 3 different nextjs applications. +

+

+ They utilize omnidirectional routing and pages or components are able to + be federated between applications. +

+

You may open any application by clicking on the links below:

+ +

Federation test cases

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test caseExpectedActual
+ Loading remote component (CheckoutTitle) from localhost:3002 +
+
+ lazy(()=>import('checkout/CheckoutTitle')) +
+
+

This title came from checkout with hooks data!!!

+
old
+ Load federated component from checkout with old antd version + [Button from antd@5.18.3]test
+ Loading remote component with PNG image from localhost:3001 +
+
(check publicPath fix in image-loader)
+
+ + other thing
+ Loading remote component with SVG from localhost:3001 +
+
(check publicPath fix in url-loader)
+
+ + anothaaaaaa
+ +

Other problems to fix:

+
    +
  • + 🐞 Incorrectly exposed modules in next.config.js (e.g. typo in path) + do not throw an error in console +
  • +
  • + 📝 Try to introduce a remote entry loading according to prefix path. + It will be nice runtime improvement if you have eg 20 apps and load + just one remoteEntry instead of all of them. +
  • +
  • + 📝 It will be nice to regenerate remoteEntry if new page was added in + remote app. +
  • +
  • + 📝 Remote components do not regenerate chunks if they were changed. +
  • +
+ + ); +}; +Home.getInitialProps = () => { + console.log("home calls get initial props"); + return {}; +}; +export default Home; diff --git a/examples/federation-single-app/public/.gitkeep b/examples/federation-single-app/public/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/federation-single-app/public/favicon.ico b/examples/federation-single-app/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4965832f2c9b0605eaa189b7c7fb11124d24e48a GIT binary patch literal 15086 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 + + + + diff --git a/examples/federation-single-app/remotes.d.ts b/examples/federation-single-app/remotes.d.ts new file mode 100644 index 0000000000..f5d9a71722 --- /dev/null +++ b/examples/federation-single-app/remotes.d.ts @@ -0,0 +1,5 @@ +declare module "shop/useCustomRemoteHook"; +declare module "shop/WebpackSvg"; +declare module "shop/WebpackPng"; +declare module "checkout/CheckoutTitle"; +declare module "checkout/ButtonOldAnt"; diff --git a/examples/federation-single-app/tsconfig.json b/examples/federation-single-app/tsconfig.json new file mode 100644 index 0000000000..7aabbd6f50 --- /dev/null +++ b/examples/federation-single-app/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "target": "es2017", + "jsx": "preserve", + "module": "esnext", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": false, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "resolveJsonModule": true, + "isolatedModules": true, + "incremental": true + }, + "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "next-env.d.ts"], + "exclude": ["node_modules", "jest.config.ts"] +}