Skip to content

feat(nf): Angular i18n support #627

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e4e1976
feat(i18n): exposed entries built by ng application internal
refactorTractor Feb 1, 2024
8acf3c4
chore(beautify): this automatically modified indentations
refactorTractor Feb 1, 2024
b085958
feat(i18n): ng adapter writes files, maps exposed files, registers 4 …
refactorTractor Feb 2, 2024
cba5171
feat(i18n): update all index.html-s
refactorTractor Feb 2, 2024
d8af33d
feat(i18n): preparing bundle, correct external handling
refactorTractor Feb 2, 2024
83281e7
beautify: whitespaces
refactorTractor Feb 2, 2024
1383f6e
feat(i18n) fixing up mistakes, whitespaces w/out package changes
refactorTractor Feb 5, 2024
1234e24
stylistic changes
refactorTractor Feb 5, 2024
ba042a2
feat(i18n): fix serving locale root
refactorTractor Feb 7, 2024
52402e6
feat(i18n): fix finding and writing locales, fix hash handling, inden…
refactorTractor Feb 7, 2024
f7f7a49
feat(i18n): no polyfills from middleware, put vite entries in remoteE…
refactorTractor Feb 9, 2024
ca71726
feat(i18n): stylistic changes
refactorTractor Feb 9, 2024
958492b
feat(i18n): add localize package, stylistic changes
refactorTractor Feb 9, 2024
bba5054
feat(i18n): stylistic changes
refactorTractor Feb 9, 2024
03544d5
feat(i18n): should still work without localization
refactorTractor Feb 12, 2024
62eaf63
feat(i18n): NG0203 comes if ng version < 17.1.0
refactorTractor Feb 12, 2024
8f1123f
feat(i18n): stylistic changes
refactorTractor Feb 12, 2024
38cec49
Merge branch 'main' into i18n_application_adapter
refactorTractor Feb 12, 2024
cd39f77
prepare schematic to work as a fork. + whitespace formatting
refactorTractor Aug 16, 2024
cb01557
fixes
refactorTractor Aug 16, 2024
d93331e
make remoteEntry outside language bundles reference the languages to …
refactorTractor Aug 16, 2024
2a64fdb
added pathmappings
refactorTractor Aug 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions libs/native-federation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,5 @@
"mrmime": "^1.0.1",
"npmlog": "^6.0.2",
"process": "0.11.10"
},
"peerDependencies": {}
}
}
92 changes: 29 additions & 63 deletions libs/native-federation/src/builders/build/builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import * as path from 'path';
import * as fs from 'fs';
import * as mrmime from 'mrmime';

import {
BuilderContext,
Expand Down Expand Up @@ -37,7 +35,6 @@ import {
startServer,
} from '../../utils/dev-server';
import { RebuildHubs } from '../../utils/rebuild-events';
import { updateIndexHtml, updateScriptTags } from '../../utils/updateIndexHtml';
import { existsSync, mkdirSync, rmSync } from 'fs';
import {
EsBuildResult,
Expand All @@ -46,9 +43,11 @@ import {
} from '../../utils/mem-resuts';
import { JsonObject } from '@angular-devkit/core';
import { createSharedMappingsPlugin } from '../../utils/shared-mappings-plugin';
import { Connect } from 'vite';
import { PluginBuild } from 'esbuild';
import { FederationInfo } from '@softarc/native-federation-runtime';
import { prepareBundles } from '../../utils/prepare-bundles';
import { updateScriptTags } from '../../utils/updateIndexHtml';
import { createI18nOptions } from '@angular-devkit/build-angular/src/utils/i18n-options';
import { getFederationFilesMiddleware } from '../../utils/federation-files-middleware';

export async function* runBuilder(
nfOptions: NfBuilderSchema,
Expand Down Expand Up @@ -103,6 +102,8 @@ export async function* runBuilder(
options = (await context.validateOptions(_options, builder)) as JsonObject &
Schema;
}
const metadata = await context.getProjectMetadata(context.target.project);
const i18nOpts = createI18nOptions(metadata, options.localize);

const runServer = !!nfOptions.port;
const write = !runServer;
Expand All @@ -116,7 +117,7 @@ export async function* runBuilder(

setLogLevel(options.verbose ? 'verbose' : 'info');

const outputPath = path.join(options.outputPath, 'browser');
const outputPath = path.join(options.outputPath as string, 'browser');

const fedOptions: FederationOptions = {
workspaceRoot: context.workspaceRoot,
Expand All @@ -143,32 +144,8 @@ export async function* runBuilder(
},
},
];

const middleware: Connect.NextHandleFunction[] = [
(req, res, next) => {
const fileName = path.join(
fedOptions.workspaceRoot,
fedOptions.outputPath,
req.url
);
const exists = fs.existsSync(fileName);

if (req.url !== '/' && req.url !== '' && exists) {
const lookup = mrmime.lookup;
const mimeType = lookup(path.extname(fileName)) || 'text/javascript';
const rawBody = fs.readFileSync(fileName, 'utf-8');
const body = addDebugInformation(req.url, rawBody);
res.writeHead(200, {
'Content-Type': mimeType,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type',
});
res.end(body);
} else {
next();
}
},
const middleware = [
getFederationFilesMiddleware(fedOptions, i18nOpts, nfOptions.pathMappings),
];

const memResults = new MemResults();
Expand Down Expand Up @@ -204,9 +181,11 @@ export async function* runBuilder(
normOuterOptions,
appBuilderName,
context,
nfOptions.skipHtmlTransform ? {} : {
indexHtml: transformIndexHtml,
},
nfOptions.skipHtmlTransform
? {}
: {
indexHtml: transformIndexHtml,
},
{
buildPlugins: plugins,
middleware,
Expand All @@ -220,8 +199,12 @@ export async function* runBuilder(

if (!output.success) {
setError('Compilation Error');
reloadBrowser();
continue;
if (nfOptions.dev) {
reloadBrowser();
continue;
} else {
yield output;
}
} else {
setError(null);
}
Expand All @@ -236,12 +219,17 @@ export async function* runBuilder(
);
}

if (write && !nfOptions.dev && !nfOptions.skipHtmlTransform) {
updateIndexHtml(fedOptions);
}
prepareBundles(
options,
fedOptions,
i18nOpts,
output,
write && !nfOptions.dev && !nfOptions.skipHtmlTransform,
memResults
);

if (first && runServer) {
startServer(nfOptions, options.outputPath, memResults);
startServer(nfOptions, options.outputPath as string, memResults);
}

if (!first && runServer) {
Expand Down Expand Up @@ -284,25 +272,3 @@ function infereConfigPath(tsConfig: string): string {
function transformIndexHtml(content: string): Promise<string> {
return Promise.resolve(updateScriptTags(content, 'main.js', 'polyfills.js'));
}

function addDebugInformation(fileName: string, rawBody: string): string {
if (fileName !== '/remoteEntry.json') {
return rawBody;
}

const remoteEntry = JSON.parse(rawBody) as FederationInfo;
const shared = remoteEntry.shared;

if (!shared) {
return rawBody;
}

const sharedForVite = shared.map((s) => ({
...s,
packageName: `/@id/${s.packageName}`,
}));

remoteEntry.shared = [...shared, ...sharedForVite];

return JSON.stringify(remoteEntry, null, 2);
}
1 change: 1 addition & 0 deletions libs/native-federation/src/builders/build/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export interface NfBuilderSchema extends JsonObject {
shell: string;
watch: boolean;
skipHtmlTransform: boolean;
pathMappings?: [string, string][];
} // eslint-disable-line
13 changes: 13 additions & 0 deletions libs/native-federation/src/builders/build/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@
"skipHtmlTransform": {
"type": "boolean",
"default": false
},
"pathMappings": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string",
"minItems": 2,
"maxItems": 2
}
},
"description": "In case baseHref doesn't match nicely to the Angular i18n folder structure you can provide a list of tuples that contain Regex string and a replacement string values. These will map the url's path part to physical location relative to the outputPath. First match applies.",
"default": null
}
}
}
15 changes: 11 additions & 4 deletions libs/native-federation/src/schematics/init/schematic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ export default function config(options: MfSchematicSchema): Rule {
version: '^1.5.12',
overwrite: false,
});
addPackageJsonDependency(tree, {
name: '@softarc/native-federation-runtime',
type: NodeDependencyType.Default,
version: '2.0.8',
overwrite: false,
});

context.addTask(new NodePackageInstallTask());

Expand Down Expand Up @@ -278,7 +284,8 @@ function generateRemoteMap(workspace: any, projectName: string) {
project?.architect?.serve &&
project?.architect?.build
) {
const pPort = project.architect['serve-original']?.options?.port ??
const pPort =
project.architect['serve-original']?.options?.port ??
project.architect.serve?.options?.port ??
4200;
result[
Expand Down Expand Up @@ -313,7 +320,7 @@ function makeMainAsync(

let newMainContent = '';
if (options.type === 'dynamic-host') {
newMainContent = `import { initFederation } from '@angular-architects/native-federation';
newMainContent = `import { initFederation } from '@softarc/native-federation-runtime';

initFederation('/assets/federation.manifest.json')
.catch(err => console.error(err))
Expand All @@ -322,15 +329,15 @@ initFederation('/assets/federation.manifest.json')
`;
} else if (options.type === 'host') {
const manifest = JSON.stringify(remoteMap, null, 2).replace(/"/g, "'");
newMainContent = `import { initFederation } from '@angular-architects/native-federation';
newMainContent = `import { initFederation } from '@softarc/native-federation-runtime';

initFederation(${manifest})
.catch(err => console.error(err))
.then(_ => import('./bootstrap'))
.catch(err => console.error(err));
`;
} else {
newMainContent = `import { initFederation } from '@angular-architects/native-federation';
newMainContent = `import { initFederation } from '@softarc/native-federation-runtime';

initFederation()
.catch(err => console.error(err))
Expand Down
Loading