Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the fallback bundle logic #15929

Closed
Artur- opened this issue Feb 16, 2023 · 3 comments · Fixed by #16592
Closed

Remove the fallback bundle logic #15929

Artur- opened this issue Feb 16, 2023 · 3 comments · Fixed by #16592

Comments

@Artur-
Copy link
Member

Artur- commented Feb 16, 2023

Describe your motivation

When compiling the frontend, Flow scans all entry points (routes and exported web components) and determines which components are reachable/imported through those entry points. The frontend files (JS/CSS) related to all found components are then added to target/frontend/generated-flow-imports.js and that becomes the main JS bundle. All other components found on the classpath are then added to target/frontend/generated-flow-imports-fallback.js in case they are needed even though the component scanner found no reference to them. Then there is JS written to generated-flow-imports.js so that the fallback bundle can be dynamically imported.

This whole complexity is added so that even if you use components only through reflection (super rare) or if there is a bug in the component scanner (which then should be fixed), then your production bundle will still contain all the components you use.

The whole world fallback bundle causes bad performance if a single component is left out, for one reason or another. Then you end up in loading the whole fallback bundle, possibly even on the initial load, just because one file is misplaced. In this case you would get much better performance by defining explicitly that the one file is needed and all the other files would be left out.

The whole world fallback also causes the production build for smaller applications to be much slower than necessary. Typically it is one or several of the large components you are not using (charts/spreadsheet/...) and they take the most time to process in build.

Describe the solution you'd like

Instead of "just in case" adding the whole world in a fallback bundle we should make it clear which components are included in the bundle so you can somehow verify that the list contains the component you use. If you use components only through reflection or if there is a bug in the scanner, you are able to add components to the included list by adding @Uses(TheComponent.class) to any entry point or class reached by any entry point.

@Legioth
Copy link
Member

Legioth commented Feb 17, 2023

One thing we could consider doing to limit the impact of removing the fallback bundle is to make the error handling clearer in the case when a component is missing from the bundle.

@Artur-
Copy link
Member Author

Artur- commented Apr 11, 2023

We seem to already include this in a production build stats.json

{
 "bundleImports": [
  "@vaadin-component-factory/vcf-nav",
  "@vaadin/app-layout/theme/lumo/vaadin-app-layout.js",
  "@vaadin/app-layout/theme/lumo/vaadin-drawer-toggle.js",
  "@vaadin/button/theme/lumo/vaadin-button.js",
  "@vaadin/common-frontend/ConnectionIndicator.js",
  "@vaadin/horizontal-layout/theme/lumo/vaadin-horizontal-layout.js",
  "@vaadin/notification/theme/lumo/vaadin-notification.js",
  "@vaadin/polymer-legacy-adapter/style-modules.js",
  "@vaadin/scroller/theme/lumo/vaadin-scroller.js",
  "@vaadin/text-field/theme/lumo/vaadin-text-field.js",
  "@vaadin/tooltip/theme/lumo/vaadin-tooltip.js",
  "@vaadin/vaadin-lumo-styles/color-global.js",
  "@vaadin/vaadin-lumo-styles/sizing.js",
  "@vaadin/vaadin-lumo-styles/spacing.js",
  "@vaadin/vaadin-lumo-styles/style.js",
  "@vaadin/vaadin-lumo-styles/typography-global.js",
  "@vaadin/vaadin-lumo-styles/vaadin-iconset.js",
  "@vaadin/vertical-layout/theme/lumo/vaadin-vertical-layout.js",
  "Frontend/generated/jar-resources/flow-component-renderer.js"
 ],
}

so if a @JsModule or similar is found and it is not in the bundleImport list, there is a problem that can be logged as an error

Artur- added a commit that referenced this issue Apr 16, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
Artur- added a commit that referenced this issue Apr 16, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
Artur- added a commit that referenced this issue Apr 17, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
Artur- added a commit that referenced this issue Apr 17, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
Artur- added a commit that referenced this issue Apr 17, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
Artur- added a commit that referenced this issue Apr 17, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
Artur- added a commit that referenced this issue Apr 17, 2023
The fallback chunk contained all JavaScript and CSS for classes which cannot be reached from an entry point (route or exported web component).
By removing it we improve performance as we do not need to scan all classes, only the reachable ones. We also fix issues with the license checker as it did not really know how to behave with commercial components that may or may not be used.

The drawback of removing the fallback chunk is that if you are using a component which is not reachable, as determined by the scanner, then your JS/CSS for the component will be missing. The typical case for this is having a factory that can create components using reflection. The scanner is not able to find the referenced classes as they only appear as a string in the source code. For this case, you need to add `@Uses(SomeComponent.class)` to the factory, for each component it can create using reflection.

To be able to detect unreachable components in development mode, you should set the `devmode.optimizeBundle` property to `true`.

Fixes #15929
@vaadin-bot
Copy link
Collaborator

This ticket/PR has been released with Vaadin 24.1.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging a pull request may close this issue.

3 participants