Skip to content

Commit 0187e67

Browse files
AdministratorAdministrator
authored andcommitted
Create nx native federation plugin for dashboard-example
1 parent 93f29bd commit 0187e67

File tree

16 files changed

+433
-0
lines changed

16 files changed

+433
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7+
"rules": {}
8+
},
9+
{
10+
"files": ["*.ts", "*.tsx"],
11+
"rules": {}
12+
},
13+
{
14+
"files": ["*.js", "*.jsx"],
15+
"rules": {}
16+
},
17+
{
18+
"files": ["./package.json", "./executors.json"],
19+
"parser": "jsonc-eslint-parser",
20+
"rules": {
21+
"@nrwl/nx/nx-plugin-checks": "error"
22+
}
23+
}
24+
]
25+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# native-federation-plugin
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Building
6+
7+
Run `nx build native-federation-plugin` to build the library.
8+
9+
## Running unit tests
10+
11+
Run `nx test native-federation-plugin` to execute the unit tests via [Jest](https://jestjs.io).
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"$schema": "http://json-schema.org/schema",
3+
"executors": {
4+
"build": {
5+
"implementation": "./src/executors/build/executor",
6+
"schema": "./src/executors/build/schema.json",
7+
"description": "build executor"
8+
}
9+
}
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: "native-federation-plugin",
4+
preset: "../../jest.preset.js",
5+
globals: {
6+
"ts-jest": {
7+
tsconfig: "<rootDir>/tsconfig.spec.json",
8+
},
9+
},
10+
transform: {
11+
"^.+\\.[tj]s$": "ts-jest",
12+
},
13+
moduleFileExtensions: ["ts", "js", "html"],
14+
coverageDirectory: "../../coverage/libs/native-federation-plugin",
15+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "native-federation-plugin",
3+
"version": "0.0.1",
4+
"main": "src/index.js",
5+
"executors": "./executors.json"
6+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
3+
"sourceRoot": "libs/native-federation-plugin/src",
4+
"projectType": "library",
5+
"targets": {
6+
"build": {
7+
"executor": "@nrwl/js:tsc",
8+
"outputs": ["{options.outputPath}"],
9+
"options": {
10+
"outputPath": "dist/libs/native-federation-plugin",
11+
"main": "libs/native-federation-plugin/src/index.ts",
12+
"tsConfig": "libs/native-federation-plugin/tsconfig.lib.json",
13+
"assets": [
14+
"libs/native-federation-plugin/*.md",
15+
{
16+
"input": "./libs/native-federation-plugin/src",
17+
"glob": "**/!(*.ts)",
18+
"output": "./src"
19+
},
20+
{
21+
"input": "./libs/native-federation-plugin/src",
22+
"glob": "**/*.d.ts",
23+
"output": "./src"
24+
},
25+
{
26+
"input": "./libs/native-federation-plugin",
27+
"glob": "executors.json",
28+
"output": "."
29+
}
30+
]
31+
}
32+
},
33+
"lint": {
34+
"executor": "@nrwl/linter:eslint",
35+
"outputs": ["{options.outputFile}"],
36+
"options": {
37+
"lintFilePatterns": [
38+
"libs/native-federation-plugin/**/*.ts",
39+
"libs/native-federation-plugin/executors.json",
40+
"libs/native-federation-plugin/package.json"
41+
]
42+
}
43+
},
44+
"test": {
45+
"executor": "@nrwl/jest:jest",
46+
"outputs": ["coverage/libs/native-federation-plugin"],
47+
"options": {
48+
"jestConfig": "libs/native-federation-plugin/jest.config.ts",
49+
"passWithNoTests": true
50+
}
51+
}
52+
},
53+
"tags": []
54+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import * as esbuild from "esbuild";
2+
import * as path from "path";
3+
import * as fs from "fs";
4+
import { federationBuilder } from "@softarc/native-federation/build";
5+
import { esBuildAdapter } from "@softarc/native-federation-esbuild";
6+
import { NFPWorkspacePaths } from "./interface";
7+
8+
/**
9+
*
10+
*/
11+
function getWorkspacePaths(
12+
workspaceRootPath: string,
13+
projectName: string
14+
): NFPWorkspacePaths {
15+
const projectPath = path.join(workspaceRootPath, `./apps/${projectName}`);
16+
const projectSrcPath = path.join(projectPath, `./src`);
17+
18+
return {
19+
workspaceRootPath,
20+
workspaceDistPath: `dist/${projectName}`,
21+
workspaceTsConfigPath: `tsconfig.json`,
22+
projectPath,
23+
projectSrcPath,
24+
projectEntryPath: path.join(projectSrcPath, "./app/index.ts"),
25+
projectFederationConfigPath: `apps/${projectName}/federation.config.js`,
26+
};
27+
}
28+
29+
/**
30+
*
31+
*/
32+
async function setupNativeFederationBuilder(workspace: NFPWorkspacePaths) {
33+
await federationBuilder.init({
34+
options: {
35+
workspaceRoot: workspace.workspaceRootPath,
36+
outputPath: workspace.workspaceDistPath,
37+
tsConfig: workspace.workspaceTsConfigPath,
38+
federationConfig: workspace.projectFederationConfigPath,
39+
verbose: false,
40+
},
41+
adapter: esBuildAdapter,
42+
});
43+
}
44+
45+
/**
46+
*
47+
*/
48+
async function compileProjectEntryFileByEsbuild(workspace: NFPWorkspacePaths) {
49+
const { workspaceDistPath, workspaceTsConfigPath, projectEntryPath } =
50+
workspace;
51+
52+
fs.rmSync(workspaceDistPath, { force: true, recursive: true });
53+
54+
await esbuild.build({
55+
entryPoints: [projectEntryPath],
56+
external: federationBuilder.externals,
57+
outdir: workspaceDistPath,
58+
bundle: true,
59+
platform: "browser",
60+
format: "esm",
61+
mainFields: ["es2020", "browser", "module", "main"],
62+
conditions: ["es2020", "es2015", "module"],
63+
resolveExtensions: [".ts", ".tsx", ".mjs", ".js"],
64+
tsconfig: workspaceTsConfigPath,
65+
splitting: true,
66+
// plugins: [ commonjs() ]
67+
});
68+
}
69+
70+
/**
71+
*
72+
*/
73+
function copyProjectIndexHtml(workspace: NFPWorkspacePaths) {
74+
const { workspaceDistPath, projectSrcPath } = workspace;
75+
const indexHtmlFromPath = path.join(projectSrcPath, "./index.html");
76+
const indexHtmlToPath = path.join(workspaceDistPath, "./index.html");
77+
78+
const faviconIcoFromPath = path.join(projectSrcPath, "./favicon.ico");
79+
const faviconIcoToPath = path.join(workspaceDistPath, "./favicon.ico");
80+
81+
fs.copyFileSync(indexHtmlFromPath, indexHtmlToPath);
82+
fs.copyFileSync(faviconIcoFromPath, faviconIcoToPath);
83+
}
84+
85+
/**
86+
* Main function
87+
*/
88+
export async function executeBuild(
89+
workspaceRootPath: string,
90+
projectName: string
91+
) {
92+
const workspace: NFPWorkspacePaths = getWorkspacePaths(
93+
workspaceRootPath,
94+
projectName
95+
);
96+
97+
await setupNativeFederationBuilder(workspace);
98+
99+
await compileProjectEntryFileByEsbuild(workspace);
100+
101+
copyProjectIndexHtml(workspace);
102+
103+
await federationBuilder.build();
104+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { NativeFederationBuildExecutorOptions } from "./schema";
2+
//import { ExecutorContext } from '@nrwl/devkit';
3+
4+
import executor from "./executor";
5+
6+
const options: NativeFederationBuildExecutorOptions = {
7+
baseUrl: "http://localhost:3000/",
8+
};
9+
10+
describe("Build Executor", () => {
11+
it("can run", async () => {
12+
const output = await executor(options, null);
13+
expect(output.success).toBe(true);
14+
});
15+
});
16+
17+
/*fterAll((done) => {
18+
done();
19+
});*/
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import * as fs from "fs";
2+
import * as path from "path";
3+
import { promisify } from "util";
4+
import { exec } from "child_process";
5+
import { ExecutorContext } from "@nrwl/devkit";
6+
import { NativeFederationBuildExecutorOptions } from "./schema";
7+
8+
/**
9+
*
10+
*/
11+
const NATIVE_FEDERATION_BUILDER_NAME = (name: string): string => {
12+
return `nfp-${name}-builder`;
13+
};
14+
15+
/**
16+
*
17+
*/
18+
function createProjectBuilderTsFile(
19+
workspaceRootPath: string,
20+
workspaceDistPath: string,
21+
projectName: string
22+
) {
23+
const builderOutputFile = path.join(
24+
workspaceDistPath,
25+
`./${NATIVE_FEDERATION_BUILDER_NAME(projectName)}.ts`
26+
);
27+
const builderTypescript = `
28+
import { executeBuild } from './build';
29+
executeBuild('${workspaceRootPath}', '${projectName}');
30+
`;
31+
32+
fs.mkdirSync(workspaceDistPath, { recursive: true });
33+
fs.writeFileSync(builderOutputFile, builderTypescript, {
34+
encoding: "utf8",
35+
flag: "w",
36+
});
37+
}
38+
39+
/**
40+
*
41+
*/
42+
function removeProjectBuilderTsFile(
43+
workspaceDistPath: string,
44+
projectName: string
45+
) {
46+
const builderOutputFile = path.join(
47+
workspaceDistPath,
48+
`./${NATIVE_FEDERATION_BUILDER_NAME(projectName)}.ts`
49+
);
50+
51+
try {
52+
fs.unlinkSync(builderOutputFile);
53+
} catch (e) {
54+
throw e;
55+
}
56+
}
57+
58+
/**
59+
*
60+
*/
61+
async function compileCommonBuilderTsFile(
62+
workspaceDistPath: string
63+
): Promise<{ stdout: string; stderr: string }> {
64+
const builderSourceFile = path.join(__dirname, "./build.ts");
65+
const bundleCommand = `
66+
npx tsc --skipLibCheck ${builderSourceFile} --outDir ${workspaceDistPath}
67+
`;
68+
69+
return promisify(exec)(bundleCommand);
70+
}
71+
72+
/**
73+
*
74+
*/
75+
async function compileAndRunProjectBuilderFiles(
76+
workspaceDistPath: string,
77+
projectName: string
78+
): Promise<{ stdout: string; stderr: string }> {
79+
const builderOutputFile = path.join(
80+
workspaceDistPath,
81+
`./${NATIVE_FEDERATION_BUILDER_NAME(projectName)}.ts`
82+
);
83+
const builderOutputJsFile = path.join(
84+
workspaceDistPath,
85+
`./${NATIVE_FEDERATION_BUILDER_NAME(projectName)}.js`
86+
);
87+
const bundleAndRunCommand = `
88+
npx tsc --skipLibCheck ${builderOutputFile} --outDir ${workspaceDistPath} && node ${builderOutputJsFile}
89+
`;
90+
91+
return promisify(exec)(bundleAndRunCommand);
92+
}
93+
94+
/**
95+
*
96+
*/
97+
function onRunExecutorError(error) {
98+
console.error(error.stderr);
99+
return { success: false };
100+
}
101+
102+
/**
103+
* Main function
104+
*/
105+
export default async function runExecutor(
106+
options: NativeFederationBuildExecutorOptions,
107+
context: ExecutorContext
108+
): Promise<{ success: boolean }> {
109+
const { root: workspaceRootPath, projectName } = context;
110+
const workspaceDistPath = path.join(workspaceRootPath, `./dist`);
111+
112+
try {
113+
await compileCommonBuilderTsFile(workspaceDistPath);
114+
} catch (e) {
115+
return onRunExecutorError(e);
116+
}
117+
118+
createProjectBuilderTsFile(workspaceRootPath, workspaceDistPath, projectName);
119+
120+
try {
121+
await compileAndRunProjectBuilderFiles(workspaceDistPath, projectName);
122+
removeProjectBuilderTsFile(workspaceDistPath, projectName);
123+
} catch (e) {
124+
return onRunExecutorError(e);
125+
}
126+
127+
return { success: true };
128+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface NFPWorkspacePaths {
2+
workspaceRootPath: string;
3+
workspaceDistPath: string;
4+
workspaceTsConfigPath: string;
5+
projectPath: string;
6+
projectSrcPath: string;
7+
projectEntryPath: string;
8+
projectFederationConfigPath: string;
9+
}

0 commit comments

Comments
 (0)