Stencil: Using stencil generated components in other projects

Created on 15 Dec 2017  Â·  31Comments  Â·  Source: ionic-team/stencil

I’ve been playing about with StencilJS and I’m absolutely loving it. I’ve read through the docs and looked at the various recommendations for using a component in our own apps. I really like the ability to use unpkg.com. However, I want to use it stand alone like the node_modules option but with the ability to package it up in a single js file. I don’t imagine this is possible due (to what i think is) the browser feature detection loading them in. Am I right in this assumption?
Docs
https://stenciljs.com/docs/distribution/

Cheers
Ally

enhancement

Most helpful comment

Yeah this is interesting, I think the compiler could also output a monolithic file too.

Would users be able to just add the script tag to the html and avoid webpack?

All 31 comments

We have a need for something like this as well. Here's my use case:

I'm replacing a set of AngularJS 1.x components with Stencil. Currently, the AngularJS components are packaged into a UMD bundle and loaded into lots of projects with Webpack.

The Stencil Webpack plugin might help with this, but we'd have to add the plugin to hundreds of Webpack configurations, which is a non-trivial amount of effort.

To make Stencil a drop-in replacement, I think we'd need a single-file UMD bundle of the components. This would obviously have a number of drawbacks (you'd likely include unnecessary polyfills, etc), but it would be the first step in our transition.

So this is to avoid having a directory of files that are self loading?

Kind of. The main goal is to make the transition to Stencil components seamless for app teams.

Currently each app bundles its dependencies and serves it up as as a monolithic Webpack bundle. So if there was a way to get something like import 'enterprise-reusable-components' to work without modifying the app's Webpack config, that would be allow us to drop-in replace things.

For my use case it wouldn't matter whether the app's Webpack bundle is a monolith or code-splits the Stencil components.

At the moment, my integration plan is:

  • Create a Stencil collection and host the dist/ files on a server somewhere
  • Create a wrapper UMD module that dynamically creates a <script> tag pointing to the collection's entry file and adds it to the page's <head>
  • App teams would then use the UMD module - so the Stencil components wouldn't be bundled with their app

Is this a reasonable approach?

Yeah this is interesting, I think the compiler could also output a monolithic file too.

Would users be able to just add the script tag to the html and avoid webpack?

There will be an interim period where we've transitioned some components to Stencil but others are AngularJS components still loaded via Webpack, so we can't bypass bundling entirely. Their own app code is also bundled via Webpack.

But yeah, as I'm talking out loud, I think not bundling the Stencil components with Webpack, and adding the script tag to the currently-generated dist/ folder for the Stencil components would let us progress. Whether app teams do it in their HTML, or I build the script tag dynamically in JS, it should have the same effect.

The @stencil/webpack package should be able to help accomplish this: https://www.npmjs.com/package/@stencil/webpack Hope that helps, thanks

Thanks for this, but I don't understand exactly how this webpack plugin would help bundling everything up into a single file. It looks like this plugin explicitly keeps the component code in separate chunks.

Yeah, I am having a hard time understanding how it is possible to consume any stencil built module in a project that is using another bundler (parcel, rollup or even require js wouldn't work). If there was some customizable way of allowing the elements to be initialized, it would be an excellent way to let some more flexibility without having to copy directories or to have very different public paths.

// some build runtime for the stencil generated core
import core from 'my-stencil-library/core';
// the vanilla component definition
import { MyButton } from 'my-stencil-library/components/my-button';

// Allow the core to initialize
core.initialize({
  components: {
    MyButton,
  },
}).then(() => {
  console.log('All good to go');
  const myButton = document.createElement('my-button');
  document.querySelector('#app').append(myButton);
});

I'm trying out stencil now but don't see support for http. What do I have to do for that? Thanks

@billp72 Are you wanting to make network requests to an API? If not could you explain what you are looking for a little more?

Yes, an external api. Thanks, Bill

On Wed, Feb 28, 2018 at 11:59 AM, Justin Willis notifications@github.com
wrote:

@billp72 https://github.com/billp72 Are you wanting to make network
requests to an API? If not could you explain what you are looking for a
little more?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ionic-team/stencil/issues/365#issuecomment-369304951,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKB2h0Q2ujz6gn2de0IJz9vcXw7mTPxhks5tZYS4gaJpZM4RD3wv
.

Ahh ok cool, we recommend you use the fetch api https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch which is built right into the browser.

Oh, sorry. What about post/put and the rest of the crud. Thanks

On Wed, Feb 28, 2018 at 12:26 PM, Justin Willis notifications@github.com
wrote:

Ahh ok cool, we recommend you use the fetch api
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
which is built right into the browser.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ionic-team/stencil/issues/365#issuecomment-369314584,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKB2h6QpUfrQ2s_nkXCYb3bHGqXyoMDxks5tZYvJgaJpZM4RD3wv
.

Please have a look at the 'Supplying request options' part of the docs in the link @jgw96 just mentioned. A POST example is right there. It shouldn't be a problem to create a PUT request from there.

Good question! The fetch API supports different http methods, applying headers, handling credentials and more. The "Making fetch requests" part of that link i sent you above has examples.

In a stencil class, can I write a constructor?

Thanks again

On Wed, Feb 28, 2018 at 12:32 PM, Justin Willis notifications@github.com
wrote:

Good question! The fetch API supports different http methods, applying
headers, handling credentials and more. The "Making fetch requests" part of
that link i sent you above has examples.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ionic-team/stencil/issues/365#issuecomment-369317506,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKB2h-FGyu6H6BwvlXS1FHwD_qXo9lxnks5tZY2_gaJpZM4RD3wv
.

Yep! Web components are just ES6 classes

So long as i have your attention, I'm trying to run that ecommerce PWA I
found on your git. I tried running: ionic build and then ionic serve but
received errors. I didn't see a readMe. Any advice?

thanks

On Wed, Feb 28, 2018 at 3:03 PM, Justin Willis notifications@github.com
wrote:

Yep! Web components are just ES6 classes

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ionic-team/stencil/issues/365#issuecomment-369365045,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKB2h_uoIGobaRHX6ZSXTYtlOLyZpAbeks5tZbD-gaJpZM4RD3wv
.

Here's a more reasonable question. After making an async call, I want to
set my state so it re-renders once fetch has completed. I'm using
"componentDidLoad" because it executes after everything is rendered
((then)) I simply set my state like: this.content = response.

@State() content: any;

I console log inside render. And while the data is eventually coming, it's
not re-firing render again so I get a run-time error because stuff is
undefined. What am I doing wrong?

thanks

On Wed, Feb 28, 2018 at 3:11 PM, BP epop.bill@gmail.com wrote:

So long as i have your attention, I'm trying to run that ecommerce PWA I
found on your git. I tried running: ionic build and then ionic serve but
received errors. I didn't see a readMe. Any advice?

thanks

On Wed, Feb 28, 2018 at 3:03 PM, Justin Willis notifications@github.com
wrote:

Yep! Web components are just ES6 classes

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ionic-team/stencil/issues/365#issuecomment-369365045,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKB2h_uoIGobaRHX6ZSXTYtlOLyZpAbeks5tZbD-gaJpZM4RD3wv
.

Any movement on how we can integrate StencilJS components with other frameworks using standard imports?
Would be nice to get a monolithic distribution option

@wesgro I really wanted to use StencilJS but this build complication means I haven't been able to fit it into my build process easily. I've had much more success with Svelte though - I was up and running quickly, it compiles easily into a monolith and has support for several different loaders.

Thanks @willtj! I'll have a look at Svelte in the mean time.

I've been loving Stencil so far, but ran into a similar scenario where I needed to use it in an environment that uses require.js. It can be done, but the distribution process would be very bad due to the file dependencies. Having a single file distribution would be really helpful.
Edit: @mattdsteele, your approach will make my life easier! Haha. That's a good idea and would "simulate" the most common use for Stencil. Thanks!

An update - integrating into other environments is a lot better now. Namely you can produce a dist/esm folder for your library, which can be bundled with Webpack or Rollup.

See https://stenciljs.com/docs/framework-integration/ for more details.

@pedropmota for AMD environments like RequireJS, you'll probably need to do the "dynamically generate a script tag" dance.

Thanks for replying, @mattdsteele. Unfortunately, RequireJS makes it behave weirdly even by adding the dynamic script tag to the page. When the component is about to be rendered inside the RequireJS "flow", the main component script file tries to load the other js files from a different location. It's like it doesn't know what's the base URL for those files when it's loaded by RequireJS.

Anyway, just sharing my experience in that scenario, although I assume it's not a common one at all. Thanks!

A possible way to fix this (which we used) is to require an intermediate script, something like:

(function() {
  var toolkitUri = 'https://example.org/assets/js/components/name';

  var t = document.createElement('script');
  t.type = 'text/javascript';
  t.setAttribute('data-resources-url', toolkitUri +'/');
  t.src = toolkitUri +'.js';
  document.body.appendChild(t);
})()

@julesjanssen, thanks a lot! The data-resources-url attribute actually didn't seem to be required for my scenario (although I'm leaving it anyway), but your document.body.appendChild enlightened my path since I was doing document.head.appendChild and it was loading the library before RequireJS was loaded. I got a perfect scenario now. Thanks!

any news regarding the ability to bundle a StencilJS component into a single file? similar to what Angular Elements/ Vue web components wrapper do?

I'm trying to load a stencil component using requirejs and seem to also be running into this issue:

https://github.com/ionic-team/stencil/issues/365#issuecomment-411078373

Access to script at 'https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/iiifgallery/iiifgallery.udwqux00.js' from origin 'http://localhost:5001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Here's my test page:

https://github.com/edsilv/requirejs-stencil-test/blob/master/index.html

Apologies, but I don't understand how to apply @julesjanssen's intermediate script fix - could someone give me some pointers?

No worries, have solved it and updated my example page.
I found that it started working after removing data-resources-url.

Can we please revisit this feature? My team is using requirejs and umd, and we're having so many problems integrating our components. At least the monolith umd.min.js would help team integrate components very easily

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MatanYadaev picture MatanYadaev  Â·  3Comments

kensodemann picture kensodemann  Â·  3Comments

glemiere picture glemiere  Â·  3Comments

bekliev picture bekliev  Â·  3Comments

ryanmunger picture ryanmunger  Â·  3Comments