Closed echarles closed 2 years ago
federation.config.json
"filename" is not used by federated-types
. So "filename" should stay in webpack.config
I'm not a TS user so I'm no help here.
Who can discuss on this theme? Maybe RFC or something else? 2y opened issue with common case where answer is "I'm not a TS" look weird
I disagree. In the end, Typescript support must not an official thing for this tech. On the other hand, there are plenty of solutions mentioned above works just fine.
I do think a good Typescript solution is very important for the long-term success of module federation, given how TS keeps growing in popularity.
Would something like this work?
Package A: The code you want to get through module federation. Package B: A package that imports Package A through module federation and then re-exports those functions with correct typing. Package C: Your application, which adds Package B through npm.
Package A and Package B should be published from the same repo, so that you don't have to keep anything in sync between repos. I'm honestly not sure if this method would preserve the benefits of module federation—what happens when webpack runs on package C?
emp v2 work very very use remote d.ts
Sharing my setup:
For the host which
exposes
modules
- I created a dts-loader which will emit and collect the
.d.ts
file. And also it generates the entry.d.ts
file based on theexposes
.- Then I create a tarball(
.tgz
file) for the emitted types & entries. And I deployed this tarball with the application's statics, for example, tohttp://localhost:9000/app-dts.tgz
For the host which requires
remotes
- I created a webpack plugin WebpackRemoteTypesPlugin which will download and unpack the tarball from remote automatically when running webpack.
More details can be found here: https://github.com/ruanyl/dts-loader Comments & feedbacks are welcome :)
I was able to get this working in a polyrepo. One thing that tripped me up pretty hard was your
exposes
must explicitly reference the files you're exposing.exposes: { './theme': './src/themes/index.ts', './helpers': './src/helpers/index.ts', './constants': './src/constants/index.ts', }
This will not work:
exposes: { './theme': './src/themes, './helpers': './src/helpers', './constants': './src/constants, }
Opened up this issue so hopefully it can be improved: ruanyl/dts-loader#7
Also, I was able to automate the archiving by using tar-webpack-plugin, so my types are generated and synced whenever I
npm start
- pretty neat!
Could you please share how you got tar-webpack-plugin to work?
Although I wonder what should be done when running tsc in CI, I think you can do the same thing with filemanager-webpack-plugin like this without using tar-webpack-plugin.
new FileManagerPlugin({
events: {
onEnd: {
archive: [
{
source: '.wp_federation',
destination: 'path/to/types.tar.gz',
format: 'tar',
}
],
},
},
}),
Depending on your use case/setup you could solve this by having a
tsconfig.json
in the project root and leverage path-mapping to resolve the apps entry points (Remote Name + Exposed module):
/tsconfig.json
:... "paths": { "app1/Remote": ["./packages/app1/src/app"], "app2/Remote": ["./packages/app2/src/app"] } ...
/packages/app1/tsconfig.json
&/packages/app2/tsconfig.json
:{ "extends": "../../tsconfig.json" }
I've setup a little prototype using this setup: rangle/federated-modules-typescript
This is the easier and quickest solution that worked for me! Thanks @micmro 🙏🏻
If anyone is looking for a poly-repo solution, I've put together this sample app with some instructions to share the type definitions of exposed files: https://github.com/jrandeniya/federated-types-sample
It's relatively straight forward using the great work done by @touk/federated-types and webpack-remote-types-plugin
I've also been using the tsconfig.json
paths
solution and it has been working well, but it's not without issues. That is, those remotes that you've configured with paths
will still need to be fully installed when you check types, or you'll end up with errors:
./packages/app1/src/app/useSelectedEntity.ts:2:21 - error TS2307: Cannot find module 'lodash/isEqual' or its corresponding type declarations.
2 import isEqual from "lodash/isEqual";
~~~~~~~~~~~~~~~~
We have released a Federated Types Plugin beta.
Theres some gaps in the type def bundling, we are aware of it and working on improvements.
https://app.privjs.com/buy/packageDetail?pkg=@module-federation/typescript
We have released a Federated Types Plugin beta.
Theres some gaps in the type def bundling, we are aware of it and working on improvements.
https://app.privjs.com/buy/packageDetail?pkg=@module-federation/typescript
It looks promising. Is there a plan to open source it in regular npm ?
We have released a Federated Types Plugin beta.
Theres some gaps in the type def bundling, we are aware of it and working on improvements.
https://app.privjs.com/buy/packageDetail?pkg=@module-federation/typescript
It looks promising. Is there a plan to open source it in regular npm ?
Not currently, I generally only publish OSS to npm. Closed source, even if it's free, usually stays on priv
Perhaps in the future depending on data & feedback during beta & RC phases
Hey @ScriptedAlchemy, I'm glad there's finally a solution emerging to share Typescript definitions among microfrontends from the author, despite of saying that I'm not a TS user so I'm no help here.!
I was trying other solutions like @touk/federated-types that reads a federation.config.json
and generates types in node_modules@types__federated_types
It does that for local modules but does not collect types for modules that are exposed from node_modules
.
Our federation.config.json
config looks like this:
{
"name": "commonLibs",
"exposes": {
"./AxiosHttp": "./src/api-services/axios-client/index",
...
"./@cloudbeds/ui-library": "@cloudbeds/ui-library",
"./react": "react",
"./react-dom": "react-dom",
"./react-query": "react-query",
"./react-router-dom": "react-router-dom"
}
}
Everything after ...
is from node_modules
and we want that to be part of commonLibs
microfrontend so that will consume a single version of these without even installing react
in consuming app's package.json
, e.g.
import react from 'commonLibs/react';
Coupled with webpack-remote-types-plugin we could have updated types without uploading them to S3 or publishing to NPM. Unfortunately that doesn’t work with Dynamic remotes - it needs an actual URL from which the remote is served from. We use external-remotes-plugin and uses a dynamic variable name, e.g. [window.commonLibs]
instead of localhost:4242
Here's a screen of the error we are experiencing:
Now we are trying to achieve that with Federated Types Plugin beta.
It would be really great if the closed source plugin would have an official place to open issues. Probably this thread is currently serves this purpose
@module-federation/typescript creates types in dist/@mf-typescript
The __types_index.json
file contains list of type definition files for all exposed modules, here it's:
[
"index.d.ts",
"index.d.ts",
"index.d.ts",
"index.d.ts",
"ui-library.d.ts",
"react.d.ts",
"react-dom.d.ts",
"react-query.d.ts",
"react-router-dom.d.ts"
]
Although it lists packages in node_modules
, e.g. react.d.ts
and ui-library.d.ts
they are not included in dist/@mf-typescript
Also it would be great if that file's purpose would be documented here
Compared to @touk/federated-types, instead of a single file with all types, @module-federation/typescript recreates the directory structure which is neat.
There's one serious issue with @module-federation/typescript
plugin is that the types cannot be used for microfrontends that are served from production environment (unless we don't know something). E.g. imagine there are 10 federated apps
Some are served with webpack-dev-server, others from production (e.g. CDN, AWS Cloudfront, etc.). For these we would like to publish an npm package with types.
It doesn't look like @module-federation/typescript
has any configuration.
@ScriptedAlchemy are there any hidden options that we could provide to generate types that are usable when published as an NPM package and includes types for modules that expose node_modules
? If not, would it be possible to extend the plugin to accommodate for those use-cases?
Also it suffers from the issue with dynamic imports
Even though here are examples in advanced-api and the dynamic System
Host. So it's not something unusual to do.
We use the module-federation/external-remotes-plugin to achieve this
Also the Practical Module Federation has an example of Dynamically Loading Federated Modules for Webpack 4 and 5.
@ScriptedAlchemy how we can use the plugin in such environment?
Looks like module-federation/external-remotes-plugin and @module-federation/typescript are currently incompatible
I've changed the URL to be localhost
in remotes
section and now we're getting this 404 error for exposed npm package
\node_modules\got\index.js:482
proxy.emit('error', new got.HTTPError(statusCode, res.statusMessage, res.headers, opts), null, res);
^
GotError [HTTPError]: Response code 404 (Not Found)
path: '/@mf-typescript/ui-library.d.ts',
protocol: 'http:',
url: 'http://localhost:9082/@mf-typescript/ui-library.d.ts',
statusCode: 404,
statusMessage: 'Not Found',
Sorry for the numerous comments, I wish it can be hosted on Github, with Issues/Discussion tabs It can be an empty repo with a README only.
We have released a Federated Types Plugin beta.
Theres some gaps in the type def bundling, we are aware of it and working on improvements.
https://app.privjs.com/buy/packageDetail?pkg=@module-federation/typescript
I want to contribute to the repo, is there any way I can join the work? Wait for your reply. @ScriptedAlchemy
I don't know if this was already mentioned in this thread but there are some nice solutions exposed in this blog post: https://spin.atomicobject.com/2022/07/19/typescript-federated-modules/
For anyone interested, at Cloudbeds, we've released a public NPM package that was built on top of existing solutions
https://www.npmjs.com/package/@cloudbeds/webpack-module-federation-types-plugin
It's also planned to open source it on Github
@ScriptedAlchemy Any plan to add typescript support in federated modules?
Already done. App.privjs.com search for module-federation/typescript
We did this months ago
I'm searching for a solution with Angular using the new typescript package. I tried to use it but with no success. But great initiative @ScriptedAlchemy
The @cloudbeds/webpack-module-federation-types-plugin
is now available on Github. Feel free to use Issues or Discussions tabs.
And let me thank @ScriptedAlchemy for the awesome Module Federation plugin upon which a lot of projects nowadays started to rely on. I hope that some day there won't be a need for a 3rd party plugin to deal with types and there'll be a standard documented way built into Webpack.next
If we can merge or open PRs to module-federation/typescript to improve the "official" plugin that would be great. We open-sourced it to try and get more input and help since i dont write TS I just know webpack very well haha
@ScriptedAlchemy can you link the github repo?
@ScriptedAlchemy can you link the github repo?
thats the one, PR's welcome
Hey @ScriptedAlchemy, I'm glad there's finally a solution emerging to share Typescript definitions among microfrontends from the author, despite of saying that I'm not a TS user so I'm no help here.!
I was trying other solutions like @touk/federated-types that reads a
federation.config.json
and generates types innode_modules@types__federated_types
It does that for local modules but does not collect types for modules that are exposed from
node_modules
.Our
federation.config.json
config looks like this:{ "name": "commonLibs", "exposes": { "./AxiosHttp": "./src/api-services/axios-client/index", ... "./@cloudbeds/ui-library": "@cloudbeds/ui-library", "./react": "react", "./react-dom": "react-dom", "./react-query": "react-query", "./react-router-dom": "react-router-dom" } }
Everything after
...
is fromnode_modules
and we want that to be part ofcommonLibs
microfrontend so that will consume a single version of these without even installingreact
in consuming app'spackage.json
, e.g.import react from 'commonLibs/react';
Coupled with webpack-remote-types-plugin we could have updated types without uploading them to S3 or publishing to NPM. Unfortunately that doesn’t work with Dynamic remotes - it needs an actual URL from which the remote is served from. We use external-remotes-plugin and uses a dynamic variable name, e.g.
[window.commonLibs]
instead oflocalhost:4242
Here's a screen of the error we are experiencing:
Hi @steven-prybylynskyi , Could you please suggest me the package you have used to build types for modules exposed from node_modules(eg: react).
Hey @ScriptedAlchemy, I'm glad there's finally a solution emerging to share Typescript definitions among microfrontends from the author, despite of saying that I'm not a TS user so I'm no help here.! I was trying other solutions like @touk/federated-types that reads a
federation.config.json
and generates types innode_modules@types__federated_types
It does that for local modules but does not collect types for modules that are exposed fromnode_modules
. Ourfederation.config.json
config looks like this:{ "name": "commonLibs", "exposes": { "./AxiosHttp": "./src/api-services/axios-client/index", ... "./@cloudbeds/ui-library": "@cloudbeds/ui-library", "./react": "react", "./react-dom": "react-dom", "./react-query": "react-query", "./react-router-dom": "react-router-dom" } }
Everything after
...
is fromnode_modules
and we want that to be part ofcommonLibs
microfrontend so that will consume a single version of these without even installingreact
in consuming app'spackage.json
, e.g.import react from 'commonLibs/react';
Coupled with webpack-remote-types-plugin we could have updated types without uploading them to S3 or publishing to NPM. Unfortunately that doesn’t work with Dynamic remotes - it needs an actual URL from which the remote is served from. We use external-remotes-plugin and uses a dynamic variable name, e.g.
[window.commonLibs]
instead oflocalhost:4242
Here's a screen of the error we are experiencing:Hi @steven-prybylynskyi , Could you please suggest me the package you have used to build types for modules exposed from node_modules(eg: react).
https://github.com/module-federation/universe/tree/main/packages/native-federation-typescript
Typescript support will be implemented as a built-in capability in the coming iteration of module federation. Colloquially known as "v1.5"
You will see this in https://modernjs.dev as well
Type Hint Support Tracking: https://github.com/module-federation/universe/issues/1943
Update from @ScriptedAlchemy - https://www.npmjs.com/package/@module-federation/typescript has been released
I can see a disadvantage using remotes libraries vs the classical libraries where e.g. typescript can be used to enforce strong types. The current typescript example defines a generic
app2/Button
which is similar defining aany
type.https://github.com/module-federation/module-federation-examples/blob/cf2d070c7bbb0d5f447cfe33f69e07bcf85f8ddb/typescript/app1/src/app2.d.ts#L3-L7
As the remote var does not have type, I don't see a way to benefit from the
app2
types inapp1
. Any idea on this?