diff --git a/packages/create-module-federation/package.json b/packages/create-module-federation/package.json index 298cf225f7..067d7bf00f 100644 --- a/packages/create-module-federation/package.json +++ b/packages/create-module-federation/package.json @@ -3,7 +3,7 @@ "description": "Create a new Module Federation project", "public": true, "sideEffects": false, - "version": "0.0.0", + "version": "0.0.0-1737428758075", "license": "MIT", "repository": { "type": "git", @@ -18,11 +18,14 @@ "build": "rslib build" }, "main": "./dist/index.js", + "engines": { + "node": ">=16.7.0" + }, "bin": { "create-module-federation": "./dist/index.js" }, "files": [ - "template", + "templates", "dist" ], "dependencies": { diff --git a/packages/create-module-federation/project.json b/packages/create-module-federation/project.json index 98bc4c8d17..97a9be02ad 100644 --- a/packages/create-module-federation/project.json +++ b/packages/create-module-federation/project.json @@ -32,17 +32,16 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "executor": "nx:run-commands", "options": { - "jestConfig": "packages/create-module-federation/jest.config.js", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } + "parallel": false, + "dependsOn": [ + { + "target": "build", + "dependencies": true + } + ], + "commands": ["echo 'no test'"] } }, "pre-release": { diff --git a/packages/create-module-federation/src/create.ts b/packages/create-module-federation/src/create.ts index 2b798ccba0..fe9826af58 100644 --- a/packages/create-module-federation/src/create.ts +++ b/packages/create-module-federation/src/create.ts @@ -4,6 +4,7 @@ */ import path from 'path'; import fs from 'fs'; +import { fileURLToPath } from 'url'; import { cancel, isCancel, @@ -18,6 +19,10 @@ import { logger } from 'rslog'; import { FsMaterial } from './materials/FsMaterial'; import { HandlebarsAPI } from './handlebars'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const packageDir = path.resolve(__dirname, '..'); + type Argv = { help?: boolean; dir?: string; @@ -93,9 +98,11 @@ function checkCancel(value: unknown) { * 5. Input: '/root/path/to/foo' * Output: folder -> `'/root/path/to/foo'` folder, `package.json#name` -> `foo` */ -function formatDir(input: string) { +function formatProjectName(input: string) { + const formatted = input.trim().replace(/\/+$/g, ''); return { - targetDir: input.trim().replace(/\/+$/g, ''), + packageName: input, + targetDir: formatted, }; } @@ -118,37 +125,6 @@ async function getAppTemplateName( return `${template}-ts`; } - let providerInfo: ProviderInfo = { - name: '', - entry: '', - }; - - if (roleType === 'consumer') { - const providerName = checkCancel( - await text({ - message: - 'Please input your provider name (You can skip by press "enter"):', - defaultValue: '', - }), - ); - - if (providerName) { - providerInfo.name = providerName; - - const providerEntry = checkCancel( - await text({ - message: `Please input your provider("${providerName}") entry:`, - validate(value) { - if (value.length === 0) { - return 'Entry is required'; - } - }, - }), - ); - providerInfo.entry = providerEntry; - } - } - return `${roleType}-${framework}-ts`; } @@ -187,7 +163,7 @@ async function getLibTemplateName({ template }: Argv) { return `${roleType}-${templateName}-ts`; } - return `${roleType}-${templateName}-[${Object.keys(tools)}]-ts`; + return `${roleType}-${templateName}-${tools[0]}-ts`; } function getTemplateName( @@ -263,7 +239,7 @@ async function forgeTemplate({ }, argv, ); - const material = new FsMaterial(__dirname); + const material = new FsMaterial(packageDir); const renderTemplate = async (templateDir: string) => { const templatePattern = `${templateDir}**/*`; @@ -331,24 +307,20 @@ export async function create({ const pkgInfo = pkgFromUserAgent(process.env['npm_config_user_agent']); const pkgManager = pkgInfo ? pkgInfo.name : 'npm'; - const mfName = - argv.dir ?? - checkCancel( - await text({ - message: 'Please input Module Federation name:', - placeholder: 'mf-project-name', - defaultValue: 'mf-project-name', - validate(value) { - if (value.length === 0) { - return 'Name is required'; - } - }, - }), - ); - - const dir = argv.dir || 'mf-project'; + const mfName = checkCancel( + await text({ + message: 'Please input Module Federation name:', + placeholder: 'mf_project_name', + defaultValue: 'mf_project_name', + validate(value) { + if (value.length === 0) { + return 'Name is required'; + } + }, + }), + ); - const { targetDir } = formatDir(dir); + const { targetDir } = formatProjectName(path.join(argv.dir || '', mfName)); const distFolder = path.isAbsolute(targetDir) ? targetDir : path.join(cwd, targetDir); diff --git a/packages/create-module-federation/src/handlebars/index.ts b/packages/create-module-federation/src/handlebars/index.ts index 871d0f4892..09e55cb41f 100644 --- a/packages/create-module-federation/src/handlebars/index.ts +++ b/packages/create-module-federation/src/handlebars/index.ts @@ -34,7 +34,9 @@ export class HandlebarsAPI { } await outputFs( target, - renderString(resourceValue.content, parameters), + templateResource.resourceKey.endsWith('.handlebars') + ? renderString(resourceValue.content, parameters) + : resourceValue.content, outputFilePath, { encoding: 'utf-8' }, ); diff --git a/packages/create-module-federation/src/index.ts b/packages/create-module-federation/src/index.ts index 165aa271a8..e934916c4b 100644 --- a/packages/create-module-federation/src/index.ts +++ b/packages/create-module-federation/src/index.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { create } from './create'; interface Template { diff --git a/packages/create-module-federation/templates/consumer-modern-ts/module-federation.config.ts.handlebars b/packages/create-module-federation/templates/consumer-modern-ts/module-federation.config.ts.handlebars index 776aa71a4d..28dbf654e4 100644 --- a/packages/create-module-federation/templates/consumer-modern-ts/module-federation.config.ts.handlebars +++ b/packages/create-module-federation/templates/consumer-modern-ts/module-federation.config.ts.handlebars @@ -3,7 +3,7 @@ import { createModuleFederationConfig } from '@module-federation/modern-js'; export default createModuleFederationConfig({ name: '{{mfName}}', remotes: { - 'provider': 'provider@http://localhost:8080/mf-manifest.json', + 'provider': 'rslib_provider@https://unpkg.com/module-federation-rslib-provider@latest/dist/mf/mf-manifest.json', }, shared: { react: { singleton: true }, diff --git a/packages/create-module-federation/templates/consumer-modern-ts/src/routes/page.tsx b/packages/create-module-federation/templates/consumer-modern-ts/src/routes/page.tsx index b197052740..68d8a4ff3a 100644 --- a/packages/create-module-federation/templates/consumer-modern-ts/src/routes/page.tsx +++ b/packages/create-module-federation/templates/consumer-modern-ts/src/routes/page.tsx @@ -1,6 +1,5 @@ import { Helmet } from '@modern-js/runtime/head'; import './index.css'; -import { ComponentInspector } from '../components/ComponentInspector'; import Header from 'provider/Header'; import Description from 'provider/Description'; import Footer from 'provider/Footer'; @@ -16,17 +15,9 @@ const Index = () => (
- -
- - - - - - - -
- +
+ +
); diff --git a/packages/create-module-federation/templates/consumer-rsbuild-ts/module-federation.config.ts.handlebars b/packages/create-module-federation/templates/consumer-rsbuild-ts/module-federation.config.ts.handlebars new file mode 100644 index 0000000000..51de1d0375 --- /dev/null +++ b/packages/create-module-federation/templates/consumer-rsbuild-ts/module-federation.config.ts.handlebars @@ -0,0 +1,12 @@ +import { createModuleFederationConfig } from '@module-federation/rsbuild-plugin'; + +export default createModuleFederationConfig({ + name: '{{mfName}}', + remotes: { + 'provider': 'rslib_provider@https://unpkg.com/module-federation-rslib-provider@latest/dist/mf/mf-manifest.json', + }, + shared: { + react: { singleton: true }, + 'react-dom': { singleton: true }, + }, +}); diff --git a/packages/create-module-federation/templates/consumer-rsbuild-ts/src/App.tsx b/packages/create-module-federation/templates/consumer-rsbuild-ts/src/App.tsx index 7932bce7d1..29fc3a5975 100644 --- a/packages/create-module-federation/templates/consumer-rsbuild-ts/src/App.tsx +++ b/packages/create-module-federation/templates/consumer-rsbuild-ts/src/App.tsx @@ -1,5 +1,4 @@ import './App.css'; -import { ComponentInspector } from './components/ComponentInspector'; import Header from 'provider/Header'; import Description from 'provider/Description'; import Footer from 'provider/Footer'; @@ -7,17 +6,9 @@ import Footer from 'provider/Footer'; const App = () => { return (
- -
- - - - - - - -
- +
+ +
); }; diff --git a/packages/create-module-federation/templates/modern-common/src/components/ComponentInspector.css b/packages/create-module-federation/templates/modern-common/src/components/ComponentInspector.css deleted file mode 100644 index da68e5015e..0000000000 --- a/packages/create-module-federation/templates/modern-common/src/components/ComponentInspector.css +++ /dev/null @@ -1,86 +0,0 @@ -.component-inspector { - position: relative; - display: inline-block; -} - -.inspector-info { - position: fixed; - z-index: 1000; - background: #1a1a1a; - padding: 4px 8px; - border-radius: 4px; - font-size: 12px; - color: #fff; - pointer-events: none; - display: flex; - align-items: center; - gap: 8px; -} - -.inspector-overlay { - position: fixed; - border-radius: 4px; - pointer-events: none; - z-index: 999; - background: - linear-gradient(90deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 0 0, - linear-gradient(90deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 0 100%, - linear-gradient(0deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 0 0, - linear-gradient(0deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 100% 0; - background-repeat: repeat-x, repeat-x, repeat-y, repeat-y; - background-size: - 200% 3px, - 200% 3px, - 3px 200%, - 3px 200%; /* 将边框从 2px 加粗到 3px */ - animation: borderRotate 4s linear infinite; -} - -@keyframes borderRotate { - 0% { - background-position: - 0% 0, - 0% 100%, - 0 0%, - 100% 0%; - } - 100% { - background-position: - 200% 0, - -200% 100%, - 0 -200%, - 100% 200%; - } -} -.mf-tag { - color: #646cff; - font-weight: 500; - position: relative; - padding-left: 16px; -} - -.mf-tag::before { - content: ''; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 12px; - height: 12px; - background-image: url('https://module-federation.io/svg.svg'); - background-repeat: no-repeat; - background-position: center; - background-size: contain; -} - -.divider { - color: #4a4a4a; -} - -.gradient-text { - background: linear-gradient(90deg, #60a5fa, #ec4899); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - font-weight: 500; -} diff --git a/packages/create-module-federation/templates/modern-common/src/components/ComponentInspector.tsx b/packages/create-module-federation/templates/modern-common/src/components/ComponentInspector.tsx deleted file mode 100644 index 50128edf47..0000000000 --- a/packages/create-module-federation/templates/modern-common/src/components/ComponentInspector.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { useState } from 'react'; -import './ComponentInspector.css'; - -interface InspectorInfo { - top: number; - left: number; - width: number; - height: number; -} - -export const ComponentInspector: React.FC<{ - children: React.ReactNode; - componentName: string; - mfName: string; -}> = ({ children, componentName, mfName }) => { - const [inspectorInfo, setInspectorInfo] = useState( - null, - ); - - const handleMouseEnter = (e: React.MouseEvent) => { - const rect = e.currentTarget.getBoundingClientRect(); - setInspectorInfo({ - top: rect.top, - left: rect.left, - width: rect.width, - height: rect.height, - }); - }; - - const handleMouseLeave = () => { - setInspectorInfo(null); - }; - - return ( -
- {children} - {inspectorInfo && ( - <> -
- {mfName} - | - {componentName} -
-
- - )} -
- ); -}; diff --git a/packages/create-module-federation/templates/modern-common/tsconfig.json b/packages/create-module-federation/templates/modern-common/tsconfig.json index ce7f951eef..26ef0ff030 100644 --- a/packages/create-module-federation/templates/modern-common/tsconfig.json +++ b/packages/create-module-federation/templates/modern-common/tsconfig.json @@ -6,7 +6,8 @@ "baseUrl": "./", "paths": { "@/*": ["./src/*"], - "@shared/*": ["./shared/*"] + "@shared/*": ["./shared/*"], + "*": ["./@mf-types/*"] } }, "include": ["src", "shared", "config", "modern.config.ts"], diff --git a/packages/create-module-federation/templates/provider-modern-ts/src/routes/page.tsx b/packages/create-module-federation/templates/provider-modern-ts/src/routes/page.tsx index 18bbf92c26..862fa4f73c 100644 --- a/packages/create-module-federation/templates/provider-modern-ts/src/routes/page.tsx +++ b/packages/create-module-federation/templates/provider-modern-ts/src/routes/page.tsx @@ -1,6 +1,5 @@ import { Helmet } from '@modern-js/runtime/head'; import './index.css'; -import { ComponentInspector } from '../components/ComponentInspector'; import Header from '../components/Header'; import Description from '../components/Description'; import Footer from '../components/Footer'; @@ -16,17 +15,9 @@ const Index = () => (
- -
- - - - - - - -
- +
+ +
); diff --git a/packages/create-module-federation/templates/provider-rsbuild-ts/src/App.tsx b/packages/create-module-federation/templates/provider-rsbuild-ts/src/App.tsx index fbd2f7a18e..efeaaa0cbf 100644 --- a/packages/create-module-federation/templates/provider-rsbuild-ts/src/App.tsx +++ b/packages/create-module-federation/templates/provider-rsbuild-ts/src/App.tsx @@ -1,5 +1,4 @@ import './App.css'; -import { ComponentInspector } from './components/ComponentInspector'; import Header from './components/Header'; import Description from './components/Description'; import Footer from './components/Footer'; @@ -7,17 +6,9 @@ import Footer from './components/Footer'; const App = () => { return (
- -
- - - - - - - -
- +
+ +
); }; diff --git a/packages/create-module-federation/templates/provider-rslib-storybook-ts/.gitignore b/packages/create-module-federation/templates/provider-rslib-storybook-ts/.gitignore new file mode 100644 index 0000000000..c5f1042988 --- /dev/null +++ b/packages/create-module-federation/templates/provider-rslib-storybook-ts/.gitignore @@ -0,0 +1,16 @@ +# Local +.DS_Store +*.local +*.log* + +# Dist +node_modules +dist/ + +# IDE +.vscode/* +!.vscode/extensions.json +.idea + +# Storybook dist +storybook-static/ diff --git a/packages/create-module-federation/templates/provider-rslib-storybook-ts/package.json.handlebars b/packages/create-module-federation/templates/provider-rslib-storybook-ts/package.json.handlebars index 4d5eced7ab..aa90a07f55 100644 --- a/packages/create-module-federation/templates/provider-rslib-storybook-ts/package.json.handlebars +++ b/packages/create-module-federation/templates/provider-rslib-storybook-ts/package.json.handlebars @@ -15,17 +15,32 @@ ], "scripts": { "build": "rslib build", + "build:storybook": "storybook build", "dev": "rslib build --watch", + "storybook": "storybook dev -p 6006", "mf-dev": "rslib mf-dev" }, "devDependencies": { "@rsbuild/core": "1.2.0-beta.0", "@rsbuild/plugin-react": "^1.1.0", "@rslib/core": "^0.3.1", - "@types/react": "^19.0.4", - "react": "^19.0.0", + "@storybook/addon-essentials": "^8.4.7", + "@storybook/addon-interactions": "^8.4.7", + "@storybook/addon-links": "^8.4.7", + "@storybook/addon-onboarding": "^8.4.7", + "@storybook/blocks": "^8.4.7", + "@storybook/react": "^8.4.7", + "@storybook/test": "^8.4.7", + "@types/react": "^18.3.11", + "@types/react-dom": "~18.3.1", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "storybook": "^8.4.7", + "storybook-addon-rslib": "^0.1.7", + "storybook-react-rsbuild": "^0.1.7", "typescript": "^5.7.3", - "@module-federation/rsbuild-plugin":"^0.8.9" + "@module-federation/rsbuild-plugin":"^0.8.9", + "@module-federation/storybook-addon":"^4.0.1" }, "peerDependencies": { "react": ">=16.9.0", diff --git a/packages/create-module-federation/templates/lib-common/.gitignore b/packages/create-module-federation/templates/provider-rslib-ts/.gitignore similarity index 100% rename from packages/create-module-federation/templates/lib-common/.gitignore rename to packages/create-module-federation/templates/provider-rslib-ts/.gitignore diff --git a/packages/create-module-federation/templates/provider-rslib-ts/package.json.handlebars b/packages/create-module-federation/templates/provider-rslib-ts/package.json.handlebars index 0b45bb1981..0391fdb6a3 100644 --- a/packages/create-module-federation/templates/provider-rslib-ts/package.json.handlebars +++ b/packages/create-module-federation/templates/provider-rslib-ts/package.json.handlebars @@ -15,31 +15,17 @@ ], "scripts": { "build": "rslib build", - "build:storybook": "storybook build", "dev": "rslib build --watch", - "storybook": "storybook dev -p 6006", "mf-dev": "rslib mf-dev" }, "devDependencies": { "@rsbuild/core": "1.2.0-beta.0", "@rsbuild/plugin-react": "^1.1.0", "@rslib/core": "^0.3.1", - "@storybook/addon-essentials": "^8.4.7", - "@storybook/addon-interactions": "^8.4.7", - "@storybook/addon-links": "^8.4.7", - "@storybook/addon-onboarding": "^8.4.7", - "@storybook/blocks": "^8.4.7", - "@storybook/react": "^8.4.7", - "@storybook/test": "^8.4.7", - "@types/react": "^19.0.4", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "storybook": "^8.4.7", - "storybook-addon-rslib": "^0.1.7", - "storybook-react-rsbuild": "^0.1.7", + "@types/react": "^18.3.11", + "react": "^18.3.1", "typescript": "^5.7.3", "@module-federation/rsbuild-plugin":"^0.8.9", - "@module-federation/storybook-addon":"^4.0.1" }, "peerDependencies": { "react": ">=16.9.0", diff --git a/packages/create-module-federation/templates/rsbuild-common/src/components/ComponentInspector.css b/packages/create-module-federation/templates/rsbuild-common/src/components/ComponentInspector.css deleted file mode 100644 index da68e5015e..0000000000 --- a/packages/create-module-federation/templates/rsbuild-common/src/components/ComponentInspector.css +++ /dev/null @@ -1,86 +0,0 @@ -.component-inspector { - position: relative; - display: inline-block; -} - -.inspector-info { - position: fixed; - z-index: 1000; - background: #1a1a1a; - padding: 4px 8px; - border-radius: 4px; - font-size: 12px; - color: #fff; - pointer-events: none; - display: flex; - align-items: center; - gap: 8px; -} - -.inspector-overlay { - position: fixed; - border-radius: 4px; - pointer-events: none; - z-index: 999; - background: - linear-gradient(90deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 0 0, - linear-gradient(90deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 0 100%, - linear-gradient(0deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 0 0, - linear-gradient(0deg, #3b82f6 0%, #ec4899 50%, #3b82f6 100%) 100% 0; - background-repeat: repeat-x, repeat-x, repeat-y, repeat-y; - background-size: - 200% 3px, - 200% 3px, - 3px 200%, - 3px 200%; /* 将边框从 2px 加粗到 3px */ - animation: borderRotate 4s linear infinite; -} - -@keyframes borderRotate { - 0% { - background-position: - 0% 0, - 0% 100%, - 0 0%, - 100% 0%; - } - 100% { - background-position: - 200% 0, - -200% 100%, - 0 -200%, - 100% 200%; - } -} -.mf-tag { - color: #646cff; - font-weight: 500; - position: relative; - padding-left: 16px; -} - -.mf-tag::before { - content: ''; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 12px; - height: 12px; - background-image: url('https://module-federation.io/svg.svg'); - background-repeat: no-repeat; - background-position: center; - background-size: contain; -} - -.divider { - color: #4a4a4a; -} - -.gradient-text { - background: linear-gradient(90deg, #60a5fa, #ec4899); - -webkit-background-clip: text; - background-clip: text; - -webkit-text-fill-color: transparent; - font-weight: 500; -} diff --git a/packages/create-module-federation/templates/rsbuild-common/src/components/ComponentInspector.tsx b/packages/create-module-federation/templates/rsbuild-common/src/components/ComponentInspector.tsx deleted file mode 100644 index 50128edf47..0000000000 --- a/packages/create-module-federation/templates/rsbuild-common/src/components/ComponentInspector.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { useState } from 'react'; -import './ComponentInspector.css'; - -interface InspectorInfo { - top: number; - left: number; - width: number; - height: number; -} - -export const ComponentInspector: React.FC<{ - children: React.ReactNode; - componentName: string; - mfName: string; -}> = ({ children, componentName, mfName }) => { - const [inspectorInfo, setInspectorInfo] = useState( - null, - ); - - const handleMouseEnter = (e: React.MouseEvent) => { - const rect = e.currentTarget.getBoundingClientRect(); - setInspectorInfo({ - top: rect.top, - left: rect.left, - width: rect.width, - height: rect.height, - }); - }; - - const handleMouseLeave = () => { - setInspectorInfo(null); - }; - - return ( -
- {children} - {inspectorInfo && ( - <> -
- {mfName} - | - {componentName} -
-
- - )} -
- ); -}; diff --git a/packages/create-module-federation/tsconfig.json b/packages/create-module-federation/tsconfig.json index 2cd74a5bff..56e67fa0f0 100644 --- a/packages/create-module-federation/tsconfig.json +++ b/packages/create-module-federation/tsconfig.json @@ -3,13 +3,13 @@ "compilerOptions": { "lib": ["DOM", "ESNext"], "target": "ES2020", - "module": "Node16", + "module": "ESNext", + "moduleResolution": "Bundler", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noFallthroughCasesInSwitch": true, - "moduleResolution": "node16", "resolveJsonModule": true, "esModuleInterop": true, "skipLibCheck": true,