Skip to content

Commit

Permalink
feat(react): Add federate-module generator
Browse files Browse the repository at this point in the history
  • Loading branch information
ndcunningham committed Oct 5, 2023
1 parent 0c5edf7 commit d19ffde
Show file tree
Hide file tree
Showing 15 changed files with 815 additions and 5 deletions.
8 changes: 8 additions & 0 deletions docs/generated/manifests/menus.json
Original file line number Diff line number Diff line change
Expand Up @@ -8074,6 +8074,14 @@
"children": [],
"isExternal": false,
"disableCollapsible": false
},
{
"id": "federate-module",
"path": "/nx-api/react/generators/federate-module",
"name": "federate-module",
"children": [],
"isExternal": false,
"disableCollapsible": false
}
],
"isExternal": false,
Expand Down
9 changes: 9 additions & 0 deletions docs/generated/manifests/nx-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,15 @@
"originalFilePath": "/packages/react/src/generators/setup-ssr/schema.json",
"path": "/nx-api/react/generators/setup-ssr",
"type": "generator"
},
"/nx-api/react/generators/federate-module": {
"description": "Federate a module.",
"file": "generated/packages/react/generators/federate-module.json",
"hidden": false,
"name": "federate-module",
"originalFilePath": "/packages/react/src/generators/federate-module/schema.json",
"path": "/nx-api/react/generators/federate-module",
"type": "generator"
}
},
"path": "/nx-api/react"
Expand Down
9 changes: 9 additions & 0 deletions docs/generated/packages-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,15 @@
"originalFilePath": "/packages/react/src/generators/setup-ssr/schema.json",
"path": "react/generators/setup-ssr",
"type": "generator"
},
{
"description": "Federate a module.",
"file": "generated/packages/react/generators/federate-module.json",
"hidden": false,
"name": "federate-module",
"originalFilePath": "/packages/react/src/generators/federate-module/schema.json",
"path": "react/generators/federate-module",
"type": "generator"
}
],
"githubRoot": "https://github.com/nrwl/nx/blob/master",
Expand Down
118 changes: 118 additions & 0 deletions docs/generated/packages/react/generators/federate-module.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
{
"name": "federate-module",
"factory": "./src/generators/federate-module/federate-module#federateModuleGenerator",
"schema": {
"$schema": "http://json-schema.org/draft-04/schema",
"cli": "nx",
"$id": "NxReactFederateModule",
"title": "Federate Module",
"description": "Create a federated module, which can be loaded by a remote host.",
"examples": [
{
"command": "nx g federate-module MyModule --path=./src/component/my-cmp.ts --remote=my-remote-app",
"description": "Create a federated module called my-remote-app, that exposes my-cmp from ./src/component/my-cmp.ts. called Mymodule."
}
],
"type": "object",
"properties": {
"name": {
"description": "The name of the module.",
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the module?",
"pattern": "^[a-zA-Z][^:]*$"
},
"path": {
"type": "string",
"description": "The relative path from the remote root to the module to be federated.",
"x-prompt": "What is the path to the module to be federated?"
},
"remote": {
"type": "string",
"description": "The name of the remote.",
"x-prompt": "What is/should the remote be named?"
},
"projectNameAndRootFormat": {
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"style": {
"description": "The file extension to be used for style files.",
"type": "string",
"default": "css",
"alias": "s",
"x-prompt": {
"message": "Which stylesheet format would you like to use?",
"type": "list",
"items": [
{ "value": "css", "label": "CSS" },
{
"value": "scss",
"label": "SASS(.scss) [ http://sass-lang.com ]"
},
{
"value": "less",
"label": "LESS [ http://lesscss.org ]"
},
{
"value": "styled-components",
"label": "styled-components [ https://styled-components.com ]"
},
{
"value": "@emotion/styled",
"label": "emotion [ https://emotion.sh ]"
},
{
"value": "styled-jsx",
"label": "styled-jsx [ https://www.npmjs.com/package/styled-jsx ]"
},
{
"value": "styl",
"label": "DEPRECATD: Stylus(.styl) [ http://stylus-lang.com ]"
},
{ "value": "none", "label": "None" }
]
}
},
"linter": {
"description": "The tool to use for running lint checks.",
"type": "string",
"enum": ["eslint"],
"default": "eslint"
},
"skipFormat": {
"description": "Skip formatting files.",
"type": "boolean",
"default": false,
"x-priority": "internal"
},
"unitTestRunner": {
"type": "string",
"enum": ["jest", "none"],
"description": "Test runner to use for unit tests.",
"default": "jest"
},
"e2eTestRunner": {
"type": "string",
"enum": ["cypress", "none"],
"description": "Test runner to use for end to end (e2e) tests.",
"default": "cypress"
},
"host": {
"type": "string",
"description": "The host / shell application for this remote.",
"x-priority": "important"
}
},
"required": ["name"],
"additionalProperties": false,
"presets": []
},
"description": "Federate a module.",
"hidden": false,
"implementation": "/packages/react/src/generators/federate-module/federate-module#federateModuleGenerator.ts",
"aliases": [],
"path": "/packages/react/src/generators/federate-module/schema.json",
"type": "generator"
}
1 change: 1 addition & 0 deletions docs/shared/reference/sitemap.md
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@
- [component-test](/nx-api/react/generators/component-test)
- [setup-tailwind](/nx-api/react/generators/setup-tailwind)
- [setup-ssr](/nx-api/react/generators/setup-ssr)
- [federate-module](/nx-api/react/generators/federate-module)
- [react-native](/nx-api/react-native)
- [documents](/nx-api/react-native/documents)
- [Overview](/nx-api/react-native/documents/overview)
Expand Down
102 changes: 100 additions & 2 deletions e2e/react-core/src/react-module-federation.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { stripIndents } from '@nx/devkit';
import { Tree, stripIndents } from '@nx/devkit';
import {
checkFilesExist,
cleanupProject,
Expand All @@ -15,11 +15,16 @@ import {
updateJson,
} from '@nx/e2e/utils';
import { join } from 'path';
import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports';

describe('React Module Federation', () => {
let proj: string;
let tree: Tree;

beforeAll(() => (proj = newProject()));
beforeAll(() => {
tree = createTreeWithEmptyWorkspace();
proj = newProject();
});

afterAll(() => cleanupProject());

Expand Down Expand Up @@ -382,6 +387,99 @@ describe('React Module Federation', () => {
}
}, 500_000);

// Federate Module
describe('Federate Module', () => {
it('should federate a module from a library and update an existing remote', async () => {
const lib = uniq('lib');
const remote = uniq('remote');
const module = uniq('module');
const host = uniq('host');

runCLI(
`generate @nx/react:host ${host} --remotes=${remote} --no-interactive --projectNameAndRootFormat=as-provided`
);

runCLI(
`generate @nx/js:lib ${lib} --no-interactive --projectNameAndRootFormat=as-provided`
);

// Federate Module
runCLI(
`generate @nx/react:federate-module ${module} --remote=${remote} --path=${lib}/src/index.ts --no-interactive`
);

updateFile(
`${lib}/src/index.ts`,
`export { default } from './lib/${lib}';`
);
updateFile(
`${lib}/src/lib/${lib}.ts`,
`export default function lib() { return 'Hello from ${lib}'; };`
);

// Update Host to use the module
updateFile(
`${host}/src/app/app.tsx`,
`
import * as React from 'react';
import NxWelcome from './nx-welcome';
import { Link, Route, Routes } from 'react-router-dom';
import myLib from '${remote}/${module}';
export function App() {
return (
<React.Suspense fallback={null}>
<div className='remote'>
My Remote Library: { myLib() }
</div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
</ul>
<Routes>
<Route path="/" element={<NxWelcome title="Host" />} />
</Routes>
</React.Suspense>
);
}
export default App;
`
);

// Update e2e test to check the module
updateFile(
`${host}-e2e/src/e2e/app.cy.ts`,
`
describe('${host}', () => {
beforeEach(() => cy.visit('/'));
it('should display contain the remote library', () => {
expect(cy.get('div.remote')).to.exist;
expect(cy.get('div.remote').contains('My Remote Library: Hello from ${lib}'));
});
});
`
);

// Build host and remote
const buildOutput = runCLI(`build ${host}`);
const remoteOutput = runCLI(`build ${remote}`);

expect(buildOutput).toContain('Successfully ran target build');
expect(remoteOutput).toContain('Successfully ran target build');

if (runE2ETests()) {
const hostE2eResults = runCLI(`e2e ${host}-e2e --no-watch --verbose`);

expect(hostE2eResults).toContain('All specs passed!');
}
}, 500_000);
});

function readPort(appName: string): number {
const config = readJson(join('apps', appName, 'project.json'));
return config.targets.serve.options.port;
Expand Down
14 changes: 14 additions & 0 deletions packages/react/generators.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@
"schema": "./src/generators/setup-ssr/schema.json",
"description": "Set up SSR configuration for a project.",
"hidden": false
},

"federate-module": {
"factory": "./src/generators/federate-module/federate-module#federateModuleSchematic",
"schema": "./src/generators/federate-module/schema.json",
"description": "Federate a module.",
"hidden": false
}
},
"generators": {
Expand Down Expand Up @@ -218,6 +225,13 @@
"schema": "./src/generators/setup-ssr/schema.json",
"description": "Set up SSR configuration for a project.",
"hidden": false
},

"federate-module": {
"factory": "./src/generators/federate-module/federate-module#federateModuleGenerator",
"schema": "./src/generators/federate-module/schema.json",
"description": "Federate a module.",
"hidden": false
}
}
}
Loading

0 comments on commit d19ffde

Please sign in to comment.