|
Hi All, SHELL webpack.config.js const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const share = mf.share;
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, '../../tsconfig.json'),
['auth-lib']
);
module.exports = {
output: {
uniqueName: "shell",
publicPath: "auto"
},
optimization: {
runtimeChunk: false
},
resolve: {
alias: {
...sharedMappings.getAliases(),
}
},
plugins: [
new ModuleFederationPlugin({
// For hosts (please adjust)
remotes: {
"myremote": "myremote@http://localhost:4250/remoteEntry.js"
},
shared: share({
"@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
"@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
"@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
"@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
...sharedMappings.getDescriptors()
})
}),
sharedMappings.getPlugin()
],
};REMOTE webpack.config.js const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const mf = require("@angular-architects/module-federation/webpack");
const path = require("path");
const share = mf.share;
const sharedMappings = new mf.SharedMappings();
sharedMappings.register(
path.join(__dirname, 'tsconfig.json'),
[/* mapped paths to share */]
);
module.exports = {
output: {
uniqueName: "myremote",
publicPath: "auto"
},
optimization: {
runtimeChunk: false
},
resolve: {
alias: {
...sharedMappings.getAliases(),
}
},
plugins: [
new ModuleFederationPlugin({
// For remotes (please adjust)
name: "myremote",
filename: "remoteEntry.js",
exposes: {
'./Module': './src/app/myremote/myremote.module.ts'
},
shared: share({
"@angular/core": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
"@angular/common": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
"@angular/common/http": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
"@angular/router": { singleton: true, strictVersion: true, requiredVersion: 'auto' },
...sharedMappings.getDescriptors()
})
}),
sharedMappings.getPlugin()
],
};Everything works smoothly when I use the reference to my remote module in the shell app like so: import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
const routes: Routes = [{
path: '',
component: HomeComponent,
pathMatch: 'full'
}, {
path: 'myremote',
loadChildren: () => import('myremote/Module').then(m => m.MyRemoteModule)
}];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }The problem appears when the remote module's component within its code instantiate a new Web Worker like so: const myWorker = new Worker(
new URL('../path/to/workers/worker.ts',
import.meta.url
),
{ type: 'module', name: 'my-worker' }
);The code above, in Webpack 5, already generates a separate bundle in my app called my-worker.js, and it's not part nor of the component's neither the module's bundle. Therefore exposing the module to Module Federation, will not expose into the remoteEntry.js also the worker's code. Then trying with the shell app to navigate to the route which loads my remote, will error and notify that:
So the question is, if I want to have a remote and expose its modules to be used in a shell app, and one of its modules uses a Web Worker, how can I make sure that the separate worker bundle created by Webpack is also exposed in order for the shell app to be able to instantiate it? Asked also on stack overflow: |
Replies: 6 comments 1 reply
You need setup CORS, please read https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS |
|
@gigadie I'm experiencing the same issue, basically I'm developing in front of a proxy (starting the server with the --proxy-config flag) and the CORS defs are enabled (at least for API interactions), did you added something to your shell webpack.config? |
|
Hi guys, I'm having the same problem. Can you help me? I've tried to implement the proxy but without success. @gigadie did you manage to solve it? |
|
I haven't been able to get Web Workers running at all in an Angular 14 app using Module Federation either on the host or the remote. Does anybody happen to have a sample project with it working that I could reference? I opened an issue with @angular-architects/module-federation (angular-architects/module-federation-plugin#304), but I am not sure that is where the problem resides. I also have a repro project: https://github.com/protonyx/ng-module-federation-web-worker |
|
I resolved it as suggested by alexander-akait, I even marked it as answered on stack overflow, have a look guys. |
|
As mentioned here #14648 (reply in thread) At the end I solved it using fetch instead: export class CorsWorker {
private readonly url: string | URL;
private readonly options?: WorkerOptions;
// Have this only to trick Webpack into properly transpiling
// the url address from the component which uses it
constructor(url: string | URL, options?: WorkerOptions) {
this.url = url;
this.options = options;
}
async createWorker(): Promise<Worker> {
const f = await fetch(this.url);
const t = await f.text();
const b = new Blob([t], {
type: 'application/javascript',
});
const url = URL.createObjectURL(b);
const worker = new Worker(url, this.options);
return worker;
}
}and then import { CorsWorker as Worker } from './cors-worker';
// aliasing CorsWorker to Worker makes it statically analyzable
const corsWorker = await (new Worker(
new URL('../workers/my-worker.worker', import.meta.url),
{ type: 'module', name: 'my-worker' },
)).createWorker(); |
As mentioned here #14648 (reply in thread)
At the end I solved it using fetch instead: