Skip to content

Commit

Permalink
feat(nf): add hash to generated bundles
Browse files Browse the repository at this point in the history
  • Loading branch information
manfredsteyer committed Aug 7, 2024
1 parent da7180d commit 655a658
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 121 deletions.
22 changes: 18 additions & 4 deletions libs/native-federation-core/src/lib/core/bundle-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { FederationOptions } from './federation-options';
import { copySrcMapIfExists } from '../utils/copy-src-map-if-exists';
import { logger } from '../utils/logger';
import { normalize } from '../utils/normalize';
import crypto from 'crypto';

export async function bundleShared(
config: NormalizedFederationConfig,
Expand All @@ -32,11 +33,24 @@ export async function bundleShared(

const allEntryPoints = packageInfos.map((pi) => {
const encName = pi.packageName.replace(/[^A-Za-z0-9]/g, '_');
const encVersion = pi.version.replace(/[^A-Za-z0-9]/g, '_');

// const encVersion = pi.version.replace(/[^A-Za-z0-9]/g, '_');

// const outName = fedOptions.dev
// ? `${encName}-${encVersion}-dev.js`
// : `${encName}-${encVersion}.js`;

const hashBase = pi.version + '_' + pi.entryPoint;
const hash = crypto.createHash('sha256')
.update(hashBase)
.digest('base64')
.replace(/\//g, '_')
.replace(/\+/g, '-')
.replace(/=/g, '')
.substring(0,10);

const outName = fedOptions.dev
? `${encName}-${encVersion}-dev.js`
: `${encName}-${encVersion}.js`;
? `${encName}.${hash}-dev.js`
: `${encName}.${hash}.js`;

return { fileName: pi.entryPoint, outName };
});
Expand Down
2 changes: 1 addition & 1 deletion libs/native-federation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ We will at least provide a new version of this package per Angular major. If nec

## Migration from Module Federation

If you currently use Angular with Module Federation, you can follow our Migration Guide to migrate to Native Federation and Angular's new fast esbuild-based build system.
If you currently use Angular with Module Federation, you can follow our [Migration Guide](https://github.com/angular-architects/module-federation-plugin/blob/main/libs/native-federation/docs/migrate.md) to migrate to Native Federation and Angular's new fast esbuild-based build system.

## Updates

Expand Down
233 changes: 117 additions & 116 deletions libs/native-federation/docs/migrate.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,154 +12,155 @@ Native Federation for Angular is a thin wrapper around the esbuild builder that
- Update your solution to the newest version of `@angular-architects/module-federation` (!)
- Have a look to our [FAQs about sharing packages with Native Federation](share-faq.md)

In general, you need Native Federation for Angular 18.1 and Module Federation 18.x.

## Migration for Angular CLI projects

1. Remove Module Federation from your poject(s):

```
ng g @angular-architects/module-federation:remove --project xyz
```
```
ng g @angular-architects/module-federation:remove --project xyz
```

2. Update your workspace to the new esbuild-based build system:

```
ng update @angular/cli --name use-application-builder
```
```
ng update @angular/cli --name use-application-builder
```

3. Initialize Native Federation for your projects:

```
ng add @angular-architects/native-federation --project xyz --type remote --port 4201
```
```
ng add @angular-architects/native-federation --project xyz --type remote --port 4201
```

**Remarks:** Use type `remote` or type `dynamic-host`.
**Remarks:** Use type `remote` or type `dynamic-host`.

4. Adjust your `federation.config.js` generated for Native Federation. You can mostly copy over the settings from your `webpack.config.js` used for Module Federation before.

5. Update your EcmaScript imports in your source code. Make sure, you import from `@angular-architects/native-federation` instead of from `@angular-architects/module-federation`. Please also note that the signature of `loadRemoteModule` has been simplified:

```typescript
// Before
import { loadRemoteModule } from '@angular-architects/module-federation';

[...]

export const APP_ROUTES: Routes = [
[...]
{
path: 'booking',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:4201/remoteEntry.js',
exposedModule: './routes'
})
.then(m => m.MFE1_ROUTES)
},
[...]
];
```

```typescript
// After
import { loadRemoteModule } from '@angular-architects/native-federation';
[...]
export const APP_ROUTES: Routes = [
[...]
{
path: 'flights',
loadComponent: () => loadRemoteModule('mfe1', './Component')
.then((m) => m.AppComponent),
},
[...]
];
```

Please also note that loadRemoteModule now always points to a logical name that is resolved via the shell's federation manifest (`src/assets/federation.manifest.json` or `public/federation.manifest.json`):

```json
{
"mfe1": "http://localhost:4201/remoteEntry.json"
}
```

Please also note that the remoteEntry is now a `.json` file.
```typescript
// Before
import { loadRemoteModule } from '@angular-architects/module-federation';

[...]

export const APP_ROUTES: Routes = [
[...]
{
path: 'booking',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:4201/remoteEntry.js',
exposedModule: './routes'
})
.then(m => m.MFE1_ROUTES)
},
[...]
];
```

```typescript
// After
import { loadRemoteModule } from '@angular-architects/native-federation';
[...]
export const APP_ROUTES: Routes = [
[...]
{
path: 'flights',
loadComponent: () => loadRemoteModule('mfe1', './Component')
.then((m) => m.AppComponent),
},
[...]
];
```

Please also note that loadRemoteModule now always points to a logical name that is resolved via the shell's federation manifest (`src/assets/federation.manifest.json` or `public/federation.manifest.json`):

```json
{
"mfe1": "http://localhost:4201/remoteEntry.json"
}
```

Please also note that the remoteEntry is now a `.json` file.

6. If everything works, delete your `webpack.config.js`


## Migration for Nx projects

1. Remove Module Federation from your poject(s):

```
nx g @angular-architects/module-federation:remove --project xyz
```
```
nx g @angular-architects/module-federation:remove --project xyz
```

2. Initialize Native Federation for your projects:

```
npm i @angular-architects/native-federation
```
npm i @angular-architects/native-federation

nx g @angular-architects/native-federation:init --project xyz --type remote --port 4201
```
nx g @angular-architects/native-federation:init --project xyz --type remote --port 4201
```

**Remarks:** Use type `remote` or type `dynamic-host`.
**Remarks:** Use type `remote` or type `dynamic-host`.

3. Adjust your federation.config.js generated for Native Federation. You can mostly copy over the settings from your `webpack.config.js` used for Module Federation before.
3. Adjust your `federation.config.js` generated for Native Federation. You can mostly copy over the settings from your `webpack.config.js` used for Module Federation before.

4. Update your EcmaScript imports in your source code. Make sure, you import from `@angular-architects/native-federation` instead of from `@angular-architects/module-federation`. Please also note that the signature of `loadRemoteModule` has been simplified:

```typescript
// Before
import { loadRemoteModule } from '@angular-architects/module-federation';
[...]
export const APP_ROUTES: Routes = [
[...]
{
path: 'booking',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:4201/remoteEntry.js',
exposedModule: './routes'
})
.then(m => m.MFE1_ROUTES)
},
[...]
];
```

```typescript
// After
import { loadRemoteModule } from '@angular-architects/native-federation';
[...]
export const APP_ROUTES: Routes = [
[...]
{
path: 'flights',
loadComponent: () => loadRemoteModule('mfe1', './Component')
.then((m) => m.AppComponent),
},
[...]
];
```

Please also note that loadRemoteModule now always points to a logical name that is resolved via the shell's federation manifest (`src/assets/federation.manifest.json` or `public/federation.manifest.json`):

```json
{
"mfe1": "http://localhost:4201/remoteEntry.json"
}
```

Please also note that the remoteEntry is now a `.json` file.
```typescript
// Before
import { loadRemoteModule } from '@angular-architects/module-federation';
[...]
export const APP_ROUTES: Routes = [
[...]
{
path: 'booking',
loadChildren: () =>
loadRemoteModule({
type: 'module',
remoteEntry: 'http://localhost:4201/remoteEntry.js',
exposedModule: './routes'
})
.then(m => m.MFE1_ROUTES)
},
[...]
];
```

```typescript
// After
import { loadRemoteModule } from '@angular-architects/native-federation';
[...]
export const APP_ROUTES: Routes = [
[...]
{
path: 'flights',
loadComponent: () => loadRemoteModule('mfe1', './Component')
.then((m) => m.AppComponent),
},
[...]
];
```

Please also note that loadRemoteModule now always points to a logical name that is resolved via the shell's federation manifest (`src/assets/federation.manifest.json` or `public/federation.manifest.json`):

```json
{
"mfe1": "http://localhost:4201/remoteEntry.json"
}
```

Please also note that the remoteEntry is now a `.json` file.

5. If everything works, delete your `webpack.config.js`

Expand Down

0 comments on commit 655a658

Please sign in to comment.