Custom Elements Bundle
The dist-custom-elements-bundle
output target is used to generate a custom elements as a single bundle. The output can be "single" bundle because it's generated to ensure components are tree-shakable. For example, if a component library has 100 components, but an external project only imported one component from the bundle, then only the code used by that one component would be pulled into the project. This is due to Stencil's use of ES Modules and the compiler generating friendly code for bundlers to parse and understand.
outputTargets: [
{
type: 'dist-custom-elements-bundle'
}
]
Defining Exported Custom Elements
By default, the custom elements bundle will be written to
dist/custom-elements-bundle/index.mjs
. This directory can be configured using the output target's
dir
config. The generated
index.mjs
contains exports to each component class and will have their styles included within the bundle. However, this build does not automatically define the custom elements, or apply any polyfills.
Below is an example of defining a custom element within the bundle:
import { HelloWorld } from 'my-library/dist/custom-elements-bundle';
customElements.define('hello-world', HelloWorld);
For convinence, the bundle also exports a
defineCustomElements()
method. When the
defineCustomElements()
is called it will define each component in the bundle. However, it does not run automatically and it will not be called if it is not imported and executed.
Also note that the generated bundle will export each component class and will already have the styles bundled. However, it does not define the custom elements, or apply any polyfills.
Distributing Custom Elements
Your component library can be easily distributed on NPM, similar to how
@ionic/core
does it. From there consumers of your library can decide how to import your library into their project. For the
dist-custom-elements-bundle
, the default import location would be
my-library/dist/custom-elements-bundle
, but this can get further configured within the
package.json
file.
To make this bundle the entry module for a package, set the package.json
's module
property to:
{
"module": "dist/custom-elements-bundle/index.mjs"
}
Note: If you are distributing both the dist
and
dist-custom-elements-bundle
, then it's best to choose which one of them should be the
module
entry, but that's up to you.
Next you can publish your library to Node Package Manager (NPM). For more information about setting up the
package.json
file, and publishing, see:
Publishing Component Library To NPM.
How is this different than "dist" output target?
The dist-custom-elements-bundle
builds each component as a stand-alone class that extends
HTMLElement
. The output is a standardized custom element with the styles already attached and without any of Stencil's lazy-loading. This may be preferred for projects that are already handling bundling, lazy-loading and defining the custom elements themselves.
The dist
output target on the other hand is more for projects that want to be able allow each component to lazy-load themselves, without having to setup bundling configurations to do so.
Luckily, both builds can be generated at the same time, and shipped in the same distribution. It would be up to the consumer of your component library to decide which build to use.
Legacy Browsers
If the library is to be used on IE11 we recommand using the
dist
output target instead since it will only load the required polyfills on-demand. The
dist-custom-elements-bundle
we only recommend if for modern browsers that already support Custom Elements, Shadow DOM and CSS Variables (basically not IE11 or Edge 18 and below). If this this build is going to be used within legacy browsers then the project consuming these components will have to provide its own polyfills, and correctly downlevel the output to ES5.
Good news is that they're all widely supported for modern web develoment: