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 783 forks source link

Importing Stencil-generated custom elements in another Stencil project fails #2531

Open lxg opened 4 years ago

lxg commented 4 years ago

Stencil version:

@stencil/core@1.15.0-4

I'm submitting a:

[x ] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

When I create a set of custom elements with Stencil using the dist-custom-elements-bundle target and try to use them in another Stencil project by registering the custom element with customElements.define, I get the following errors in the console:

my-component.entry.js:2673 stencil Trying to lazily load component <ui-button> with style mode "undefined", but it does not exist.

my-component.entry.js:1906 Uncaught (in promise) TypeError: Cannot read property 'then' of undefined
    at initializeComponent (my-component.entry.js:1906)
    at my-component.entry.js:2059

When I import the component in the same way in a project that isn’t Stencil, it works fine. (#2516 aside.)

Steps to reproduce:

I have created a demo here: https://github.com/lxg/stencil-elements-poc

jainanuj0812 commented 3 years ago

Facing the same problem,

Any update?

Paitum commented 3 years ago

I am facing a similar problem. Is there clear guidance on how to use a Stencil Component Library's "custom elements" output within another Stencil Component Project?

The use-case here is a set of shared-base-components being used within multiple application-web-components. This is analogous to Angular Material components being used within many Angular Applications.

A consumer of one of the application would be responsible for loading the application web components and NOT be responsible for loading the shared components.

Paitum commented 3 years ago

It appears only using dist-custom-elements-bundle was affecting my outcome. Once using BOTH dist and dist-custom-elements-bundle it started working. This could also be due to how my package.json file is configured to reference many undefined files within dist/.

Clear documentation on this use-case would be a huge benefit. I assume StencilJS projects consuming other StencilJS components would be a use-case worth documenting, for both build-time linking and runtime lazyloading scenarios.

SheepFromHeaven commented 3 years ago

Any updates here? This is really keeping stencil from being scalable. I had a look into the stencil runtime and it seems the initializeComponent function does not care about the source of a component. It just looks if the build is lazy. There I currently no way to do this, as far as I see it!

SheepFromHeaven commented 3 years ago

BTW: Still a problem in 2.4.0

MarkChrisLevy commented 3 years ago

I made appropriate changes in stencil compiler and runtime and it now works - you may check it https://github.com/CODE-AND-MORE/stencil/tree/codeandmore (build and test or npm install github:CODE-AND-MORE/stencil-core-build). With those changes it is now possible to import components generated only as dist-custom-elements-bundle and use them with other stencil project that build lazy components. I'm not making a PUSH request yet, cause there are other things to be done to improve dist-custom-elements-bundle.

Quick summary of changes:

MarkChrisLevy commented 3 years ago

@lxg @SheepFromHeaven Can you test my fork and check it for your use case?

lxg commented 3 years ago

Hi, sorry, I’m not using Stencil in current projects anymore … switched to pure TSX for web components.

SheepFromHeaven commented 3 years ago

@MarkChrisLevy was on vacation. Will try 👍 thx!

SheepFromHeaven commented 3 years ago

Hey @MarkChrisLevy. I tried, but it did not seem to work. I installed your version in both of the projects. As soon as I import one of the components in my lazy bundle, the whole library is being imported 🙁

MarkChrisLevy commented 3 years ago

@SheepFromHeaven Hmm, I'm using it without any issues. Can you show me your stencil conf for building a component? See how I'm doing it: ionx.

MarkChrisLevy commented 3 years ago

As far I know Stencil team plans to improve CustomElements output target and would be great to hear more about it, any word @rwaskiewicz in this topic? Thanks.

rwaskiewicz commented 3 years ago

Hey all 👋 I don't have anything concrete to share at the moment as far as timelines are concerned on specific improvements.

@MarkChrisLevy did you have any specific thoughts on how to improve the CustomElements output target?

MarkChrisLevy commented 3 years ago

@rwaskiewicz Uhh, sorry for not answering, I didn't see your reply. There are several issues with current implementation of CustomElements, the main issue is that it cannot be used alongside with LazyLoad build - CustomElements components just doesn't load. Please have a look what I did to make it work and some nice improvements: https://github.com/ionic-team/stencil/issues/2531#issuecomment-808082875

danemesis commented 2 years ago

It does work for me on the latest stencil generated by npm init stencil

package.json

{
  "name": "core",
  "version": "0.0.1",
  "description": "Core set of material components",
  "main": "dist/index.cjs.js",
  "module": "dist/index.js",
  "es2015": "dist/esm/index.mjs",
  "es2017": "dist/esm/index.mjs",
  "types": "dist/types/components.d.ts",
  "collection": "dist/collection/collection-manifest.json",
  "collection:main": "dist/collection/index.js",
  "unpkg": "dist/core/core.esm.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/ionic-team/stencil-component-starter.git"
  },
  "files": [
    "dist/",
    "loader/"
  ],
  "scripts": {
    "build": "stencil build --docs",
    "start": "stencil build --dev --watch --serve",
    "test": "stencil test --spec --e2e",
    "test.watch": "stencil test --spec --e2e --watchAll",
    "generate": "stencil generate"
  },
  "dependencies": {
    "@stencil/core": "^2.11.0",
    "@types/hammerjs": "^2.0.41",
    "hammerjs": "^2.0.8",
    "lozad": "^1.16.0"
  },
  "devDependencies": {
    "@stencil/postcss": "^2.1.0",
    "@stencil/sass": "^1.5.2",
    "@types/jest": "^26.0.24",
    "autoprefixer": "^10.4.2",
    "jest": "^26.6.3",
    "jest-cli": "^26.6.3",
    "puppeteer": "^10.0.0"
  },
  "license": "MIT"
}

stencil.config.ts

import { Config } from '@stencil/core';
import { sass } from '@stencil/sass';
import { postcss } from '@stencil/postcss';
import autoprefixer from 'autoprefixer';

export const config: Config = {
  namespace: 'core',
  outputTargets: [
    {
      type: 'dist',
      esmLoaderPath: '../loader',
    },
    {
      type: 'dist-custom-elements',
    },
    {
      type: 'docs-readme',
    },
    {
      type: 'www',
      serviceWorker: null, // disable service workers
    },
  ],
  plugins: [
    sass(),
    postcss({
      plugins: [autoprefixer()],
    }),
  ],
};

stencil elements are just normal elements. in a project you want to reference you just add package as dependency and in global.ts you add import 'core';

orl99 commented 2 years ago

is there any update???

thibert commented 2 years ago

+1 !!! I can't make it work in my project also. Too sad to not be able to build a WebComponent with Stencil which embed few components from my Stencil Library... It will work if you embed your entire collection but not acceptable in terms of weight and good practices.

Hope it will be fixed soon :)

thibert commented 2 years ago

@rwaskiewicz do you have any news to share ? Thank you

duncanhunter commented 1 year ago

Does Ionic/Stencil have any advice on how to write unit or e2e tests in a stencil project that depends on other stencil projects' compiled components?

We are considering running these tests in Playwright or Cypress, as we have a mono repo with a base library of stencil components and another library of stencil components that use the base library. Ideally, we would prefer just to use the stencil testing setup.

Before stencil v4 we just did a hacky direct path to the other library's component, but now it is not working and trying to find a better solution.

Ideally, it would be better to have some guidance on registering custom elements from any source in the stencil unit or e2e tests.

Or, if this is not possible, some reply to this thread would be much appreciated.

j3rmzy commented 9 months ago

Wondering if anyone has been able to get this working in the context of unit tests? Similar to @duncanhunter's issue. Was originally getting 'Cannot use import statement outside a module' which I understand to be an ES module and CommonJS issue so used 'babel-jest' to transform the source code correctly for the Jest tests. However, I've hit another issue were I'm using 'template' within my spec tests to render the component and now I'm getting unexpected token on the opening tag.

Here is what my test file looks like:

// my-text.spec.tsx
import { newSpecPage } from '@stencil/core/testing';
import { Text } from './my-text';
import { h } from '@stencil/core';
import { MyButton } from 'component-library-a/dist/components/my-button';
// ^^^ Previously errored: 'Cannot use import statement outside a module' but fixed by using 'babel-jest'.

it('should render my component', async () => {
  const page = await newSpecPage({
    components: [Text, MyButton],
    template: () => (
      <my-text ......></my-text> // ERROR: Unexpected token: '<'
    )
  });
  expect(page.root).toEqualHtml(`......

...so it's very basic.

Error:

template: () => <my-text></my-text>
                ^
SyntaxError: Unexpected token '<'

I have also set @babel/present-env in babel.config.json and "@babel/plugin-syntax-jsx" as the plugin but still no luck.

Having to manually set babel-jest doesn't seem right. I would've expected the jest-preprocessor which is the default transform provided by Stencil to do the job already.

I've added this comment here as it's a knock on from trying to figure out how to import a Stencil component library into another Stencil component library.

duncanhunter commented 9 months ago

We reverted from having stencil project that depends on other stencil projects and avoid the headaches.