microsoft / fluentui

Fluent UI web represents a collection of utilities, React components, and web components for building web applications.
https://react.fluentui.dev
Other
18.29k stars 2.71k forks source link

[Feature]: Pure ESModules that do not import NodeJS Modules. #28974

Open mohamedmansour opened 1 year ago

mohamedmansour commented 1 year ago

Library

Web Components (@fluentui/web-components)

Describe the feature that you would like added

The global north star idea is to use @fluentui/web-components without a bundler, using native browser platform ESModules.

Currently, the ESM exports are not true ESModules because they import node resolution modules which require a bundler or a post process script. The photo below shows you the red boxes which are breaking it. image

I really believe @fluentui/web-components dist/esm folder should contain:

image

The main reasons of doing this is because we have an enormous application (Chromium) where we want to host two versions of the FluentUI library to allow teams to incrementally migrate their surface when a breaking change occurs instead of messaging 60+ teams to update their Website in one go. The reason of this is because Chromium has a single node_modules folder and we want to treat libraries as pure ESModules.

LitElement and LitMaterial work this way as well making development easier to work with, something similar to FAST would be great for developer tooling as well.

Have you discussed this feature with our team

No response

Additional context

No response

Validations

Priority

None

mohamedmansour commented 1 year ago

@EisenbergEffect @chrisdholt FYI, thoughts?

EisenbergEffect commented 1 year ago

I think it would be good to have pure ES modules for each component. I wouldn't include fast-element/fast-foundation in this package's output though. Instead, I would recommend using import maps so that you can point @microsoft/fast-element and @microsoft/fast-foundation/* at the fast-element and fast-foundation ES modules from their own packages.

See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap

mohamedmansour commented 1 year ago

Thank you @EisenbergEffect.

That is what I kinda did, I used AOT importmaps in esbuild to automatically resolve (plugin) the NodeJs package imports. And I used esbuild to bundle each component separately. That is just a prebuild process so we can package the fluentui in the product as bundles since each fluentui component imports around 10-20 esm modules (from utilities, foundation, and itself)

If the library, fluentui, did that instead of the dev, then the dev story would be easier for updating fluentui versions. Like the graph i shared above, one esm for fast-element, and one esm per component (like how LitMaterial does it, easier to use)

I am most likely missing something here.

microsoft-github-policy-service[bot] commented 7 months ago

Because this issue has not had activity for over 150 days, we're automatically closing it for house-keeping purposes.

Still require assistance? Please, create a new issue with up-to date details.

mohamedmansour commented 7 months ago

@chrisdholt can we reopen this please?

microsoft-github-policy-service[bot] commented 1 month ago

This issue has not had activity for over 180 days! We're adding Soft close label and will close it soon for house-keeping purposes. Still require assistance? Please add comment - "keep open".

mohamedmansour commented 1 day ago

@chrisdholt can we reopen this please? The reason why this is important is because we have around 100 Web Apps and they all duplicate the bundles for @fluentui/web-components, hence the disk size increases for the binary (Chromium) instead of sharing.

Instead of bundling @fluentui/web-components, we want to treat it as "external" to the bundler. and treat is as web native ES Modules. That way @fluentui/web-components will be shared with all our 100 Web Apps. This won't regress performance because currently tree-shaking in omitted since decorators are in use. Hence, import @fluentui/web-components/button.js would be the same as import ./dist/button.js

Right now, the dist folder has a fake esm because it requires a bundler, the imports to other node_modules invalidates ESM:

import { __decorate } from "tslib";
import { attr, FASTElement, nullableNumberConverter, observable } from '@microsoft/fast-element';
import { keyEnter, keySpace } from '@microsoft/fast-web-utilities';
import { StartEnd } from '../patterns/index.js';
import { applyMixins } from '../utils/apply-mixins.js';
import { toggleState } from '../utils/element-internals.js';
import { ButtonType } from './button.options.js';

Plus it doesn't bundle all the button.styles.js/button.tempate.js button.js into one ESM. Ideally for pure ES Modules, we need each component to have 1 JS, and perhaps couple JS for the core.