ionic-team / stencil

A toolchain for building scalable, enterprise-ready component systems on top of TypeScript and Web Component standards. Stencil components can be distributed natively to React, Angular, Vue, and traditional web developers from a single, framework-agnostic codebase.
https://stenciljs.com
Other
12.5k stars 784 forks source link

bug: All stencil components are imported in Angular even if only one is called #5952

Open Loic57 opened 3 weeks ago

Loic57 commented 3 weeks ago

Prerequisites

Stencil Version

4.20

Current Behavior

I followed this documentationt to build a monorepo with stencil and angular : https://stenciljs.com/docs/angular Nothing less, nothing more.

When running my angular app I can see in the network tab in my console that my two stencil components are loaded whereas I only need one. image

In my app.component.ts (angular 18.2 in standalone mode) I call only "my-component" but my two components are called in the console.

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { MyComponent } from 'component-library';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet, MyComponent],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'my-app';
}

Expected Behavior

I would like to load only the right component, not everything at once.

System Info

System: node 20.15.1
    Platform: windows (10.0.19045)
   CPU Model: 11th Gen Intel(R) Core(TM) i5-11600K @ 3.90GHz (12 cpus)
    Compiler:  [HIDDEN]\@stencil\core\compiler\stencil.js
       Build: 1722623140
     Stencil: 4.20.0
  TypeScript: 5.5.3
      Rollup: 2.56.3
      Parse5: 7.1.2
      jQuery: 4.0.0-pre
      Terser: 5.31.1

Steps to Reproduce

git clone https://github.com/Loic57/stencil-angular-18 npm i (be sure to have lerna installed) go to packages/stencil-library and run : npm run build go to packages/angular-workspace and run : npx -p @angular/cli ng build component-library go to packages/angular-workspace/projects/my-app and run : npm run start

The browser should open on localhost:4200 and you should see "Hell, i'm a test" which is shipped by default with stencil.

But if you inspect the network tab in the console you should see another component name created by myself but which is not called in app.component.ts

Code Reproduction URL

https://github.com/Loic57/stencil-angular-18

Additional Information

No response

Loic57 commented 3 weeks ago

There is something which disturb me a lot. In the documentation it says : By default, the dist-custom-elements output target generates a single file per component, and exports each of those files individually.

But, in the angular documentation it says : The configuration for the Custom Elements output target must set the export behavior to single-export-module for the wrappers to generate correctly if using the scam or standalone output type.

So, in one side it says, "keep customElementsExportBehavior on default to have one component per file" and on the other side it says "change customElementsExportBehavior to 'single-export-module' if you need standalone components"

But single-export-module' regroups all the components into one index.js file.

I'm lost

louisschandeler commented 2 weeks ago

Hello,

I encounter exactly the same problem. However in our case, we use more than 50 components and the JS coming from the stencil components is more than 10MB in our angular app. However we followed the stencil documentation for standalone component in angular.

We are in a situation where putting an app into production is no longer possible for our organization due to the size of the stencil javascript.

I hope the stencil team can help us to use/call real standalone components. Thanks in advance

roni0101 commented 1 week ago

We are facing the same issue. When importing a component from stencil.js library to an angular app, all exported components get loaded and registered although only one was imported. Is there a workaround or a different configuration that will fix this. Our stencil.config has:

{ type: 'dist', esmLoaderPath: '../loader', }, { type: 'dist-custom-elements', customElementsExportBehavior: 'single-export-module', }, angularOutputTarget({ componentCorePackage: 'our-lib', customElementsDir: 'dist/components', outputType: 'standalone', directivesProxyFile: '../angular-lib/src/lib/components.ts', directivesArrayFile: '../angular-lib/src/lib/index.ts', }),

djount commented 1 week ago

Same issue here, at the beginning we thought it was an issue with Angular 18 but we did some tests on Angular 17 and 16.2 and this is the same. All components are loaded at the same time. We have around 30 components built with stencil and the page is quite heavy.

Are there any solutions ?

christian-bromann commented 1 week ago

Hey you all 👋 we currently have a lot of competing priorities and can't give every issue the attention it deserves. We recommend at this point to help the project by contributing a patch that may help to resolve the issue. We are happy to answer any questions that may arrise.

andberg commented 18 minutes ago

@Loic57 - Could it be the issue that is described here for React-output target? It says; "When you look at the components generated by stencils in typescript, they are all prepended by the comment “/@PURE/”. As we saw in the previous article, this comment serves as an indicator to the bundler, signaling that these components are pure functions and can be safely removed if they are not directly invoked by the application." The solution was to add the following to the typescript config:

"compilerOptions": {
      "removeComments": false

We are having the same issue that you describe, but we export our component-library as an Angular Module. So teams that consumes it import the entire module. When we went from Angular 16 to 17 and from Stencil 3 to 4 (which unfortunately was the same PR) we got this problem with thee-shaking. If a team only use a button, they don't get just the button, they get everything. We are investigating this now, but takes a while to see what's what. :)