Comments (86)
ill raise this with Microsoft - they will have to support federation since they are going to be using it heavily
from module-federation-examples.
What I have done is use node to generate a .d.ts file, that are loaded by our global.d.ts file.
So each Remote outputs a .d.ts file that go declare module "dlaWidgets/Widets" {}
, with using the ts.createProgram you can tap into the typeChecker stuff that i use to print its public api. Kinda like getting tsc to ouput definition files, but instead spit them into a single file.
Then each of my hosts import this .d.ts file, which I have registered in a global.d.ts, that all of my projectReferenced monorepo apps include.
So there is a small disconnect between a webpack config, and the types. But any exposed things, are automagically available with types in my entire app. So ts might say its a valid import, but just need to actially configure it with webpack also.
Working on open sourcing this generative thing - just gotta make sure it works in all use cases.
from module-federation-examples.
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 :)
from module-federation-examples.
I'm not a TS user so I'm no help here.
from module-federation-examples.
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
from module-federation-examples.
@maraisr your approach sounds very interesting. Keep us posted if you open source it.
from module-federation-examples.
Or have a monorepo of types
from module-federation-examples.
More then 1 year from the day that issue was open , do we have some good solution how we can resolve that issue and make typescript work well with the plugin ? Tnx
from module-federation-examples.
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: https://github.com/rangle/federated-modules-typescript
from module-federation-examples.
What I have done is use node to generate a .d.ts file, that are loaded by our global.d.ts file.
So each Remote outputs a .d.ts file that go
declare module "dlaWidgets/Widets" {}
, with using the ts.createProgram you can tap into the typeChecker stuff that i use to print its public api. Kinda like getting tsc to ouput definition files, but instead spit them into a single file.Then each of my hosts import this .d.ts file, which I have registered in a global.d.ts, that all of my projectReferenced monorepo apps include.
So there is a small disconnect between a webpack config, and the types. But any exposed things, are automagically available with types in my entire app. So ts might say its a valid import, but just need to actially configure it with webpack also.
Working on open sourcing this generative thing - just gotta make sure it works in all use cases.
In addition to this approach, what about packaging that d.ts ouput file and deploying it as a tar.gz alongside your webpack artifacts? Similar to a @types/* package except not published to registry. Then a host app can optionally add dev-dependency referencing the remote tar.gz file and always have latest TS types.
I think this approach would work well for non-monorepo cases.
from module-federation-examples.
@zhangwilling it's not a part of IDE, it's all about typechenking of typescript compiler itself
from module-federation-examples.
yeah IDE can solve it, assuming it supports that. Meeting with Microsoft in august - seeking changes to TS to support MF, in doing so IDEs will have to follow the spec
from module-federation-examples.
I would love some feedback on how I am currently solving this issue:
I have a mono-repo with several packages. Each package defines a federation.config.json
file that declares its remote name and what it exposes, like so:
packages/app2/config/federation.config.json
{
"name": "app2",
"filename": "remoteEntry.js",
"exposes": {
"./Button": "./app2/Button"
}
}
The webpack config file for the module imports this config and spreads it into the plugin config like:
packages/app2/config/webpack.config.js
plugins: [
new ModuleFederationPlugin({
...federationConfig,
shared: {
...deps,
},
}),
],
I then have an NPM module I am calling federated_types
which exposes a CLI command called make-federated-types
which can be called via an npm script
in a package.
This command finds and reads the package's federation.config.json
and uses the TS compiler to generate types with a similar process to what @maraisr described - however I write the types into an @types/__federated_types
directory under the projects node_modules
directory. This is nice because there is no extra resolution configuration needed in the tsconfig file or webpack config files since they look in @types
as a default location.
The command does allow for specifying where the federated typing files should be written, but by default, it writes to the node_modules/@types/__federated_types
directory.
Then in each package.json, I added an entry to the scripts
node, like:
"scripts": {
"make-types": "make-federated-types"
},
And since I'm using Lerna, when I run lerna run make-types
it generates the typings for the items I have exposed via federation
Does this seem like a sound approach? Is writing to the node_modules
directory a bad idea? Is there a better location to write to?
from module-federation-examples.
Very cool. I am happy to help!
If it's useful to anyone looking at sharing type definitions between their packages in a mono-repo, here is what I am using: https://github.com/pixability/federated-types
from module-federation-examples.
I was able to get my project with module federation and typescript working, along with typesafety of remote components, with minimal cost:
- Each remote application has a
declaration.d.ts
file in the root defining the props of exposed components:
declare module "app2/App" {
type Props = import('./src/components/App/App').Props;
const App: React.FunctionComponent<Props>;
export default App;
}
- Parent application has the following entry in
tsconfig.json
:
{
"include": [
"../*/*.d.ts"
]
}
in this scenario the lazy-loaded components are still reporting missing/incorrect props passed. The only con I can see here is that you need to make sure every newly exposed component is added to the .d.ts file, but that's a minimal cost. Also, make sure you've set "module": "esnext"
in compilerOptions in your tsconfig.json
- setting "commonjs" will result in console error reg. shared module not being available.
EDIT: One more (cosmetic) issue is, that VSCode's built-in TS server doesn't seem to recognize the "include" part of tsconfig.json resulting in marking the dynamic import in parent app as error (Cannot find module 'app2/App' or its corresponding type declarations
) but the build works fine. If anyone knows a fix for this, I'd be ever so grateful.
from module-federation-examples.
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
from module-federation-examples.
Here is a better solution with Typescript.
Form a closed loop of types, from generation to reference complete for Module Federation project.
https://github.com/efoxTeam/emp/tree/main/packages/emp-tune-dts-plugin
from module-federation-examples.
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
from module-federation-examples.
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 :)
Does this solution work well with Polyrepo as well?
from module-federation-examples.
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
from module-federation-examples.
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
from module-federation-examples.
Is anyone having issues with eslint
when importing a federated module?
👇 eslint config
{
"env": {
"browser": true,
"jest": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"extends": [
"airbnb",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:jest/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"plugins": ["react", "react-hooks", "@typescript-eslint", "jest", "prettier"],
"rules": {
"import/extensions": "off",
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
"react/jsx-uses-react": "off",
"react/jsx-filename-extension": [1, { "extensions": [".ts", ".tsx"] }],
"react/jsx-one-expression-per-line": "off",
"import/prefer-default-export": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"prettier/prettier": "error"
},
"settings": {
"import/resolver": {
"typescript": {}
}
}
}
👇 tsconfig
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react-jsx",
"lib": ["dom", "dom.iterable", "esnext"],
"moduleResolution": "node",
"noEmit": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"baseUrl": "./src",
"paths": {
"routes/*": ["routes/*"],
"services/*": ["services/*"],
"pages/*": ["pages/*"],
"components/*": ["components/*"]
}
},
"include": ["src"]
}
Thanks! 🙏
from module-federation-examples.
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 🙏🏻
from module-federation-examples.
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 ?
from module-federation-examples.
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
from module-federation-examples.
I found some devs solving this by modifying TS loader. Specifically for module Federation
from module-federation-examples.
how to fix it
from module-federation-examples.
Will check this out and see what's needed to make this work for both poly and monorepo
from module-federation-examples.
Has anyone got a reliable solution for projects that don't use a monorepo?
https://github.com/efoxTeam/emp/tree/main/packages/emp-tune-dts-plugin
from module-federation-examples.
For those of you creating .d.ts files, do you also have enums? I tried that approach earlier this year and found that my runtimes would throw up because enums need to be compiled to (extraordinarily weird) JS. Maybe I was doing something wrong?
from module-federation-examples.
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?
from module-federation-examples.
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
from module-federation-examples.
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
from module-federation-examples.
@ScriptedAlchemy Any plan to add typescript support in federated modules?
from module-federation-examples.
https://www.npmjs.com/package/@module-federation/typescript
from module-federation-examples.
@ScriptedAlchemy can you link the github repo?
I suppose https://github.com/module-federation/typescript
from module-federation-examples.
i think it should be solved by IDE, such as vscode.
from module-federation-examples.
I like the IDE idea @zhangwilling, but that will be more about aiding the development flow. However... I think this should still remain in the compiler itself, or a definition file that the compiler reads in. Personally feel its the latter.
If you solve to get the compiler to be aware of the remotes, then you don't have to worry about IDE, and specific IDE support as all IDE's will get this knowledge for free.
My solution outlined above still holds true. Its not terribly bad to implement. I'm hoping to get something open sourced soon.
Just wanting to get an idea from the community:
- Are you using a monorepo?
- Are your exposes objects exposed as standard javascript/typescript files? (Rather than inline in your webpack.config.js)
- Are the request's standard node-esk requests, ie no
@svgr/webpack!./icon.svg
, where the request would firsts require a loader?
I've taken some assumptions to how I build software, but just wanting to get more scope so that this tool when released would solve issues for the majority.
from module-federation-examples.
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
- shell - served with webpack-dev-server from localhost:4242
- commonLibs - from localhost:4243
- wmf3 - from https://production.com/wmf3
- wmf4 - from https://production.com/wmf4
- ...
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?
from module-federation-examples.
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
from module-federation-examples.
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/
from module-federation-examples.
from module-federation-examples.
I believe, in our case, we should be able to be fine with not having type checking for remote libraries. We can use shared libraries for extension authors import core libraries, so they don't need to be remote and dynamically imported.
from module-federation-examples.
I have tried a hacky way to benefit from type-safety importing the definition of the remote project (app2, here widgets) in the host project (app1). As shown on the below image, lazy returns the correct type and non acceptable props are underlined in red. I guess a solution would be to publish the types separately and a 3rd party could depend on those types.
from module-federation-examples.
ill raise this with Microsoft - they will have to support federation since they are going to be using it heavily
Awesome!
from module-federation-examples.
mono repo is not recomended when our app is very large,independent repo is better.
💡We can watch and output independent repo's d.ts, then start a server which can make d.ts could be downloaded. When other apps need d.ts,just download it to your project from local server.
from module-federation-examples.
same issue and suggest like deno remote url type.d.ts
from module-federation-examples.
This remains a solution
What I have done is use node to generate a .d.ts file, that are loaded by our global.d.ts file.
So each Remote outputs a .d.ts file that go
declare module "dlaWidgets/Widets" {}
, with using the ts.createProgram you can tap into the typeChecker stuff that i use to print its public api. Kinda like getting tsc to ouput definition files, but instead spit them into a single file.Then each of my hosts import this .d.ts file, which I have registered in a global.d.ts, that all of my projectReferenced monorepo apps include.
So there is a small disconnect between a webpack config, and the types. But any exposed things, are automagically available with types in my entire app. So ts might say its a valid import, but just need to actially configure it with webpack also.
Working on open sourcing this generative thing - just gotta make sure it works in all use cases.
from module-federation-examples.
@zhangwilling it's not a part of IDE, it's all about typechenking of typescript compiler itself
@glebmachine yes, it is not part of IDE. Maybe TS can provide extra typing file config, but IDE plugin can do this, it could be improved much by IDE. Same as maven in IDEA, maven is not part of IDEA, but it does. Because it's a very important infrastrure.👻
from module-federation-examples.
I like the IDE idea @zhangwilling, but that will be more about aiding the development flow. However... I think this should still remain in the compiler itself, or a definition file that the compiler reads in. Personally feel its the latter.
If you solve to get the compiler to be aware of the remotes, then you don't have to worry about IDE, and specific IDE support as all IDE's will get this knowledge for free.
My solution outlined above still holds true. Its not terribly bad to implement. I'm hoping to get something open sourced soon.
Just wanting to get an idea from the community:
- Are you using a monorepo?
- Are your exposes objects exposed as standard javascript/typescript files? (Rather than inline in your webpack.config.js)
- Are the request's standard node-esk requests, ie no
@svgr/webpack!./icon.svg
, where the request would firsts require a loader?I've taken some assumptions to how I build software, but just wanting to get more scope so that this tool when released would solve issues for the majority.
@maraisr
monorepo is not recommend when facing large project. so a large project would be seprated to many litttle repos by domain or module. But, we usually would put them together into same parent directory or we use worksapce in VSCode to oragnize them together logically 😈.
from module-federation-examples.
@zhangwilling yeah
But, typescript are trying to resolve imports. And fails when facing federation module import declaration. It looks like we have to be able to declare special federation modules right into tsconfig.json
file or similar way.
For now, i'm workaround this with by loads file by document.createElement('script')
.
from module-federation-examples.
You got to be careful with that approach though. It does mean that you cannot also use path mappings for other things in your app, because if you are you're probably also using tsconfig paths webpack resolver, in which case module federation plugin can't "remote" those. You can but you'd have to have a special build-time tsconfig that excludes the MF mappings.
from module-federation-examples.
Thanks @maraisr , that is a very good point I had not considered.
I suppose then it is a trade-off of manual remote interface vs potential manual MF path-mapping overwrites.
from module-federation-examples.
1.webpack provide a template for the "d.ts" module building
2.webpack config decare the use of remote "d.ts" module
3.IDE support using static inspection for the second point
from module-federation-examples.
fix it with npm-dts create in dist & request by app
from module-federation-examples.
As long as node resolves properly to the location you write to, it's a sound approach. I think haha.
What one could do is create a GitHub crawler that pulls other repos TS def files remotely (similar to webpack code streaming) and write them on demand. You'd only need a list of repos / remotes to "look" for JS defs to pull ahead of time.
Basically your mono repo idea. Applied to polyrepo and using the network
If anyone wants to try building this- I'll give you maintainer access to a repo under the official MF organization
from module-federation-examples.
Thanks for the feedback!
For your suggestions around a poly-repo solution, are you thinking an application would have a config file that defined the repos/remotes they are using, and then a script would pull those repos and generate local copies of the types needed?
Just trying to get a clearer picture. I would be happy to work on something like that. Happy and eager to help how I can!
from module-federation-examples.
Yeah basically. Imagine you listed an array of objects that contain info about your remotes.
Then we could search git repo via api or just the TS defs related to remote files and write those strings to disk in your types directory
Basically replaced fs with fetch and we get the raw git text from api
from module-federation-examples.
This is easier to instrument with federation dashboard because it know what hosts uses what remotes and where they are. In the future I could tack something into dashboard so one could query dashboard for the defs - then write the strings.
from module-federation-examples.
Cool, I'll check that out too. Thanks!
from module-federation-examples.
Has anyone got a reliable solution for projects that don't use a monorepo?
from module-federation-examples.
@lm2almeida I think the issue is that your TypeScript project doesn't understand what remote
is, and therefore eslint doesn't understand it as your eslint is configured to use TypeScript as the import resolver.
As for a solution to the TypeScript issue. The only solutions I've found so far are in this thread and they involve building the types separately and then importing them from somewhere, the main issues I'm seeing with this are the manual steps of building the types, and then syncing up these types across your projects when the files change.
At the moment it's an unsolved problem imo. It's less of an issue in a monorepo though.
from module-federation-examples.
@lm2almeida I think the issue is that your TypeScript project doesn't understand what
remote
is, and therefore eslint doesn't understand it as your eslint is configured to use TypeScript as the import resolver.As for a solution to the TypeScript issue. The only solutions I've found so far are in this thread and they involve building the types separately and then importing them from somewhere, the main issues I'm seeing with this are the manual steps of building the types, and then syncing up these types across your projects when the files change.
At the moment it's an unsolved problem imo. It's less of an issue in a monorepo though.
Thanks for the answer, @rickihastings. The problem here is that even with the declared typing the error still occurs. Looking forward for a solution 🙏
from module-federation-examples.
Whoever stuck on typings here is my approach.
First of all, I am relying on @gthmb 's federated-types
package: #20 (comment)
on my remote app, I created federation-config.json
/* federation.config.json */
{
"name": "blank",
"exposes": {
"./RemoteApp": "./src/bootstrap"
}
}
then, I exporting my typings in a custom @types
directory on my root. (remote app)
scripts: {
"make-types": "make-federated-types --outputDir ./@types/remote-app"
}
federated-types
export types inside node_modules
as default behaviour. For that reason it does not create package.json
if custom output directory set. However, I need the package.json
because I am adding my remote app's type as a dependency to my host application.
after running make-types
command, it generates the types by looking at my federation-config.json
and I manually created package.json
. In the end, you should have something similar:
├── @types
│ ├── remote-app
│ │ ├── index.d.ts
│ │ ├── remote-app.d.ts
│ │ ├── package.json
I have my typings ready to be import as a dependency for my host app. On my host app's package.json
I added these typings as devDependency
devDependencies: {
"@types/remote-app": "file:../federated-apps/remote-app/@types/remote-app",
}
then run the yarn install
as usual, and all my remote-app's typings are available for the host app, without a hassle. What's good at this, all these typings creations and importing to host app is automated and less error-prone.
from module-federation-examples.
Sharing a recent setup in my current company that is NOT monorepo (can't share code as it's not open-sourced, but happy to clarify!).
The key components are:
- npm org (to publish the exposes type, not the code)
- (Optional) A custom pipeline (like CRA) that abstract the webpack config so I can enforce similar conventions for all projects.
The convention that I enforce is that modules that are exposed must be in a src/exposes
folder. Then, I programmatically set the exposes
key of module federation plugin based on the file, e.g.
return new ModuleFederationPlugin({
exposes: {
'./exposes/file1': './src/exposes/file1'
}
})
I have a custom tsconfig.json
file that only includes src/exposes
folder. When it compiles, it will generate another folder like
type
/exposes
/file1.d.ts
/file2.d.ts
/components
/...
Writing some custom code, I generate a package.json file in that folder with name @npmorg/<appName>
, which can be published.
In the host application, when it import the remotes, always use the convention @npmorg/<appName>/exposes/<module>
and also install @npmorg/<appName>
package (which only consists of type definition).
Everytime the remote app change its interface in exposes
file, it just need to regenerate the type definition folder and publish it and the host just need to update that package to get the latest type definition.
from module-federation-examples.
I have a file in my remote which is exporting enums and interfaces and i need to consume this in my host application. My build keeps failing as either it fails with the error: / not declared and when i declare it, it fails with the error: not being used and at the place where i am using it it throws the error: cannot use namespace.
from module-federation-examples.
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!
from module-federation-examples.
federation.config.json
"filename" is not used by federated-types
. So "filename" should stay in webpack.config
from module-federation-examples.
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.
from module-federation-examples.
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?
from module-federation-examples.
emp v2 work very very use remote d.ts
from module-federation-examples.
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',
}
],
},
},
}),
from module-federation-examples.
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";
~~~~~~~~~~~~~~~~
from module-federation-examples.
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
from module-federation-examples.
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:
from module-federation-examples.
@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
from module-federation-examples.
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',
from module-federation-examples.
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.
from module-federation-examples.
Already done. App.privjs.com search for module-federation/typescript
We did this months ago
from module-federation-examples.
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
from module-federation-examples.
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
from module-federation-examples.
@ScriptedAlchemy can you link the github repo?
from module-federation-examples.
thats the one, PR's welcome
from module-federation-examples.
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).
from module-federation-examples.
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 afederation.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
from module-federation-examples.
Type Hint Support Tracking: module-federation/core#1943
from module-federation-examples.
Related Issues (20)
- Uncaught SyntaxError: Unexpected token function when use module federation v1.5 HOT 3
- Code Nextjs-v14 throws error when try to run HOT 5
- [Feature request/discussion] Allow having multiple instances of shared dependencies HOT 3
- Hot Module Reloading is solved! HOT 1
- [Question] Shared modules are duplicate in multi-bundle files of MF v8.2.2 above HOT 10
- Can I Remove remote.js?[hash] for cache remote.js HOT 2
- NPM package unavailable - nextjs-shared-v14 HOT 1
- [Bug][Nextjs13] Uncaught TypeError: Cannot read properties of undefined (reading 'consumes') HOT 2
- Examples issue HOT 3
- vue-cli master分支跑不起来 HOT 1
- [Question] URL parameters? HOT 6
- externals @module-federation/webpack-bundler-runtime no work HOT 1
- Dynamic-remotes shared config not work HOT 2
- Does V2 currently support Vite? HOT 1
- Microfe
- nextjs mf does not generate remoteEntry.js HOT 6
- Add ability to reduce requests waterfall for host-ui HOT 3
- [Help] Router Module forRoot Issue with Module Federation HOT 1
- css-Isolation not working in rspack example HOT 1
- Does it work with the Next 14 App router?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from module-federation-examples.