# Table of Contents - [Styling Components | Stencil](#styling-components-stencil) - [Search the documentation | Stencil](#search-the-documentation-stencil) - [Build Constants | Stencil](#build-constants-stencil) - [Angular Integration with Stencil | Stencil](#angular-integration-with-stencil-stencil) - [Stencil Core CLI API | Stencil](#stencil-core-cli-api-stencil) - [Stencil Core Compiler API | Stencil](#stencil-core-compiler-api-stencil) - [Stencil CLI | Stencil](#stencil-cli-stencil) - [Stencil Core Dev Server API | Stencil](#stencil-core-dev-server-api-stencil) - [Stencil Copy Tasks | Stencil](#stencil-copy-tasks-stencil) - [Extras Config | Stencil](#extras-config-stencil) - [Stencil Documentation Generation | Stencil](#stencil-documentation-generation-stencil) - [Distributing Web Components Built with Stencil | Stencil](#distributing-web-components-built-with-stencil-stencil) - [Component Lifecycle Methods | Stencil](#component-lifecycle-methods-stencil) - [Component API | Stencil](#component-api-stencil) - [Documentation Generation Config | Stencil](#documentation-generation-config-stencil) - [Component Decorator | Stencil](#component-decorator-stencil) - [Integrated Dev Server Config | Stencil](#integrated-dev-server-config-stencil) - [Build Constants | Stencil](#build-constants-stencil) - [Custom Docs Generation | Stencil](#custom-docs-generation-stencil) - [Content Security Policy Nonces | Stencil](#content-security-policy-nonces-stencil) - [VS Code Documentation | Stencil](#vs-code-documentation-stencil) - [Config | Stencil](#config-stencil) - [Design Systems | Stencil](#design-systems-stencil) - [Ember Integration with Stencil | Stencil](#ember-integration-with-stencil-stencil) - [Stencil Goals and Objectives | Stencil](#stencil-goals-and-objectives-stencil) - [Assets | Stencil](#assets-stencil) - [Custom Elements with Stencil | Stencil](#custom-elements-with-stencil-stencil) - [Docs JSON Data Output Target | Stencil](#docs-json-data-output-target-stencil) - [Stencil - A Compiler for Web Components | Stencil](#stencil-a-compiler-for-web-components-stencil) - [Framework Integration | Stencil](#framework-integration-stencil) - [Stencil Frequently Asked Questions | Stencil](#stencil-frequently-asked-questions-stencil) - [Plugin Config | Stencil](#plugin-config-stencil) - [Stencil Output Targets | Stencil](#stencil-output-targets-stencil) - [Components without a Framework | Stencil](#components-without-a-framework-stencil) - [Build Constants | Stencil](#build-constants-stencil) - [Prerender Config | Stencil](#prerender-config-stencil) - [Deploying a Static Site | Stencil](#deploying-a-static-site-stencil) - [Combining Server Side Rendering and Static Site Generation | Stencil](#combining-server-side-rendering-and-static-site-generation-stencil) - [SEO Meta Tags in SSG | Stencil](#seo-meta-tags-in-ssg-stencil) - [Telemetry | Stencil](#telemetry-stencil) - [Static Site Generation Basics in Stencil | Stencil](#static-site-generation-basics-in-stencil-stencil) - [Support Policy | Stencil](#support-policy-stencil) - [Build Constants | Stencil](#build-constants-stencil) - [Custom Elements with Stencil | Stencil](#custom-elements-with-stencil-stencil) - [Telemetry | Stencil](#telemetry-stencil) - [Webapp Output Target | Stencil](#webapp-output-target-stencil) - [Deploying a Static Site | Stencil](#deploying-a-static-site-stencil) - [Events | Stencil](#events-stencil) - [Combining Server Side Rendering and Static Site Generation | Stencil](#combining-server-side-rendering-and-static-site-generation-stencil) - [Events | Stencil](#events-stencil) - [Docs JSON Data Output Target | Stencil](#docs-json-data-output-target-stencil) - [Stencil Core Dev Server API | Stencil](#stencil-core-dev-server-api-stencil) - [Distributing Web Components Built with Stencil | Stencil](#distributing-web-components-built-with-stencil-stencil) - [Stencil CLI | Stencil](#stencil-cli-stencil) - [Telemetry | Stencil](#telemetry-stencil) - [Support Policy | Stencil](#support-policy-stencil) - [Plugin Config | Stencil](#plugin-config-stencil) - [Stencil Core CLI API | Stencil](#stencil-core-cli-api-stencil) - [Support Policy | Stencil](#support-policy-stencil) - [Stencil - A Compiler for Web Components | Stencil](#stencil-a-compiler-for-web-components-stencil) - [Webapp Output Target | Stencil](#webapp-output-target-stencil) - [Hydrate App | Stencil](#hydrate-app-stencil) - [Stencil Core CLI API | Stencil](#stencil-core-cli-api-stencil) - [Stencil Goals and Objectives | Stencil](#stencil-goals-and-objectives-stencil) - [Stencil Goals and Objectives | Stencil](#stencil-goals-and-objectives-stencil) - [Stencil - A Compiler for Web Components | Stencil](#stencil-a-compiler-for-web-components-stencil) - [Functional Components | Stencil](#functional-components-stencil) - [Prerender Config | Stencil](#prerender-config-stencil) - [Upgrading to Stencil v4.0.0 | Stencil](#upgrading-to-stencil-v4-0-0-stencil) - [Stencil Style Guide | Stencil](#stencil-style-guide-stencil) - [Stencil - A Compiler for Web Components | Stencil](#stencil-a-compiler-for-web-components-stencil) - [Stencil CLI | Stencil](#stencil-cli-stencil) - [VS Code Documentation | Stencil](#vs-code-documentation-stencil) - [VS Code Documentation | Stencil](#vs-code-documentation-stencil) - [Prerender Config | Stencil](#prerender-config-stencil) - [Deploying a Static Site | Stencil](#deploying-a-static-site-stencil) - [Integrated Dev Server Config | Stencil](#integrated-dev-server-config-stencil) - [Stencil Documentation Generation | Stencil](#stencil-documentation-generation-stencil) - [Static Site Generation | Stencil](#static-site-generation-stencil) - [Integrated Dev Server Config | Stencil](#integrated-dev-server-config-stencil) - [Combining Server Side Rendering and Static Site Generation | Stencil](#combining-server-side-rendering-and-static-site-generation-stencil) - [Docs JSON Data Output Target | Stencil](#docs-json-data-output-target-stencil) - [Methods | Stencil](#methods-stencil) - [Stencil Core Compiler API | Stencil](#stencil-core-compiler-api-stencil) - [Combining Server Side Rendering and Static Site Generation | Stencil](#combining-server-side-rendering-and-static-site-generation-stencil) - [Using JSX | Stencil](#using-jsx-stencil) - [Docs JSON Data Output Target | Stencil](#docs-json-data-output-target-stencil) - [Documentation Generation Config | Stencil](#documentation-generation-config-stencil) - [Stencil Output Targets | Stencil](#stencil-output-targets-stencil) - [Distributing Web Components Built with Stencil | Stencil](#distributing-web-components-built-with-stencil-stencil) - [Getting Started | Stencil](#getting-started-stencil) - [Static Site Generation Basics in Stencil | Stencil](#static-site-generation-basics-in-stencil-stencil) - [Versioning | Stencil](#versioning-stencil) - [Deploying a Static Site | Stencil](#deploying-a-static-site-stencil) - [Internal state | Stencil](#internal-state-stencil) - [Storybook Integration | Stencil](#storybook-integration-stencil) - [Getting Started | Stencil](#getting-started-stencil) - [Properties | Stencil](#properties-stencil) - [Styling Components | Stencil](#styling-components-stencil) - [Docs Readme Auto-Generation | Stencil](#docs-readme-auto-generation-stencil) - [Form-Associated Components | Stencil](#form-associated-components-stencil) - [Extras Config | Stencil](#extras-config-stencil) - [Components without a Framework | Stencil](#components-without-a-framework-stencil) - [Events | Stencil](#events-stencil) - [Store | Stencil](#store-stencil) - [Distributing Web Components Built with Stencil | Stencil](#distributing-web-components-built-with-stencil-stencil) - [Internal state | Stencil](#internal-state-stencil) - [Server Side Rendering | Stencil](#server-side-rendering-stencil) - [Custom Docs Generation | Stencil](#custom-docs-generation-stencil) - [Methods | Stencil](#methods-stencil) - [Typed Components | Stencil](#typed-components-stencil) - [Framework Integration | Stencil](#framework-integration-stencil) - [Store | Stencil](#store-stencil) - [Stencil Style Guide | Stencil](#stencil-style-guide-stencil) - [Web Workers | Stencil](#web-workers-stencil) - [Build Conditionals | Stencil](#build-conditionals-stencil) - [Design Systems | Stencil](#design-systems-stencil) - [Web Workers | Stencil](#web-workers-stencil) - [Build Conditionals | Stencil](#build-conditionals-stencil) - [Working with host elements | Stencil](#working-with-host-elements-stencil) - [Styling Components | Stencil](#styling-components-stencil) - [Module Bundling | Stencil](#module-bundling-stencil) - [Design Systems | Stencil](#design-systems-stencil) - [Typed Components | Stencil](#typed-components-stencil) - [Component API | Stencil](#component-api-stencil) - [Reactive Data, Handling arrays and objects | Stencil](#reactive-data-handling-arrays-and-objects-stencil) - [Testing | Stencil](#testing-stencil) - [Framework Integration | Stencil](#framework-integration-stencil) - [Stencil Style Guide | Stencil](#stencil-style-guide-stencil) - [Module Bundling | Stencil](#module-bundling-stencil) - [Content Security Policy Nonces | Stencil](#content-security-policy-nonces-stencil) - [Stencil Frequently Asked Questions | Stencil](#stencil-frequently-asked-questions-stencil) - [Publishing A Component Library | Stencil](#publishing-a-component-library-stencil) - [Debugging With VS Code | Stencil](#debugging-with-vs-code-stencil) - [Service Workers | Stencil](#service-workers-stencil) - [Getting Started | Stencil](#getting-started-stencil) - [Forms | Stencil](#forms-stencil) - [Testing | Stencil](#testing-stencil) - [Testing | Stencil](#testing-stencil) - [Custom Elements with Stencil | Stencil](#custom-elements-with-stencil-stencil) - [Custom Elements with Stencil | Stencil](#custom-elements-with-stencil-stencil) - [Publishing A Component Library | Stencil](#publishing-a-component-library-stencil) - [Component API | Stencil](#component-api-stencil) - [Component Lifecycle Methods | Stencil](#component-lifecycle-methods-stencil) - [Telemetry | Stencil](#telemetry-stencil) - [Component Decorator | Stencil](#component-decorator-stencil) - [Form-Associated Components | Stencil](#form-associated-components-stencil) - [Webapp Output Target | Stencil](#webapp-output-target-stencil) - [Working with host elements | Stencil](#working-with-host-elements-stencil) - [Functional Components | Stencil](#functional-components-stencil) - [SEO Meta Tags in SSG | Stencil](#seo-meta-tags-in-ssg-stencil) - [Methods | Stencil](#methods-stencil) - [Properties | Stencil](#properties-stencil) - [Reactive Data, Handling arrays and objects | Stencil](#reactive-data-handling-arrays-and-objects-stencil) - [Internal state | Stencil](#internal-state-stencil) - [Using JSX | Stencil](#using-jsx-stencil) - [Framework Integration | Stencil](#framework-integration-stencil) - [Static Site Generation | Stencil](#static-site-generation-stencil) - [Config | Stencil](#config-stencil) - [Stencil Core Dev Server API | Stencil](#stencil-core-dev-server-api-stencil) - [Hydrate App | Stencil](#hydrate-app-stencil) - [Plugin Config | Stencil](#plugin-config-stencil) - [Hydrate App | Stencil](#hydrate-app-stencil) - [Storybook Integration | Stencil](#storybook-integration-stencil) - [Functional Components | Stencil](#functional-components-stencil) - [Stencil Output Targets | Stencil](#stencil-output-targets-stencil) - [Upgrading to Stencil v4.0.0 | Stencil](#upgrading-to-stencil-v4-0-0-stencil) - [WebdriverIO Overview | Stencil](#webdriverio-overview-stencil) - [Vitest | Stencil](#vitest-stencil) - [Server Side Rendering | Stencil](#server-side-rendering-stencil) - [React Integration with Stencil | Stencil](#react-integration-with-stencil-stencil) - [Angular Integration with Stencil | Stencil](#angular-integration-with-stencil-stencil) - [Stencil Core Dev Server API | Stencil](#stencil-core-dev-server-api-stencil) - [Stencil Documentation Generation | Stencil](#stencil-documentation-generation-stencil) - [WebdriverIO Overview | Stencil](#webdriverio-overview-stencil) - [WebdriverIO Overview | Stencil](#webdriverio-overview-stencil) - [Vitest | Stencil](#vitest-stencil) - [Vitest | Stencil](#vitest-stencil) - [Plugin Config | Stencil](#plugin-config-stencil) - [Documentation Generation Config | Stencil](#documentation-generation-config-stencil) - [Stencil Goals and Objectives | Stencil](#stencil-goals-and-objectives-stencil) - [Jest | Stencil](#jest-stencil) - [Support Policy | Stencil](#support-policy-stencil) - [Versioning | Stencil](#versioning-stencil) - [Upgrading to Stencil v4.0.0 | Stencil](#upgrading-to-stencil-v4-0-0-stencil) - [VS Code Documentation | Stencil](#vs-code-documentation-stencil) --- # Styling Components | Stencil [Skip to main content](https://stenciljs.com/docs/styling#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page Shadow DOM[​](https://stenciljs.com/docs/styling#shadow-dom "Direct link to Shadow DOM") ----------------------------------------------------------------------------------------- ### What is the Shadow DOM?[​](https://stenciljs.com/docs/styling#what-is-the-shadow-dom "Direct link to What is the Shadow DOM?") The [shadow DOM](https://developers.google.com/web/fundamentals/web-components/shadowdom) is an API built into the browser that allows for DOM encapsulation and style encapsulation. It is a core aspect of the Web Component standards. The shadow DOM shields a component's styles, markup, and behavior from its surrounding environment. This means that we do not need to be concerned about scoping our CSS to our component, nor worry about a component's internal DOM being interfered with by anything outside the component. When talking about the shadow DOM, we use the term "light DOM" to refer to the "regular" DOM. The light DOM encompasses any part of the DOM that does not use the shadow DOM. ### Shadow DOM in Stencil[​](https://stenciljs.com/docs/styling#shadow-dom-in-stencil "Direct link to Shadow DOM in Stencil") The shadow DOM hides and separates the DOM of a component in order to prevent clashing styles or unwanted side effects. We can use the shadow DOM in our Stencil components to ensure our components won't be affected by the applications in which they are used. To use the Shadow DOM in a Stencil component, you can set the `shadow` option to `true` in the component decorator. @Component({ tag: 'shadow-component', styleUrl: 'shadow-component.css', shadow: true,})export class ShadowComponent {} If you'd like to learn more about enabling and configuring the shadow DOM, see the [shadow field of the component api](https://stenciljs.com/docs/component#component-options) . By default, components created with the [`stencil generate` command](https://stenciljs.com/docs/cli#stencil-generate) use the shadow DOM. ### Styling with the Shadow DOM[​](https://stenciljs.com/docs/styling#styling-with-the-shadow-dom "Direct link to Styling with the Shadow DOM") With the shadow DOM enabled, elements within the shadow root are scoped, and styles outside of the component do not apply. As a result, CSS selectors inside the component can be simplified, as they will only apply to elements within the component. We do not have to include any specific selectors to scope styles to the component. :host { color: black;}div { background: blue;} note The `:host` pseudo-class selector is used to select the [`Host` element](https://stenciljs.com/docs/host-element) of the component With the shadow DOM enabled, only these styles will be applied to the component. Even if a style in the light DOM uses a selector that matches an element in the component, those styles will not be applied. ### Shadow DOM QuerySelector[​](https://stenciljs.com/docs/styling#shadow-dom-queryselector "Direct link to Shadow DOM QuerySelector") When using Shadow DOM and you want to query an element inside your web component, you must first use the [`@Element` decorator](https://stenciljs.com/docs/host-element#element-decorator) to gain access to the host element, and then you can use the `shadowRoot` property to perform the query. This is because all of your DOM inside your web component is in a shadowRoot that Shadow DOM creates. For example: import { Component, Element } from '@stencil/core';@Component({ tag: 'shadow-component', styleUrl: 'shadow-component.css', shadow: true})export class ShadowComponent { @Element() el: HTMLElement; componentDidLoad() { const elementInShadowDom = this.el.shadowRoot.querySelector('.a-class-selector'); ... }} ### Shadow DOM Browser Support[​](https://stenciljs.com/docs/styling#shadow-dom-browser-support "Direct link to Shadow DOM Browser Support") The shadow DOM is currently natively supported in the following browsers: * Chrome * Firefox * Safari * Edge (v79+) * Opera In browsers which do not support the shadow DOM we fall back to scoped CSS. This gives you the style encapsulation that comes along with the shadow DOM but without loading in a huge shadow DOM polyfill. ### Scoped CSS[​](https://stenciljs.com/docs/styling#scoped-css "Direct link to Scoped CSS") An alternative to using the shadow DOM is using scoped components. You can use scoped components by setting the `scoped` option to `true` in the component decorator. @Component({ tag: 'scoped-component', styleUrl: 'scoped-component.css', scoped: true,})export class ScopedComponent {} Scoped CSS is a proxy for style encapsulation. It works by appending a data attribute to your styles to make them unique and thereby scope them to your component. It does not, however, prevent styles from the light DOM from seeping into your component. CSS Custom Properties[​](https://stenciljs.com/docs/styling#css-custom-properties "Direct link to CSS Custom Properties") -------------------------------------------------------------------------------------------------------------------------- CSS custom properties, also often referred to as CSS variables, are used to contain values that can then be used in multiple CSS declarations. For example, we can create a custom property called `--color-primary` and assign it a value of `blue`. :host { --color-primary: blue;} And then we can use that custom property to style different parts of our component h1 { color: var(--color-primary);} ### Customizing Components with Custom Properties[​](https://stenciljs.com/docs/styling#customizing-components-with-custom-properties "Direct link to Customizing Components with Custom Properties") CSS custom properties can allow the consumers of a component to customize a component's styles from the light DOM. Consider a `shadow-card` component that uses a custom property for the color of the card heading. :host { --heading-color: black;}.heading { color: var(--heading-color);} note CSS custom properties must be declared on the `Host` element (`:host`) in order for them to be exposed to the consuming application. The `shadow-card` heading will have a default color of `black`, but this can now be changed in the light DOM by selecting the `shadow-card` and changing the value of the `--heading-color` custom property. shadow-card { --heading-color: blue;} CSS Parts[​](https://stenciljs.com/docs/styling#css-parts "Direct link to CSS Parts") -------------------------------------------------------------------------------------- CSS custom properties can be helpful for customizing components from the light DOM, but they are still a little limiting as they only allow a user to modify specific properties. For situations where users require a higher degree of flexibility, we recommend using the [CSS `::part()` pseudo-element](https://developer.mozilla.org/en-US/docs/Web/CSS/::part) . You can define parts on elements of your component with the "part" attribute. @Component({ tag: 'shadow-card', styleUrl: 'shadow-card.css', shadow: true,})export class ShadowCard { @Prop() heading: string; render() { return (

{this.heading}

); }} Then you can use the `::part()` pseudo-class on the host element to give any styles you want to the element with the corresponding part. shadow-card::part(heading) { text-transform: uppercase;} This allows for greater flexibility in styling as any styles can now be added to this element. ### Exportparts[​](https://stenciljs.com/docs/styling#exportparts "Direct link to Exportparts") If you have a Stencil component nested within another component, any `part` specified on elements of the child component will not be exposed through the parent component. In order to expose the `part`s of the child component, you need to use the `exportparts` attribute. Consider this `OuterComponent` which contains the `InnerComponent`. @Component({ tag: 'outer-component', styleUrl: 'outer-component.css', shadow: true,})export class OuterComponent { render() { return (

Outer Component

); }}@Component({ tag: 'inner-component', styleUrl: 'inner-component.css', shadow: true,})export class InnerComponent { render() { return (

Inner Component

); }} By specifying "inner-text" as the value of the `exportparts` attribute, elements of the `InnerComponent` with a `part` of "inner-text" can now be styled in the light DOM. Even though the `InnerComponent` is not used directly, we can style its parts through the `OuterComponent`. Style Modes[​](https://stenciljs.com/docs/styling#style-modes "Direct link to Style Modes") -------------------------------------------------------------------------------------------- Component Style Modes enable you to create versatile designs for your components by utilizing different styling configurations. This is achieved by assigning the styleUrls property of a component to a collection of style mode names, each linked to their respective CSS files. ### Example: Styling a Button Component[​](https://stenciljs.com/docs/styling#example-styling-a-button-component "Direct link to Example: Styling a Button Component") Consider a basic button component that supports both iOS and Material Design aesthetics: Using style modes to style a component @Component({ tag: 'simple-button', styleUrls: { md: './simple-button.md.css', // styles for Material Design ios: './simple-button.ios.css' // styles for iOS },})export class SimpleButton { // ...} In the example above, two different modes are declared. One mode is named `md` (for 'Material Design') and refers back to a Material Design-specific stylesheet. Likewise, the other is named `ios` (for iOS) and references a different stylesheet for iOS-like styling. Both stylesheets are relative paths to the file that declares the component. While we have chosen short names in the above example, there's no limitation to the keys used in the `styleUrls` object. To dictate the style mode (Material Design or iOS) in which the button should be rendered, you must initialize the desired mode before any component rendering occurs. This can be done as follows: import { setMode } from '@stencil/core';setMode(() => 'ios'); // Setting iOS as the default mode for all components The `setMode` function processes all elements, enabling the assignment of modes individually based on specific element attributes. For instance, by assigning the `mode` attribute to a component: You can conditionally set the style mode based on the `mode` property: import { setMode } from '@stencil/core';const defaultMode = 'md'; // Default to Material DesignsetMode((el) => el.getAttribute('mode') || defaultMode); The reason for deciding which mode to apply can be very arbitrary and based on your requirements, using an element property called `mode` is just one example. ### Important Considerations[​](https://stenciljs.com/docs/styling#important-considerations "Direct link to Important Considerations") * **Initialization:** Style modes must be defined at the start of the component lifecycle and cannot be changed thereafter. If you like to change the components mode dynamically you will have to re-render it entirely. * **Usage Requirement:** A style mode must be set to ensure the component loads with styles. Without specifying a style mode, the component will not apply any styles. * **Input Validation:** Verify a style mode is supported by a component you are setting it for. Setting an un-supported style mode keeps the component unstyled. * **Querying Style Mode:** To check the current style mode and e.g. provide different functionality based on the mode, use the `getMode` function: import { getMode } from '@stencil/core';const simpleButton = document.queryElement('simple-button')console.log(getMode(simpleButton)); // Outputs the current style mode of component This approach ensures your components are adaptable and can dynamically switch between different styles, enhancing the user experience across various platforms and design preferences. Global styles[​](https://stenciljs.com/docs/styling#global-styles "Direct link to Global styles") -------------------------------------------------------------------------------------------------- While most styles are usually scoped to each component, sometimes it's useful to have styles that are available to all the components in your project. To create styles that are globally available, start by creating a global stylesheet. For example, you can create a folder in your `src` directory called `global` and create a file called `global.css` within that. Most commonly, this file is used to declare CSS custom properties on the root element via the `:root` pseudo-class. This is because styles provided via the `:root` pseudo-class can pass through the shadow boundary. For example, you can define a primary color that all your components can use. :root { --color-primary: blue;} In addition to CSS custom properties, other use cases for a global stylesheet include * Theming: defining CSS variables used across the app * Load fonts with `@font-face` * App wide font-family * CSS resets To make the global styles available to all the components in your project, the `stencil.config.ts` file comes with an optional [`globalStyle` setting](https://stenciljs.com/docs/config#globalstyle) that accepts the path to your global stylesheet. export const config: Config = { namespace: 'app', globalStyle: 'src/global/global.css', outputTarget: [ { type: 'www', }, ],}; The compiler will run the same minification, autoprefixing, and plugins over `global.css` and generate an output file for the [`www`](https://stenciljs.com/docs/www) and [`dist`](https://stenciljs.com/docs/distribution) output targets. The generated file will always have the `.css` extension and be named as the specified `namespace`. In the example above, since the namespace is `app`, the generated global styles file will be located at: `./www/build/app.css`. This file must be manually imported in the `index.html` of your application. ### Constructable Stylesheets[​](https://stenciljs.com/docs/styling#constructable-stylesheets "Direct link to Constructable Stylesheets") In addition to being available in the light DOM, global styles are automatically registered to every shadow root via [constructable stylesheets](https://web.dev/constructable-stylesheets/) . This means that your global styles can target and style shadow DOM components directly. This allows you to apply styles to specific component types using the `:host()` pseudo-class with a tag name selector. For example, you can target all instances of a specific component: /* In your global stylesheet */:host(my-button) { --button-border-radius: 8px; display: inline-block;}:host(my-card) { --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); margin: 16px 0;}/* You can also use attribute selectors */:host(my-input[type="password"]) { --input-font-family: monospace;} The `:host()` function allows you to select the host element of a component when it matches the given selector. This is particularly useful for: * Setting default CSS custom properties for specific component types * Applying consistent spacing or layout styles across all instances of a component * Theming components based on their tag names or attributes note The `:host()` selector in global styles will only affect components that use shadow DOM. For scoped components, you should use regular tag selectors in your global styles. This behavior can be turned off via the [`extras.addGlobalStyleToComponents`](https://stenciljs.com/docs/config-extras#addglobalstyletocomponents) flag. Contents -------- * [Shadow DOM](https://stenciljs.com/docs/styling#shadow-dom) * [What is the Shadow DOM?](https://stenciljs.com/docs/styling#what-is-the-shadow-dom) * [Shadow DOM in Stencil](https://stenciljs.com/docs/styling#shadow-dom-in-stencil) * [Styling with the Shadow DOM](https://stenciljs.com/docs/styling#styling-with-the-shadow-dom) * [Shadow DOM QuerySelector](https://stenciljs.com/docs/styling#shadow-dom-queryselector) * [Shadow DOM Browser Support](https://stenciljs.com/docs/styling#shadow-dom-browser-support) * [Scoped CSS](https://stenciljs.com/docs/styling#scoped-css) * [CSS Custom Properties](https://stenciljs.com/docs/styling#css-custom-properties) * [Customizing Components with Custom Properties](https://stenciljs.com/docs/styling#customizing-components-with-custom-properties) * [CSS Parts](https://stenciljs.com/docs/styling#css-parts) * [Exportparts](https://stenciljs.com/docs/styling#exportparts) * [Style Modes](https://stenciljs.com/docs/styling#style-modes) * [Example: Styling a Button Component](https://stenciljs.com/docs/styling#example-styling-a-button-component) * [Important Considerations](https://stenciljs.com/docs/styling#important-considerations) * [Global styles](https://stenciljs.com/docs/styling#global-styles) * [Constructable Stylesheets](https://stenciljs.com/docs/styling#constructable-stylesheets) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/components/styling.md) --- # Search the documentation | Stencil [Skip to main content](https://stenciljs.com/docs/search#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Search the documentation ======================== [](https://www.algolia.com/) --- # Build Constants | Stencil [Skip to main content](https://stenciljs.com/docs/next/build-variables#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/build-variables) ** (v4.35). Version: Next On this page Build Constants in Stencil allow you to run specific code only when Stencil is running in development mode. This code is stripped from your bundles when doing a production build, therefore keeping your bundles as small as possible. ### Using Build Constants[​](https://stenciljs.com/docs/next/build-variables#using-build-constants "Direct link to Using Build Constants") Lets dive in and look at an example of how to use our build constants: import { Component, Build } from '@stencil/core';@Component({ tag: 'stencil-app', styleUrl: 'stencil-app.scss'})export class StencilApp { componentDidLoad() { if (Build.isDev) { console.log('im in dev mode'); } else { console.log('im running in production'); } if (Build.isBrowser) { console.log('im in the browser'); } else { console.log('im in prerendering (server)'); } }} As you can see from this example, we just need to import `Build` from `@stencil/core` and then we can use the `isDev` constant to detect when we are running in dev mode or production mode. ### Use Cases[​](https://stenciljs.com/docs/next/build-variables#use-cases "Direct link to Use Cases") Some use cases we have come up with are: * Diagnostics code that runs in dev to make sure logic is working like you would expect * `console.log()`'s that may be useful for debugging in dev mode but that you don't want to ship * Disabling auth checks when in dev mode Contents -------- * [Using Build Constants](https://stenciljs.com/docs/next/build-variables#using-build-constants) * [Use Cases](https://stenciljs.com/docs/next/build-variables#use-cases) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/build-variables.md) --- # Angular Integration with Stencil | Stencil [Skip to main content](https://stenciljs.com/docs/next/angular#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/angular) ** (v4.35). Version: Next On this page Stencil can generate Angular component wrappers for your web components. This allows your Stencil components to be used within an Angular application. The benefits of using Stencil's component wrappers over the standard web components include: * Angular component wrappers will be detached from change detection, preventing unnecessary repaints of your web component. * Web component events will be converted to RxJS observables to align with Angular's `@Output()` and will not emit across component boundaries. * Optionally, form control web components can be used as control value accessors with Angular's reactive forms or `[ngModel]`. * It is not necessary to include the [Angular `CUSTOM_ELEMENTS_SCHEMA`](https://angular.io/api/core/CUSTOM_ELEMENTS_SCHEMA) in all modules consuming your Stencil components. Supported Angular Versions[​](https://stenciljs.com/docs/next/angular#supported-angular-versions "Direct link to Supported Angular Versions") ---------------------------------------------------------------------------------------------------------------------------------------------- The following table shows the compatibility between `@stencil/angular-output-target` versions and Angular versions: | @stencil/angular-output-target | Angular | | --- | --- | | 0.10.2 | v18.x and lower | | 1.0.0 | v19.x and above | Setup[​](https://stenciljs.com/docs/next/angular#setup "Direct link to Setup") ------------------------------------------------------------------------------- ### Project Structure[​](https://stenciljs.com/docs/next/angular#project-structure "Direct link to Project Structure") We recommend using a [monorepo](https://www.toptal.com/front-end/guide-to-monorepos) structure for your component library with component wrappers. Your project workspace should contain your Stencil component library and the library for the generated Angular component wrappers. An example project set-up may look similar to: top-most-directory/└── packages ├── stencil-library/ │ ├── stencil.config.js │ └── src/components └── angular-workspace/ └── projects/ └── component-library/ └── src/ ├── lib/ └── public-api.ts This guide uses Lerna for the monorepo, but you can use other solutions such as Nx, Turborepo, etc. To use Lerna with this walk through, globally install Lerna: * npm * Yarn * pnpm npm install --global lerna yarn global add lerna pnpm add --global lerna #### Creating a Monorepo[​](https://stenciljs.com/docs/next/angular#creating-a-monorepo "Direct link to Creating a Monorepo") note If you already have a monorepo, skip this section. * npm * Yarn * pnpm # From your top-most-directory/, initialize a workspacelerna init# install dependenciesnpm install# install typescript and node typesnpm install typescript @types/node --save-dev # From your top-most-directory/, initialize a workspacelerna init# install dependenciesyarn install# install typescript and node typesyarn add typescript @types/node --dev # From your top-most-directory/, initialize a workspacelerna init# install dependenciespnpm install# install typescript and node typespnpm add typescript @types/node --save-dev #### Creating a Stencil Component Library[​](https://stenciljs.com/docs/next/angular#creating-a-stencil-component-library "Direct link to Creating a Stencil Component Library") note If you already have a Stencil component library, skip this section. In the `packages/` directory, run the following commands to generate a Stencil component library: * npm * Yarn * pnpm npm init stencil components stencil-librarycd stencil-library# Install dependenciesnpm install yarn create stencil components stencil-librarycd stencil-library# Install dependenciesyarn install pnpm create stencil components stencil-librarycd stencil-library# Install dependenciespnpm install #### Creating an Angular Component Library[​](https://stenciljs.com/docs/next/angular#creating-an-angular-component-library "Direct link to Creating an Angular Component Library") note If you already have an Angular component library, skip this section. The first time you want to create the component wrappers, you will need to have an Angular library package to write to. In the `packages/` directory, use the Angular CLI to generate a workspace and a library for your Angular component wrappers: npx -p @angular/cli ng new angular-workspace --no-create-applicationcd angular-workspacenpx -p @angular/cli ng generate library component-library You can delete the `component-library.component.ts`, `component-library.service.ts`, and `*.spec.ts` files. You will also need to add your generated Stencil library as a peer-dependency so import references can be resolved correctly: // packages/angular-workspace/projects/component-library/package.json"peerDependencies": { "@angular/common": "^15.1.0",- "@angular/core": "^15.1.0"+ "@angular/core": "^15.1.0",+ "stencil-library": "*"} For more information, see the Lerna documentation on [package dependency management](https://lerna.js.org/docs/getting-started#package-dependency-management) . note The Angular CLI will install Jasmine as a dependency to your Angular workspace. However, Stencil uses Jest as it's unit testing solution. To avoid type definition collisions when attempting to build your Stencil project, you can remove `jasmine-core` and `@types/jasmine` as dependencies in the Angular workspace `package.json` file: * npm * Yarn * pnpm # from `/packages/angular-workspace`npm uninstall jasmine-core @types/jasmine # from `/packages/angular-workspace`yarn remove jasmine-core @types/jasmine # from `/packages/angular-workspace`pnpm remove jasmine-core @types/jasmine ### Adding the Angular Output Target[​](https://stenciljs.com/docs/next/angular#adding-the-angular-output-target "Direct link to Adding the Angular Output Target") Install the `@stencil/angular-output-target` dependency to your Stencil component library package. * npm * Yarn * pnpm # Install dependencynpm install @stencil/angular-output-target --save-dev # Install dependencyyarn add @stencil/angular-output-target --dev # Install dependencypnpm add @stencil/angular-output-target --save-dev In your project's `stencil.config.ts`, add the `angularOutputTarget` configuration to the `outputTargets` array: import { angularOutputTarget } from '@stencil/angular-output-target';export const config: Config = { namespace: 'stencil-library', outputTargets: [ // By default, the generated proxy components will // leverage the output from the `dist` target, so we // need to explicitly define that output alongside the // Angular target { type: 'dist', }, angularOutputTarget({ componentCorePackage: 'stencil-library', outputType: 'component', directivesProxyFile: '../angular-workspace/projects/component-library/src/lib/stencil-generated/components.ts', directivesArrayFile: '../angular-workspace/projects/component-library/src/lib/stencil-generated/index.ts', }), ],}; tip The `componentCorePackage` should match the `name` field in your Stencil project's `package.json`. `outputType` should be set to `'component'` for Stencil projects using the `dist` output. Otherwise if using the custom elements output, `outputType` should be set to `'scam'` or `'standalone'`. The `directivesProxyFile` is the relative path to the file that will be generated with all of the Angular component wrappers. You will replace the file path to match your project's structure and respective names. You can generate any file name instead of `components.ts`. The `directivesArrayFile` is the relative path to the file that will be generated with a constant of all the Angular component wrappers. This constant can be used to easily declare and export all the wrappers. See the [API section below](https://stenciljs.com/docs/next/angular#api) for details on each of the output target's options. You can now build your Stencil component library to generate the component wrappers. * npm * Yarn * pnpm # Build the library and wrappersnpm run build # Build the library and wrappersyarn build # Build the library and wrapperspnpm run build If the build is successful, you will now have contents in the file specified in `directivesProxyFile` and `directivesArrayFile`. You can now finally import and export the generated component wrappers for your component library. For example, in your library's main Angular module: component-library.module.ts import { DIRECTIVES } from './stencil-generated';@NgModule({ declarations: [...DIRECTIVES], exports: [...DIRECTIVES],})export class ComponentLibraryModule {} Any components that are included in the `exports` array should additionally be exported in your main entry point (either `public-api.ts` or `index.ts`). Skipping this step will lead to Angular Ivy errors when building for production. For this guide, simply add the following line to the automatically generated `public-api.ts` file: public-api.ts export * from './lib/component-library.module';export { DIRECTIVES } from './lib/stencil-generated';export * from './lib/stencil-generated/components'; ### Registering Custom Elements[​](https://stenciljs.com/docs/next/angular#registering-custom-elements "Direct link to Registering Custom Elements") The default behavior for this output target does not handle automatically defining/registering the custom elements. One strategy (and the approach the [Ionic Framework](https://github.com/ionic-team/ionic-framework/blob/main/packages/angular/src/app-initialize.ts#L21-L34) takes) is to use the loader to define all custom elements during app initialization: component-library.module.ts import { APP_INITIALIZER, NgModule } from '@angular/core';import { defineCustomElements } from 'stencil-library/loader';@NgModule({ ..., providers: [ { provide: APP_INITIALIZER, useFactory: () => defineCustomElements, multi: true }, ]})export class ComponentLibraryModule {} See the [documentation](https://stenciljs.com/docs/next/distribution) for more information on defining custom elements using the `dist` output target, or [update the Angular output target](https://stenciljs.com/docs/next/angular#do-i-have-to-use-the-dist-output-target) to use `dist-custom-elements`. ### Link Your Packages (Optional)[​](https://stenciljs.com/docs/next/angular#link-your-packages-optional "Direct link to Link Your Packages (Optional)") note If you are using a monorepo tool (Lerna, Nx, etc.), skip this section. Before you can successfully build a local version of your Angular component library, you will need to link the Stencil package to the Angular package. From your Stencil project's directory, run the following command: * npm * Yarn * pnpm # Link the working directorynpm link # Link the working directoryyarn link # Link the working directorypnpm link From your Angular component library's directory, run the following command: * npm * Yarn * pnpm # Link the package namenpm link name-of-your-stencil-package # Link the package nameyarn link name-of-your-stencil-package # Link the package namepnpm link name-of-your-stencil-package The name of your Stencil package should match the `name` property from the Stencil component library's `package.json`. Your component libraries are now linked together. You can make changes in the Stencil component library and run `npm run build` to propagate the changes to the Angular component library. note As an alternative to `npm link` , you can also run `npm install` with a relative path to your Stencil component library. This strategy, however, will modify your `package.json` so it is important to make sure you do not commit those changes. Consumer Usage[​](https://stenciljs.com/docs/next/angular#consumer-usage "Direct link to Consumer Usage") ---------------------------------------------------------------------------------------------------------- note If you already have an Angular app, skip this section. ### Angular with Modules[​](https://stenciljs.com/docs/next/angular#angular-with-modules "Direct link to Angular with Modules") #### Creating a Consumer Angular App[​](https://stenciljs.com/docs/next/angular#creating-a-consumer-angular-app "Direct link to Creating a Consumer Angular App") From your Angular workspace (`/packages/angular-workspace`), run the following command to generate an Angular application with modules: npx -p @angular/cli ng generate app my-app --standalone=false #### Consuming the Angular Wrapper Components[​](https://stenciljs.com/docs/next/angular#consuming-the-angular-wrapper-components "Direct link to Consuming the Angular Wrapper Components") This section covers how developers consuming your Angular component wrappers will use your package and component wrappers in an Angular project using modules. In order to use the generated component wrappers in the Angular app, you'll first need to build your Angular component library. From the root of your Angular workspace (`/packages/angular-workspace`), run the following command: npx -p @angular/cli ng build component-library note In the output of the `ng build` command you may see a warning that looks like this: ▲ [WARNING] The glob pattern import("./**/.entry.js") did not match any files [empty-glob]node_modules/@stencil/core/internal/client/index.js:3808:2: 3808 │ `./${bundleId}.entry.js${BUILD.hotModuleReplacement && hmrVers... ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a known issue in esbuild (used under the hood by `ng build`) and should not cause an issue, but at present there's unfortunately no way to suppress this warning. * outputType: "component" * outputType: "scam" * outputType: "standalone" Import your component library into your Angular app's module. If you distributed your components through a primary `NgModule`, you can simply import that module into an implementation to use your components. app.module.ts import { ComponentLibraryModule } from 'component-library';@NgModule({ imports: [ComponentLibraryModule],})export class AppModule {} Otherwise you will need to add the components to your module's `declarations` and `exports` arrays. app.module.ts import { MyComponent } from 'component-library';@NgModule({ declarations: [MyComponent], exports: [MyComponent],})export class AppModule {} You can now directly leverage your components in their template and take advantage of Angular template binding syntax. app.component.html Now you can reference your component library as a standard import. Each component will be exported as a separate module. app.module.ts import { MyComponentModule } from 'component-library';@NgModule({ imports: [MyComponentModule],})export class AppModule {} You can now directly leverage your components in their template and take advantage of Angular template binding syntax. app.component.html Now you can import and reference your components in your consuming application in the same way you would with any other Angular components: app.component.ts import { Component } from '@angular/core';import { MyComponent } from 'component-library';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], standalone: true, imports: [MyComponent],})export class AppComponent {} You can now leverage your components in the template and take advantage of Angular template binding syntax. app.component.html From your Angular workspace (`/packages/angular-workspace`), run `npm start` and navigate to `localhost:4200`. You should see the component rendered correctly. ### Angular with Standalone Components[​](https://stenciljs.com/docs/next/angular#angular-with-standalone-components "Direct link to Angular with Standalone Components") In Angular CLI v17, the default behavior is to generate a new project with standalone components. From your Angular workspace (`/packages/angular-workspace`), run the following command to generate an Angular application: npx -p @angular/cli ng generate app my-app #### Consuming the Angular Wrapper Components[​](https://stenciljs.com/docs/next/angular#consuming-the-angular-wrapper-components-1 "Direct link to Consuming the Angular Wrapper Components") This section covers how developers consuming your Angular component wrappers will use your package and component wrappers. In order to use the generated component wrappers in the Angular app, you'll first need to build your Angular component library. From the root of your Angular workspace (`/packages/angular-workspace`), run the following command: npx -p @angular/cli ng build component-library note In the output of the `ng build` command you may see a warning that looks like this: ▲ [WARNING] The glob pattern import("./**/.entry.js") did not match any files [empty-glob]node_modules/@stencil/core/internal/client/index.js:3808:2: 3808 │ `./${bundleId}.entry.js${BUILD.hotModuleReplacement && hmrVers... ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a known issue in esbuild (used under the hood by `ng build`) and should not cause an issue, but at present there's unfortunately no way to suppress this warning. * outputType: "component" * outputType: "scam" * outputType: "standalone" Import your component library into your component. You must distribute your components through a primary `NgModule` to use your components in a standalone component. app.component.ts import { Component } from '@angular/core';import { ComponentLibraryModule } from 'component-library';@Component({ selector: 'app-root', standalone: true, imports: [ComponentLibraryModule], templateUrl: './app.component.html',})export class AppComponent {} You can now directly leverage your components in their template and take advantage of Angular template binding syntax. app.component.html Now you can reference your component library as a standard import. Each component will be exported as a separate module. app.module.ts import { Component } from '@angular/core';import { MyComponentModule } from 'component-library';@Component({ selector: 'app-root', standalone: true, imports: [MyComponentModule], templateUrl: './app.component.html',})export class AppComponent {} You can now directly leverage your components in their template and take advantage of Angular template binding syntax. app.component.html Now you can import and reference your components in your consuming application in the same way you would with any other standalone Angular components: app.component.ts import { Component } from '@angular/core';import { MyComponent } from 'component-library';@Component({ selector: 'app-root', standalone: true, imports: [MyComponent], templateUrl: './app.component.html',})export class AppComponent {} You can now leverage your components in the template and take advantage of Angular template binding syntax. app.component.html From your Angular workspace (`/packages/angular-workspace`), run `npm start` and navigate to `localhost:4200`. You should see the component rendered correctly. API[​](https://stenciljs.com/docs/next/angular#api "Direct link to API") ------------------------------------------------------------------------- ### componentCorePackage[​](https://stenciljs.com/docs/next/angular#componentcorepackage "Direct link to componentCorePackage") **Required** **Type: `string`** The name of the Stencil package where components are available for consumers (i.e. the value of the `name` property in your Stencil component library's `package.json`). This is used during compilation to write the correct imports for components. For a starter Stencil project generated by running: * npm * Yarn * pnpm npm init stencil component my-component-lib yarn create stencil component my-component-lib pnpm create stencil component my-component-lib The `componentCorePackage` would be set to: stencil.config.ts export const config: Config = { ..., outputTargets: [ angularOutputTarget({ componentCorePackage: 'my-component-lib', // ... additional config options }) ]} Which would result in an import path like: import { MyComponent } from 'my-component-lib/components/my-component.js'; ### customElementsDir[​](https://stenciljs.com/docs/next/angular#customelementsdir "Direct link to customElementsDir") **Optional** **Default: `'components'`** **Type: `string`** This option can be used to specify the directory where the generated custom elements live. ### excludeComponents[​](https://stenciljs.com/docs/next/angular#excludecomponents "Direct link to excludeComponents") **Optional** **Default: `[]`** **Type: `string[]`** This lets you specify component tag names for which you don't want to generate Angular wrapper components. This is useful if you need to write framework-specific versions of components. For instance, in Ionic Framework, this is used for routing components - like tabs - so that Ionic Framework can integrate better with Angular's Router. ### directivesArrayFile[​](https://stenciljs.com/docs/next/angular#directivesarrayfile "Direct link to directivesArrayFile") **Optional** **Default: `null`** **Type: `string`** Used to provide a list of type Proxies to the Angular Component Library. See [Ionic Framework](https://github.com/ionic-team/ionic-framework/blob/main/packages/angular/src/directives/proxies-list.ts) for a sample. ### directivesProxyFile[​](https://stenciljs.com/docs/next/angular#directivesproxyfile "Direct link to directivesProxyFile") **Required** **Type: `string`** This parameter allows you to name the file that contains all the component wrapper definitions produced during the compilation process. This is the first file you should import in your Angular project. ### outputType[​](https://stenciljs.com/docs/next/angular#outputtype "Direct link to outputType") **Required** **Default: `'component'`** **Type: `'component' | 'scam' | 'standalone`** Specifies the type of output to be generated. It can take one of the following values: 1. `component`: Generates all the component wrappers to be declared on an Angular module. This option is required for Stencil projects using the `dist` hydrated output. 2. `scam`: Generates a separate Angular module for each component. 3. `standalone`: Generates standalone component wrappers. Both `scam` and `standalone` options are compatible with the `dist-custom-elements` output. note The configuration for the [Custom Elements](https://stenciljs.com/docs/next/custom-elements) output target must set the [export behavior](https://stenciljs.com/docs/next/custom-elements#customelementsexportbehavior) to `single-export-module` for the wrappers to generate correctly if using the `scam` or `standalone` output type. Note: Please choose the appropriate `outputType` based on your project's requirements and the desired output structure. ### valueAccessorConfigs[​](https://stenciljs.com/docs/next/angular#valueaccessorconfigs "Direct link to valueAccessorConfigs") **Optional** **Default: `[]`** **Type: `ValueAccessorConfig[]`** This lets you define which components should be integrated with `ngModel` (i.e. form components). It lets you set what the target prop is (i.e. `value`), which event will cause the target prop to change, and more. stencil.config.ts const angularValueAccessorBindings: ValueAccessorConfig[] = [ { elementSelectors: ['my-input[type=text]'], event: 'myChange', targetAttr: 'value', type: 'text', },];export const config: Config = { namespace: 'stencil-library', outputTargets: [ angularOutputTarget({ componentCorePackage: 'component-library', directivesProxyFile: '{path to your proxy file}', valueAccessorConfigs: angularValueAccessorBindings, }), { type: 'dist', esmLoaderPath: '../loader', }, ],}; FAQs[​](https://stenciljs.com/docs/next/angular#faqs "Direct link to FAQs") ---------------------------------------------------------------------------- ### Do I have to use the `dist` output target?[​](https://stenciljs.com/docs/next/angular#do-i-have-to-use-the-dist-output-target "Direct link to do-i-have-to-use-the-dist-output-target") No! By default, this output target will look to use the `dist` output, but the output from `dist-custom-elements` can be used alternatively. To do so, change the type `outputType` argument to either `scam` or `standalone`. For more information on both these options, see the [API section](https://stenciljs.com/docs/next/angular#outputtype) . stencil.config.ts export const config: Config = { ..., outputTargets: [ // Needs to be included { type: 'dist-custom-elements' }, angularOutputTarget({ componentCorePackage: 'component-library', directivesProxyFile: '{path to your proxy file}', // This is what tells the target to use the custom elements output outputType: 'standalone' // or 'scam' }) ]} Now, all generated imports will point to the default directory for the custom elements output. If you specified a different directory using the `dir` property for `dist-custom-elements`, you need to also specify that directory for the Angular output target. See [the API section](https://stenciljs.com/docs/next/angular#customelementsdir) for more information. In addition, all the Web Component will be automatically defined as the generated component modules are bootstrapped. So, you do not need to implement the Stencil loader for lazy-loading the custom elements (i.e. you can remove the `APP_INITIALIZER` logic introduced [in this section](https://stenciljs.com/docs/next/angular#adding-the-angular-output-target) ). As such, the generated Angular components can now be directly imported and declared on any Angular module implementing them: app.module.ts import { MyComponent } from 'component-library';@NgModule({ declarations: [MyComponent],})export class AppModule {} ### What is the best format to write event names?[​](https://stenciljs.com/docs/next/angular#what-is-the-best-format-to-write-event-names "Direct link to What is the best format to write event names?") Event names shouldn’t include special characters when initially written in Stencil, try to lean on using camelCased event names for interoperability between frameworks. ### How do I bind input events directly to a value accessor?[​](https://stenciljs.com/docs/next/angular#how-do-i-bind-input-events-directly-to-a-value-accessor "Direct link to How do I bind input events directly to a value accessor?") You can configure how your input events can map directly to a value accessor, allowing two-way data-binding to be a built in feature of any of your components. Take a look at [valueAccessorConfig's option above](https://stenciljs.com/docs/next/angular#valueaccessorconfigs) . ### How do I access components with ViewChild or ViewChildren?[​](https://stenciljs.com/docs/next/angular#how-do-i-access-components-with-viewchild-or-viewchildren "Direct link to How do I access components with ViewChild or ViewChildren?") Once included, components could be referenced in your code using `ViewChild` and `ViewChildren` as in the following example: import { Component, ElementRef, ViewChild } from '@angular/core';import { TestComponent } from 'test-components';@Component({ selector: 'app-home', template: ``, styleUrls: ['./home.component.scss'],})export class HomeComponent { @ViewChild(TestComponent) myTestComponent: ElementRef; async onAction() { await this.myTestComponent.nativeElement.testComponentMethod(); }} ### Why aren't my custom interfaces exported from within the index.d.ts file?[​](https://stenciljs.com/docs/next/angular#why-arent-my-custom-interfaces-exported-from-within-the-indexdts-file "Direct link to Why aren't my custom interfaces exported from within the index.d.ts file?") Usually when beginning this process, you may bump into a situation where you find that some of the interfaces you've used in your Stencil component library aren't working in your Angular component library. You can resolve this issue by adding an `interfaces.d.ts` file located within the root of your Stencil component library's project folder, then manually exporting types from that file e.g. `export * from './components';` When adding this file, it's also recommended to update your package.json's types property to be the distributed file, something like: `"types": "dist/types/interfaces.d.ts"` Contents -------- * [Supported Angular Versions](https://stenciljs.com/docs/next/angular#supported-angular-versions) * [Setup](https://stenciljs.com/docs/next/angular#setup) * [Project Structure](https://stenciljs.com/docs/next/angular#project-structure) * [Adding the Angular Output Target](https://stenciljs.com/docs/next/angular#adding-the-angular-output-target) * [Registering Custom Elements](https://stenciljs.com/docs/next/angular#registering-custom-elements) * [Link Your Packages (Optional)](https://stenciljs.com/docs/next/angular#link-your-packages-optional) * [Consumer Usage](https://stenciljs.com/docs/next/angular#consumer-usage) * [Angular with Modules](https://stenciljs.com/docs/next/angular#angular-with-modules) * [Angular with Standalone Components](https://stenciljs.com/docs/next/angular#angular-with-standalone-components) * [API](https://stenciljs.com/docs/next/angular#api) * [componentCorePackage](https://stenciljs.com/docs/next/angular#componentcorepackage) * [customElementsDir](https://stenciljs.com/docs/next/angular#customelementsdir) * [excludeComponents](https://stenciljs.com/docs/next/angular#excludecomponents) * [directivesArrayFile](https://stenciljs.com/docs/next/angular#directivesarrayfile) * [directivesProxyFile](https://stenciljs.com/docs/next/angular#directivesproxyfile) * [outputType](https://stenciljs.com/docs/next/angular#outputtype) * [valueAccessorConfigs](https://stenciljs.com/docs/next/angular#valueaccessorconfigs) * [FAQs](https://stenciljs.com/docs/next/angular#faqs) * [Do I have to use the `dist` output target?](https://stenciljs.com/docs/next/angular#do-i-have-to-use-the-dist-output-target) * [What is the best format to write event names?](https://stenciljs.com/docs/next/angular#what-is-the-best-format-to-write-event-names) * [How do I bind input events directly to a value accessor?](https://stenciljs.com/docs/next/angular#how-do-i-bind-input-events-directly-to-a-value-accessor) * [How do I access components with ViewChild or ViewChildren?](https://stenciljs.com/docs/next/angular#how-do-i-access-components-with-viewchild-or-viewchildren) * [Why aren't my custom interfaces exported from within the index.d.ts file?](https://stenciljs.com/docs/next/angular#why-arent-my-custom-interfaces-exported-from-within-the-indexdts-file) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/framework-integration/angular.md) --- # Stencil Core CLI API | Stencil [Skip to main content](https://stenciljs.com/docs/next/cli-api#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/cli-api) ** (v4.35). Version: Next On this page The CLI API can be found at `@stencil/core/cli` and ran by `bin/stencil`. createNodeLogger()[​](https://stenciljs.com/docs/next/cli-api#createnodelogger "Direct link to createNodeLogger()") -------------------------------------------------------------------------------------------------------------------- createNodeLogger(process: any): Logger Creates a "logger", based off of NodeJS APIs, that will be used by the compiler and dev-server. By default the CLI uses this method to create the NodeJS logger. The NodeJS "process" object should be provided as the first argument. createNodeSystem()[​](https://stenciljs.com/docs/next/cli-api#createnodesystem "Direct link to createNodeSystem()") -------------------------------------------------------------------------------------------------------------------- createNodeSystem(process: any): CompilerSystem Creates the "system", based off of NodeJS APIs, used by the compiler. This includes any and all file system reads and writes using NodeJS. The compiler itself is unaware of Node's `fs` module. Other system APIs include any use of `crypto` to hash content. The NodeJS "process" object should be provided as the first argument. parseFlags()[​](https://stenciljs.com/docs/next/cli-api#parseflags "Direct link to parseFlags()") -------------------------------------------------------------------------------------------------- parseFlags(args: string[]): ConfigFlags Used by the CLI to parse command-line arguments into a typed `ConfigFlags` object. This is an example of how it's used internally: `parseFlags(process.argv.slice(2))`. run()[​](https://stenciljs.com/docs/next/cli-api#run "Direct link to run()") ----------------------------------------------------------------------------- run(init: CliInitOptions): Promise Runs the CLI with the given options. This is used by Stencil's default `bin/stencil` file, but can be used externally too. runTask()[​](https://stenciljs.com/docs/next/cli-api#runtask "Direct link to runTask()") ----------------------------------------------------------------------------------------- runTask(process: any, config: Config, task: TaskCommand, sys?: CompilerSystem): Promise Runs individual tasks giving a NodeJS `process`, Stencil `config`, and task command. You can optionally pass in the `sys` that's used by the compiler. See [createNodeSystem()](https://stenciljs.com/docs/next/cli-api#createnodesystem) for more details. Contents -------- * [createNodeLogger()](https://stenciljs.com/docs/next/cli-api#createnodelogger) * [createNodeSystem()](https://stenciljs.com/docs/next/cli-api#createnodesystem) * [parseFlags()](https://stenciljs.com/docs/next/cli-api#parseflags) * [run()](https://stenciljs.com/docs/next/cli-api#run) * [runTask()](https://stenciljs.com/docs/next/cli-api#runtask) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/core/cli-api.md) --- # Stencil Core Compiler API | Stencil [Skip to main content](https://stenciljs.com/docs/next/compiler-api#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/compiler-api) ** (v4.35). Version: Next On this page The compiler API can be found at `@stencil/core/compiler/stencil.js`. This module can work in a NodeJS environment. // NodeJS (commonjs)const stencil = require('@stencil/core/compiler'); transpile()[​](https://stenciljs.com/docs/next/compiler-api#transpile "Direct link to transpile()") ---------------------------------------------------------------------------------------------------- transpile(code: string, opts?: TranspileOptions): Promise The `transpile()` function inputs source code as a string, with various options within the second argument. The function is stateless and returns a `Promise` of the results, including diagnostics and the transpiled code. The `transpile()` function does not handle any bundling, minifying, or precompiling any CSS preprocessing like Sass or Less. The `transpileSync()` equivalent is available so the same function it can be called synchronously. However, TypeScript must be already loaded within the global for it to work, where as the async `transpile()` function will load TypeScript automatically. Since TypeScript is used, the source code will transpile from TypeScript to JavaScript, and does not require Babel presets. Additionally, the results includes an `imports` array of all the import paths found in the source file. The transpile options can be used to set the `module` format, such as `cjs`, and JavaScript `target` version, such as `es2017`. transpileSync()[​](https://stenciljs.com/docs/next/compiler-api#transpilesync "Direct link to transpileSync()") ---------------------------------------------------------------------------------------------------------------- transpileSync(code: string, opts?: TranspileOptions): TranspileResults Synchronous equivalent of the `transpile()` function. When used in a browser environment, TypeScript must already be available globally, where as the async `transpile()` function will load TypeScript automatically. createCompiler()[​](https://stenciljs.com/docs/next/compiler-api#createcompiler "Direct link to createCompiler()") ------------------------------------------------------------------------------------------------------------------- createCompiler(config: Config): Promise The compiler is the utility that brings together many tools to build optimized components, such as a transpiler, bundler and minifier. When using the CLI, the `stencil build` command uses the compiler for the various builds, such as a production build, or watch mode during development. If only one file should be transpiled (converting source code from TypeScript to JavaScript) then the `transpile()` function should be used instead. Given a Stencil config, this method asynchronously returns a `Compiler` instance. The config provided should already be created using the `loadConfig({...})` method. Below is an example of a NodeJS environment running a full build. import { createNodeLogger, createNodeSys } from '@stencil/core/sys/node';import { createCompiler, loadConfig } from '@stencil/core/compiler';const logger = createNodeLogger(process);const sys = createNodeSys(process);const validated = await loadConfig({ logger, sys, config: { /* user config */ },});const compiler = await createCompiler(validated.config);const results = await compiler.build(); createSystem()[​](https://stenciljs.com/docs/next/compiler-api#createsystem "Direct link to createSystem()") ------------------------------------------------------------------------------------------------------------- createSystem(): CompilerSystem The compiler uses a `CompilerSystem` instance to access any file system reads and writes. When used from the CLI, the CLI will provide its own system based on NodeJS. This method provide a compiler system is in-memory only and independent of any platform. dependencies[​](https://stenciljs.com/docs/next/compiler-api#dependencies "Direct link to dependencies") --------------------------------------------------------------------------------------------------------- dependencies: CompilerDependency[] The `dependencies` array is only informational and provided to state which versions of dependencies the compiler was built and works with. For example, the version of TypeScript, Rollup and Terser used for this version of Stencil are listed here. loadConfig()[​](https://stenciljs.com/docs/next/compiler-api#loadconfig "Direct link to loadConfig()") ------------------------------------------------------------------------------------------------------- loadConfig(init?: LoadConfigInit): Promise The `loadConfig(init)` method is used to take raw config information and transform it into a usable config object for the compiler and dev-server. The `init` argument should be given an already created system and logger which can also be used by the compiler. optimizeCss()[​](https://stenciljs.com/docs/next/compiler-api#optimizecss "Direct link to optimizeCss()") ---------------------------------------------------------------------------------------------------------- optimizeCss(cssInput?: OptimizeCssInput): Promise Utility function used by the compiler to optimize CSS. optimizeJs()[​](https://stenciljs.com/docs/next/compiler-api#optimizejs "Direct link to optimizeJs()") ------------------------------------------------------------------------------------------------------- optimizeJs(jsInput?: OptimizeJsInput): Promise Utility function used by the compiler to optimize JavaScript. Knowing the JavaScript target will further apply minification optimizations beyond usual minification. path[​](https://stenciljs.com/docs/next/compiler-api#path "Direct link to path") --------------------------------------------------------------------------------- path: PlatformPath Utility of the `path` API provided by NodeJS, but capable of running in any environment. This `path` API is only the POSIX version: [https://nodejs.org/api/path.html](https://nodejs.org/api/path.html) version[​](https://stenciljs.com/docs/next/compiler-api#version "Direct link to version") ------------------------------------------------------------------------------------------ version: string Current version of `@stencil/core`. Contents -------- * [transpile()](https://stenciljs.com/docs/next/compiler-api#transpile) * [transpileSync()](https://stenciljs.com/docs/next/compiler-api#transpilesync) * [createCompiler()](https://stenciljs.com/docs/next/compiler-api#createcompiler) * [createSystem()](https://stenciljs.com/docs/next/compiler-api#createsystem) * [dependencies](https://stenciljs.com/docs/next/compiler-api#dependencies) * [loadConfig()](https://stenciljs.com/docs/next/compiler-api#loadconfig) * [optimizeCss()](https://stenciljs.com/docs/next/compiler-api#optimizecss) * [optimizeJs()](https://stenciljs.com/docs/next/compiler-api#optimizejs) * [path](https://stenciljs.com/docs/next/compiler-api#path) * [version](https://stenciljs.com/docs/next/compiler-api#version) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/core/compiler-api.md) --- # Stencil CLI | Stencil [Skip to main content](https://stenciljs.com/docs/next/cli#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/cli) ** (v4.35). Version: Next On this page Stencil's command line interface (CLI) is how developers can build their projects, run tests, and more. Stencil's CLI is included in the compiler, and can be invoked with the `stencil` command in a project where `@stencil/core` is installed. `stencil build`[​](https://stenciljs.com/docs/next/cli#stencil-build "Direct link to stencil-build") ----------------------------------------------------------------------------------------------------- Builds a Stencil project. The flags below are the available options for the `build` command. | Flag | Description | Alias | | --- | --- | --- | | `--ci` | Run a build using recommended settings for a Continuous Integration (CI) environment. Defaults the number of workers to 4, allows for extra time if taking screenshots via the tests and modifies the console logs. | | | `--config` | Path to the `stencil.config.ts` file. This flag is not needed in most cases since Stencil will find the config. Additionally, a Stencil config is not required. | `-c` | | `--debug` | Adds additional runtime code to help debug, and sets the log level for more verbose output. | | | `--dev` | Runs a development build. | | | `--docs` | Generate all docs based on the component types, properties, methods, events, JSDocs, CSS Custom Properties, etc. | | | `--es5` | Creates an ES5 compatible build. By default ES5 builds are not created during development in order to improve build times. However, ES5 builds are always created during production builds. Use this flag to create ES5 builds during development. | | | `--log` | Write logs for the `stencil build` into `stencil-build.log`. The log file is written in the same location as the config. | | | `--prerender` | Prerender the application using the `www` output target after the build has completed. | | | `--prod` | Runs a production build which will optimize each file, improve bundling, remove unused code, minify, etc. A production build is the default, this flag is only used to override the `--dev` flag. | | | `--max-workers` | Max number of workers the compiler should use. Defaults to use the same number of CPUs the Operating System has available. | | | `--next` | Opt-in to test the "next" Stencil compiler features. | | | `--no-cache` | Disables using the cache. | | | `--no-open` | By default the `--serve` command will open a browser window. Using the `--no-open` command will not automatically open a browser window. | | | `--port` | Port for the [Integrated Dev Server](https://stenciljs.com/docs/next/dev-server)
. Defaults to `3333`. | `-p` | | `--serve` | Starts the [Integrated Dev Server](https://stenciljs.com/docs/next/dev-server)
. | | | `--stats` | Write stats about the project to `stencil-stats.json`. The stats file is written in the same location as the config. | | | `--verbose` | Logs additional information about each step of the build. | | | `--watch` | Watches files during development and triggers a rebuild when files are updated. | | `stencil docs`[​](https://stenciljs.com/docs/next/cli#stencil-docs "Direct link to stencil-docs") -------------------------------------------------------------------------------------------------- Performs a one-time generation of documentation for your project. For more information on documentation generation, please see the [Documentation Generation section](https://stenciljs.com/docs/next/doc-generation) . info This command runs with dev mode enabled, which does not run a full build. As a result, documentation that needs to be built first, like CSS styles, will not be generated. You will need to run `npx stencil build --docs` to generate documentation that requires building. `stencil generate`[​](https://stenciljs.com/docs/next/cli#stencil-generate "Direct link to stencil-generate") -------------------------------------------------------------------------------------------------------------- Alias: `stencil g` Starts the interactive generator for a new Stencil component. The generator will ask you for a name for your component, and whether any stylesheets or testing files should be generated. If you wish to skip the interactive generator, a component tag name may be provided on the command line: stencil generate my-new-component All components will be generated within the `src/components` folder. Within `src/components`, a directory will be created with the same name as the component tag name you provided containing the generated files. For example, if you specify `page-home` as the component tag name, the files will be generated in `src/components/page-home`: src└── components └── page-home ├── page-home.css ├── page-home.e2e.ts ├── page-home.spec.ts └── page-home.tsx It is also possible to specify one or more sub-folders to generate the component in. For example, if you specify `pages/page-home` as the component tag name, the files will be generated in `src/components/pages/page-home`: stencil generate pages/page-home The command above will result in the following directory structure: src└── components └── pages └── page-home ├── page-home.css ├── page-home.e2e.ts ├── page-home.spec.ts └── page-home.tsx `stencil help`[​](https://stenciljs.com/docs/next/cli#stencil-help "Direct link to stencil-help") -------------------------------------------------------------------------------------------------- Aliases: `stencil --help`, `stencil -h` Prints various tasks that can be run and their associated flags to the terminal. `stencil test`[​](https://stenciljs.com/docs/next/cli#stencil-test "Direct link to stencil-test") -------------------------------------------------------------------------------------------------- Tests a Stencil project. The flags below are the available options for the `test` command. | Flag | Description | | --- | --- | | `--spec` | Tests `.spec.ts` files using [Jest](https://jestjs.io/)
. | | `--e2e` | Tests `.e2e.ts` files using [Puppeteer](https://developers.google.com/web/tools/puppeteer)
and [Jest](https://jestjs.io/)
. | | `--no-build` | Skips the build process before running end-to-end tests. When using this flag, it is assumed that your Stencil project has been built prior to running `stencil test`. Unit tests do not require this flag. | | `--devtools` | Opens the dev tools panel in Chrome for end-to-end tests. Setting this flag will disable `--headless` | | `--headless` | Sets the headless mode to use in Chrome for end-to-end tests. `--headless` and `--headless=true` will enable the "old" headless mode in Chrome, that was used by default prior to Chrome v112. `--headless=new` will enable the new headless mode introduced in Chrome v112. See [this article](https://developer.chrome.com/articles/new-headless/)
for more information on Chrome's new headless mode. | `stencil version`[​](https://stenciljs.com/docs/next/cli#stencil-version "Direct link to stencil-version") ----------------------------------------------------------------------------------------------------------- Aliases: `stencil -v`, `stencil --version` Prints the version of Stencil to the terminal. Contents -------- * [`stencil build`](https://stenciljs.com/docs/next/cli#stencil-build) * [`stencil docs`](https://stenciljs.com/docs/next/cli#stencil-docs) * [`stencil generate`](https://stenciljs.com/docs/next/cli#stencil-generate) * [`stencil help`](https://stenciljs.com/docs/next/cli#stencil-help) * [`stencil test`](https://stenciljs.com/docs/next/cli#stencil-test) * [`stencil version`](https://stenciljs.com/docs/next/cli#stencil-version) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/config/cli.md) --- # Stencil Core Dev Server API | Stencil [Skip to main content](https://stenciljs.com/docs/next/dev-server-api#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/dev-server-api) ** (v4.35). Version: Next On this page The CLI API can be found at `@stencil/core/dev-server`. start()[​](https://stenciljs.com/docs/next/dev-server-api#start "Direct link to start()") ------------------------------------------------------------------------------------------ start(stencilDevServerConfig: StencilDevServerConfig, logger: Logger, watcher?: CompilerWatcher): Promise Contents -------- * [start()](https://stenciljs.com/docs/next/dev-server-api#start) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/core/dev-server-api.md) --- # Stencil Copy Tasks | Stencil [Skip to main content](https://stenciljs.com/docs/next/copy-tasks#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/copy-tasks) ** (v4.35). Version: Next On this page All of Stencil's non-documentation output targets ([`dist-custom-elements`](https://stenciljs.com/docs/next/custom-elements) , [`dist`](https://stenciljs.com/docs/next/distribution) , and [`www`](https://stenciljs.com/docs/next/www) ) support a `copy` config which allows you to define file copy operations which Stencil will automatically perform as part of the build. This could be useful if, for instance, you had some static assets like images which should be distributed alongside your components. The `copy` attribute on these output targets expects an array of objects corresponding to the following `CopyTask` interface: CopyTask loading... [View on GitHub](https://github.com/ionic-team/stencil/blob/6ed2d4e285544945949ad8e4802fe7f70e392636/src/declarations/stencil-public-compiler.ts#L1594-L1665) Options[​](https://stenciljs.com/docs/next/copy-tasks#options "Direct link to Options") ---------------------------------------------------------------------------------------- A copy task can take the following options: #### `src`[​](https://stenciljs.com/docs/next/copy-tasks#src "Direct link to src") The source file path for a copy operation. This may be an absolute or relative path to a directory or a file, and may also include a glob pattern. If the path is a relative path it will be treated as relative to `Config.srcDir`. **Type:** `string` #### `dest`[​](https://stenciljs.com/docs/next/copy-tasks#dest "Direct link to dest") An optional destination file path for a copy operation. This may be an absolute or relative path. If relative, this will be treated as relative to the output directory for the output target for which this copy operation is configured. **Type:** `string` #### `ignore`[​](https://stenciljs.com/docs/next/copy-tasks#ignore "Direct link to ignore") An optional array of glob patterns to exclude from the copy operation. **Type:** `string[]` **Default:** `['**\/__mocks__/**', '**\/__fixtures__/**', '**\/dist/**', '**\/.{idea,git,cache,output,temp}/**', '.ds_store', '.gitignore', 'desktop.ini', 'thumbs.db']` #### `warn`[​](https://stenciljs.com/docs/next/copy-tasks#warn "Direct link to warn") Whether or not Stencil should issue warnings if it cannot find the specified source files or directories. Defaults to `false`. To receive warnings if a copy task source can't be found set this to `true`. **Type:** `boolean` #### `keepDirStructure`[​](https://stenciljs.com/docs/next/copy-tasks#keepdirstructure "Direct link to keepdirstructure") Whether or not directory structure should be preserved when copying files from a source directory. Defaults to `true` if no `dest` path is supplied, else it defaults to `false`. If this is set to `false`, all the files from a source directory will be copied directly to the destination directory, but if it's set to `true` they will be copied to a new directory inside the destination directory with the same name as their original source directory. So if, for instance, `src` is set to `"images"` and `keepDirStructure` is set to `true` the copy task will then produce the following directory structure: images└── foo.pngdist└── images └── foo.png Conversely if `keepDirStructure` is set to `false` then files in `images/` will be copied to `dist` without first creating a new subdirectory, resulting in the following directory structure: images└── foo.pngdist└── foo.png If a `dest` path is supplied then `keepDirStructure` will default to `false`, so that Stencil will write the copied files directly into the `dest` directory without creating a new subdirectory. This behavior can be overridden by setting `keepDirStructure` to `true`. Examples[​](https://stenciljs.com/docs/next/copy-tasks#examples "Direct link to Examples") ------------------------------------------------------------------------------------------- ### Images in the `www` Output Target[​](https://stenciljs.com/docs/next/copy-tasks#images-in-the-www-output-target "Direct link to images-in-the-www-output-target") The `copy` config within the following [`www` output target](https://stenciljs.com/docs/next/www) config will cause Stencil to copy the entire directory from `src/images` to `www/images`: outputTargets: [ { type: 'www', copy: [ { src: 'images' } ] } ] In this example, since the `srcDir` property is not set, the default source directory is `src/`, and since `dest` is not set the contents of `src/images` will be copied to a new `images` directory in `www`, the default destination directory for the `www` Output Target. ### Setting the `dest` option[​](https://stenciljs.com/docs/next/copy-tasks#setting-the-dest-option "Direct link to setting-the-dest-option") The `dest` property can also be optionally set on a `CopyTask` to either an absolute path or a path relative to the build directory of the output target. In this example we've customized the build directory to be `public` instead of the default (`'www'`), which, in combination with `dest: 'static/web-fonts'` will copy the contents of `src/files/fonts` over to `public/static/web-fonts`: outputTargets: [ { type: 'www', dir: 'public', copy: [ { src: 'files/fonts', dest: 'static/web-fonts' } ] } ] note When `dest` is set on a `CopyTask` Stencil will, by default, copy all the contents of the `src` directory to the `dest` directory without creating a new subdirectory for the contents of `src`. The `keepDirStructure` option can control this behavior. If it's set to `true` Stencil will always create a new subdirectory within `dest` with the same name as the `src` directory. In the above example this would result in the contents of `src/files/fonts` being copied to `public/static/web-fonts/fonts` instead of `public/static/web-fonts`. See the above documentation for the `keepDirStructure` option for more details. ### Opting-in to warnings[​](https://stenciljs.com/docs/next/copy-tasks#opting-in-to-warnings "Direct link to Opting-in to warnings") By default, Stencil will not log a warning if a file or directory specified in `src` cannot be located. To opt-in to warnings if a copy task source cannot be found, set `warn: true` in the `CopyTask` object, like so: outputTargets: [ { type: 'dist', copy: [ { src: 'fonts', warn: true } ] } ] Contents -------- * [Options](https://stenciljs.com/docs/next/copy-tasks#options) * [Examples](https://stenciljs.com/docs/next/copy-tasks#examples) * [Images in the `www` Output Target](https://stenciljs.com/docs/next/copy-tasks#images-in-the-www-output-target) * [Setting the `dest` option](https://stenciljs.com/docs/next/copy-tasks#setting-the-dest-option) * [Opting-in to warnings](https://stenciljs.com/docs/next/copy-tasks#opting-in-to-warnings) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/output-targets/copy-tasks.md) --- # Extras Config | Stencil [Skip to main content](https://stenciljs.com/docs/next/config-extras#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/config-extras) ** (v4.35). Version: Next On this page The `extras` config contains options to enable new/experimental features in Stencil, add & remove runtime for DOM features that require manipulations to polyfills, etc. For example, not all DOM APIs are fully polyfilled when using the Slot polyfill. Most of these are opt-in, since not all users require the additional runtime. ### appendChildSlotFix[​](https://stenciljs.com/docs/next/config-extras#appendchildslotfix "Direct link to appendChildSlotFix") By default, the slot polyfill does not update `appendChild()` so that it appends new child nodes into the correct child slot like how shadow dom works. This is an opt-in polyfill for those who need it. ### cloneNodeFix[​](https://stenciljs.com/docs/next/config-extras#clonenodefix "Direct link to cloneNodeFix") By default, the runtime does not polyfill `cloneNode()` when cloning a component that uses the slot polyfill. This is an opt-in polyfill for those who need it. ### tagNameTransform[​](https://stenciljs.com/docs/next/config-extras#tagnametransform "Direct link to tagNameTransform") The `tagNameTransform` option in the `extras` config enables support for customizing the tag names of your Stencil components at runtime. This is especially useful if you want to add a prefix, suffix, or otherwise modify the tag names when registering your custom elements, for example to avoid naming conflicts. When `tagNameTransform` is enabled in your `stencil.config.ts`: extras: { tagNameTransform: true} You can use the `transformTagName` function when calling `defineCustomElements` in your consuming project: import { defineCustomElements } from 'my-button/loader';defineCustomElements(window, { transformTagName: (tagName: string) => `${tagName}`} as never); In this example, the function simply returns the original tag name, but you can customize it as needed. For example, to add a suffix: defineCustomElements(window, { transformTagName: (tagName: string) => `${tagName}-v1`} as never); With this configuration, a component originally named `` would be registered as ``. **Note:** * The `tagNameTransform` option in your Stencil config enables this feature at build time. * The `transformTagName` function is used at runtime when registering the components. ### enableImportInjection[​](https://stenciljs.com/docs/next/config-extras#enableimportinjection "Direct link to enableImportInjection") In some cases, it can be difficult to lazily load Stencil components in a separate project that uses a bundler such as [Vite](https://vitejs.dev/) . Enabling this flag will allow downstream projects that consume a Stencil library and use a bundler such as Vite to lazily load the Stencil library's components. In order for this flag to work: 1. The Stencil library must expose lazy loadable components, such as those created with the [`dist` output target](https://stenciljs.com/docs/next/distribution) 2. The Stencil library must be recompiled with this flag set to `true` This flag works by creating dynamic import statements for every lazily loadable component in a Stencil project. Users of this flag should note that they may see an increase in their bundle size. Defaults to `false`. ### experimentalImportInjection[​](https://stenciljs.com/docs/next/config-extras#experimentalimportinjection "Direct link to experimentalImportInjection") caution This flag has been deprecated in favor of [`enableImportInjection`](https://stenciljs.com/docs/next/config-extras#enableimportinjection) , which provides the same functionality. `experimentalImportInjection` will be removed in a future major version of Stencil. In some cases, it can be difficult to lazily load Stencil components in a separate project that uses a bundler such as [Vite](https://vitejs.dev/) . This is an experimental flag that, when set to `true`, will allow downstream projects that consume a Stencil library and use a bundler such as Vite to lazily load the Stencil library's components. In order for this flag to work: 1. The Stencil library must expose lazy loadable components, such as those created with the [`dist` output target](https://stenciljs.com/docs/next/distribution) 2. The Stencil library must be recompiled with this flag set to `true` This flag works by creating dynamic import statements for every lazily loadable component in a Stencil project. Users of this flag should note that they may see an increase in their bundle size. Defaults to `false`. ### experimentalScopedSlotChanges[​](https://stenciljs.com/docs/next/config-extras#experimentalscopedslotchanges "Direct link to experimentalScopedSlotChanges") This option updates runtime behavior for Stencil's support of slots in **scoped** components to match more closely with the native Shadow DOM behaviors. When set to `true`, the following behaviors will be applied: * Stencil will hide projected nodes that do not have a destination `slot` ([#2778](https://github.com/ionic-team/stencil/issues/2877) ) (since v4.10.0) * The `textContent` getter will return the text content of all nodes located in a slot (since v4.10.0) * The `textContent` setter will overwrite all nodes located in a slot (since v4.10.0) Defaults to `false`. note These behaviors only apply to components using scoped encapsulation! ### experimentalSlotFixes[​](https://stenciljs.com/docs/next/config-extras#experimentalslotfixes "Direct link to experimentalSlotFixes") This option enables all current and future slot-related fixes. When enabled it will enable the following options, overriding their values if they are specified separately: * [`slotChildNodesFix`](https://stenciljs.com/docs/next/config-extras#slotchildnodesfix) * [`scopedSlotTextContentFix`](https://stenciljs.com/docs/next/config-extras#scopedslottextcontentfix) . * [`appendChildSlotFix`](https://stenciljs.com/docs/next/config-extras#appendchildslotfix) * [`cloneNodeFix`](https://stenciljs.com/docs/next/config-extras#clonenodefix) Slot-related fixes to the runtime will be added over the course of Stencil v4, with the intent of making these the default behavior in Stencil v5. When set to `true` fixes for the following issues will be applied: * Elements rendered outside of slot when shadow not enabled [(#2641)](https://github.com/ionic-team/stencil/issues/2641) (since v4.2.0) * A slot gets the attribute hidden when it shouldn't [(#4523)](https://github.com/ionic-team/stencil/issues/4523) (since v4.7.0) * Nested slots mis-ordered when not using Shadow DOM [(#2997)](https://github.com/ionic-team/stencil/issues/2997) (since v4.7.0) * Inconsistent behavior: slot-fb breaks styling of default slot content in component with 'shadow: false' [(#2937)](https://github.com/ionic-team/stencil/issues/2937) (since v4.7.2) * Slot content went missing within dynamic component [(#4284)](https://github.com/ionic-team/stencil/issues/4284) (since v4.8.2) * Slot element loses its parent reference and disappears when its parent is rendered conditionally [(#3913)](https://github.com/ionic-team/stencil/issues/3913) (since v4.8.2) * Failed to execute 'removeChild' on 'Node' [(#3278)](https://github.com/ionic-team/stencil/issues/3278) (since v4.9.0) * React fails to manage children in Stencil slot [(#2259)](https://github.com/ionic-team/stencil/issues/2259) (since v4.9.0) * Slot name is not updated when it is bind to a prop [(#2982)](https://github.com/ionic-team/stencil/issues/2982) (since 4.12.1) * Conditionally rendered slots not working [(#5335)](https://github.com/ionic-team/stencil/issues/5335) (since 4.13.0) note New fixes enabled by this experimental flag are not subject to Stencil's [semantic versioning policy](https://stenciljs.com/docs/next/versioning) . ### lifecycleDOMEvents[​](https://stenciljs.com/docs/next/config-extras#lifecycledomevents "Direct link to lifecycleDOMEvents") Dispatches component lifecycle events. By default these events are not dispatched, but by enabling this to `true` these events can be listened for on `window`. Mainly used for testing. | Event Name | Description | | --- | --- | | `stencil_componentWillLoad` | Dispatched for each component's `componentWillLoad`. | | `stencil_componentWillUpdate` | Dispatched for each component's `componentWillUpdate`. | | `stencil_componentWillRender` | Dispatched for each component's `componentWillRender`. | | `stencil_componentDidLoad` | Dispatched for each component's `componentDidLoad`. | | `stencil_componentDidUpdate` | Dispatched for each component's `componentDidUpdate`. | | `stencil_componentDidRender` | Dispatched for each component's `componentDidRender`. | ### scopedSlotTextContentFix[​](https://stenciljs.com/docs/next/config-extras#scopedslottextcontentfix "Direct link to scopedSlotTextContentFix") An experimental flag that when set to `true`, aligns the behavior of invoking the `textContent` getter/setter on a scoped component to act more like a component that uses the shadow DOM. Specifically, invoking `textContent` on a component will adhere to the return values described in [MDN's article on textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#description) . Defaults to `false`. ### scriptDataOpts[​](https://stenciljs.com/docs/next/config-extras#scriptdataopts "Direct link to scriptDataOpts") caution This option has been deprecated and will be removed in the next major Stencil release. It is possible to assign data to the actual ``. * The initial script itself is extremely tiny and does not represent the entire library. It's only a small registry. * You can use any or all components within your library anywhere within that webpage. * It doesn't matter if the actual component was written within the HTML or created with vanilla JavaScript, jQuery, React, etc. * Only the components used on that page will be requested and lazy-loaded. ### Importing the `dist` library using a bundler[​](https://stenciljs.com/docs/next/distribution#importing-the-dist-library-using-a-bundler "Direct link to importing-the-dist-library-using-a-bundler") * Run `npm install my-name --save` * Add an `import` within the root component: `import my-component`; * Stencil will automatically setup the lazy-loading capabilities for the Stencil library. * Then you can use the element anywhere in your template, JSX, HTML etc. ### Importing the `dist` library into another Stencil app[​](https://stenciljs.com/docs/next/distribution#importing-the-dist-library-into-another-stencil-app "Direct link to importing-the-dist-library-into-another-stencil-app") * Run `npm install my-name --save` * Add an `import` within the root component: `import my-component`; * Stencil will automatically setup the lazy-loading capabilities for the Stencil library. * Then you can use the element anywhere in your template, JSX, HTML etc. Contents -------- * [Config](https://stenciljs.com/docs/next/distribution#config) * [collectionDir](https://stenciljs.com/docs/next/distribution#collectiondir) * [dir](https://stenciljs.com/docs/next/distribution#dir) * [empty](https://stenciljs.com/docs/next/distribution#empty) * [isPrimaryPackageOutputTarget](https://stenciljs.com/docs/next/distribution#isprimarypackageoutputtarget) * [transformAliasedImportPathsInCollection](https://stenciljs.com/docs/next/distribution#transformaliasedimportpathsincollection) * [esmLoaderPath](https://stenciljs.com/docs/next/distribution#esmloaderpath) * [Publishing](https://stenciljs.com/docs/next/distribution#publishing) * [Loader](https://stenciljs.com/docs/next/distribution#loader) * [Distribution Options](https://stenciljs.com/docs/next/distribution#distribution-options) * [Script tag](https://stenciljs.com/docs/next/distribution#script-tag) * [Importing the `dist` library using a bundler](https://stenciljs.com/docs/next/distribution#importing-the-dist-library-using-a-bundler) * [Importing the `dist` library into another Stencil app](https://stenciljs.com/docs/next/distribution#importing-the-dist-library-into-another-stencil-app) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/output-targets/dist.md) --- # Component Lifecycle Methods | Stencil [Skip to main content](https://stenciljs.com/docs/next/component-lifecycle#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/component-lifecycle) ** (v4.35). Version: Next On this page Components have numerous lifecycle methods which can be used to know when the component "will" and "did" load, update, and render. These methods can be added to a component to hook into operations at the right time. Implement one of the following methods within a component class and Stencil will automatically call them in the right order: componentDidLoad()componentDidUpdate()disconnectedCallback()@Watch(‘propName’)render()connectedCallback()componentShouldUpdate()componentWillRender()componentWillUpdate()componentDidRender()componentWillLoad()Component initializedChange in a value of prop or state triggers rerenderComponent removedComponent reattached connectedCallback()[​](https://stenciljs.com/docs/next/component-lifecycle#connectedcallback "Direct link to connectedCallback()") ----------------------------------------------------------------------------------------------------------------------------------- Called every time the component is connected to the DOM. When the component is first connected, this method is called before `componentWillLoad`. It's important to note that this method can be called more than once, every time, the element is **attached** or **moved** in the DOM. For logic that needs to run every time the element is attached or moved in the DOM, it is considered a best practice to use this lifecycle method. const el = document.createElement('my-cmp');document.body.appendChild(el);// connectedCallback() called// componentWillLoad() called (first time)el.remove();// disconnectedCallback()document.body.appendChild(el);// connectedCallback() called again, but `componentWillLoad()` is not. This `lifecycle` hook follows the same semantics as the one described by the [Custom Elements Spec](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) disconnectedCallback()[​](https://stenciljs.com/docs/next/component-lifecycle#disconnectedcallback "Direct link to disconnectedCallback()") -------------------------------------------------------------------------------------------------------------------------------------------- Called every time the component is disconnected from the DOM, ie, it can be dispatched more than once, DO not confuse with a "onDestroy" kind of event. This `lifecycle` hook follows the same semantics as the one described by the [Custom Elements Spec](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) . componentWillLoad()[​](https://stenciljs.com/docs/next/component-lifecycle#componentwillload "Direct link to componentWillLoad()") ----------------------------------------------------------------------------------------------------------------------------------- Called once just after the component is first connected to the DOM. Since this method is only called once, it's a good place to load data asynchronously and to setup the state without triggering extra re-renders. A promise can be returned, that can be used to wait for the first `render()`. componentDidLoad()[​](https://stenciljs.com/docs/next/component-lifecycle#componentdidload "Direct link to componentDidLoad()") -------------------------------------------------------------------------------------------------------------------------------- Called once just after the component is fully loaded and the first `render()` occurs. componentShouldUpdate()[​](https://stenciljs.com/docs/next/component-lifecycle#componentshouldupdate "Direct link to componentShouldUpdate()") ----------------------------------------------------------------------------------------------------------------------------------------------- This hook is called when a component's [`Prop`](https://stenciljs.com/docs/next/properties) or [`State`](https://stenciljs.com/docs/next/state) property changes and a rerender is about to be requested. This hook receives three arguments: the new value, the old value and the name of the changed state. It should return a boolean to indicate if the component should rerender (`true`) or not (`false`). A couple of things to notice is that this method will not be executed before the initial render, that is, when the component is first attached to the dom, nor when a rerender is already scheduled in the next frame. Let’s say the following two props of a component change synchronously: component.somePropA = 42;component.somePropB = 88; The `componentShouldUpdate` will be first called with arguments: `42`, `undefined` and `somePropA`. If it does return `true`, the hook will not be called again since the rerender is already scheduled to happen. Instead, if the first hook returned `false`, then `componentShouldUpdate` will be called again with `88`, `undefined` and `somePropB` as arguments, triggered by the `component.somePropB = 88` mutation. Since the execution of this hook might be conditioned, it's not good to rely on it to watch for prop changes, instead use the `@Watch` decorator for that. componentWillRender()[​](https://stenciljs.com/docs/next/component-lifecycle#componentwillrender "Direct link to componentWillRender()") ----------------------------------------------------------------------------------------------------------------------------------------- Called before every `render()`. A promise can be returned, that can be used to wait for the upcoming render. componentDidRender()[​](https://stenciljs.com/docs/next/component-lifecycle#componentdidrender "Direct link to componentDidRender()") -------------------------------------------------------------------------------------------------------------------------------------- Called after every `render()`. componentWillUpdate()[​](https://stenciljs.com/docs/next/component-lifecycle#componentwillupdate "Direct link to componentWillUpdate()") ----------------------------------------------------------------------------------------------------------------------------------------- Called when the component is about to be updated because some `Prop()` or `State()` changed. It's never called during the first `render()`. A promise can be returned, that can be used to wait for the next render. componentDidUpdate()[​](https://stenciljs.com/docs/next/component-lifecycle#componentdidupdate "Direct link to componentDidUpdate()") -------------------------------------------------------------------------------------------------------------------------------------- Called just after the component updates. It's never called during the first `render()`. Rendering State[​](https://stenciljs.com/docs/next/component-lifecycle#rendering-state "Direct link to Rendering State") ------------------------------------------------------------------------------------------------------------------------- It's always recommended to make any rendered state updates within `componentWillRender()`, since this is the method which get called _before_ the `render()` method. Alternatively, updating rendered state with the `componentDidLoad()`, `componentDidUpdate()` and `componentDidRender()` methods will cause another rerender, which isn't ideal for performance. If state _must_ be updated in `componentDidUpdate()` or `componentDidRender()`, it has the potential of getting components stuck in an infinite loop. If updating state within `componentDidUpdate()` is unavoidable, then the method should also come with a way to detect if the props or state is "dirty" or not (is the data actually different or is it the same as before). By doing a dirty check, `componentDidUpdate()` is able to avoid rendering the same data, and which in turn calls `componentDidUpdate()` again. Lifecycle Hierarchy[​](https://stenciljs.com/docs/next/component-lifecycle#lifecycle-hierarchy "Direct link to Lifecycle Hierarchy") ------------------------------------------------------------------------------------------------------------------------------------- A useful feature of lifecycle methods is that they take their child component's lifecycle into consideration too. For example, if the parent component, `cmp-a`, has a child component, `cmp-b`, then `cmp-a` isn't considered "loaded" until `cmp-b` has finished loading. Another way to put it is that the deepest components finish loading first, then the `componentDidLoad()` calls bubble up. It's also important to note that even though Stencil can lazy-load components, and has asynchronous rendering, the lifecycle methods are still called in the correct order. So while the top-level component could have already been loaded, all of its lifecycle methods are still called in the correct order, which means it'll wait for a child components to finish loading. The same goes for the exact opposite, where the child components may already be ready while the parent isn't. In the example below we have a simple hierarchy of components. The numbered list shows the order of which the lifecycle methods will fire. 1. `cmp-a` - `componentWillLoad()` 2. `cmp-b` - `componentWillLoad()` 3. `cmp-c` - `componentWillLoad()` 4. `cmp-c` - `componentDidLoad()` 5. `cmp-b` - `componentDidLoad()` 6. `cmp-a` - `componentDidLoad()` Even if some components may or may not be already loaded, the entire component hierarchy waits on its child components to finish loading and rendering. Async Lifecycle Methods[​](https://stenciljs.com/docs/next/component-lifecycle#async-lifecycle-methods "Direct link to Async Lifecycle Methods") ------------------------------------------------------------------------------------------------------------------------------------------------- Some lifecycle methods, e.g. `componentWillRender`, `componentWillLoad` and `componentWillUpdate`, can also return promises which allows the method to asynchronously retrieve data or perform any async tasks. A great example of this is fetching data to be rendered in a component. For example, this very site you're reading first fetches content data before rendering. But because `fetch()` is async, it's important that `componentWillLoad()` returns a `Promise` to ensure its parent component isn't considered "loaded" until all of its content has rendered. Below is a quick example showing how `componentWillLoad()` is able to have its parent component wait on it to finish loading its data. componentWillLoad() { return fetch('/some-data.json') .then(response => response.json()) .then(data => { this.content = data; });} Example[​](https://stenciljs.com/docs/next/component-lifecycle#example "Direct link to Example") ------------------------------------------------------------------------------------------------- This simple example shows a clock and updates the current time every second. The timer is started when the component is added to the DOM. Once it's removed from the DOM, the timer is stopped. import { Component, State, h } from '@stencil/core';@Component({ tag: 'custom-clock'})export class CustomClock { timer: number; @State() time: number = Date.now(); connectedCallback() { this.timer = window.setInterval(() => { this.time = Date.now(); }, 1000); } disconnectedCallback() { window.clearInterval(this.timer); } render() { const time = new Date(this.time).toLocaleTimeString(); return ( { time } ); }} Contents -------- * [connectedCallback()](https://stenciljs.com/docs/next/component-lifecycle#connectedcallback) * [disconnectedCallback()](https://stenciljs.com/docs/next/component-lifecycle#disconnectedcallback) * [componentWillLoad()](https://stenciljs.com/docs/next/component-lifecycle#componentwillload) * [componentDidLoad()](https://stenciljs.com/docs/next/component-lifecycle#componentdidload) * [componentShouldUpdate()](https://stenciljs.com/docs/next/component-lifecycle#componentshouldupdate) * [componentWillRender()](https://stenciljs.com/docs/next/component-lifecycle#componentwillrender) * [componentDidRender()](https://stenciljs.com/docs/next/component-lifecycle#componentdidrender) * [componentWillUpdate()](https://stenciljs.com/docs/next/component-lifecycle#componentwillupdate) * [componentDidUpdate()](https://stenciljs.com/docs/next/component-lifecycle#componentdidupdate) * [Rendering State](https://stenciljs.com/docs/next/component-lifecycle#rendering-state) * [Lifecycle Hierarchy](https://stenciljs.com/docs/next/component-lifecycle#lifecycle-hierarchy) * [Async Lifecycle Methods](https://stenciljs.com/docs/next/component-lifecycle#async-lifecycle-methods) * [Example](https://stenciljs.com/docs/next/component-lifecycle#example) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/components/component-lifecycle.md) --- # Component API | Stencil [Skip to main content](https://stenciljs.com/docs/next/api#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/api) ** (v4.35). Version: Next On this page The whole API provided by stencil can be condensed in a set of decorators, lifecycles hooks and rendering methods. Decorators[​](https://stenciljs.com/docs/next/api#decorators "Direct link to Decorators") ------------------------------------------------------------------------------------------ Decorators are a pure compiler-time construction used by stencil to collect all the metadata about a component, the properties, attributes and methods it might expose, the events it might emit or even the associated stylesheets. Once all the metadata has been collected, all the decorators are removed from the output, so they don't incur any runtime overhead. * [@Component()](https://stenciljs.com/docs/next/component) declares a new web component * [@Prop()](https://stenciljs.com/docs/next/properties#the-prop-decorator-prop) declares an exposed property/attribute * [@State()](https://stenciljs.com/docs/next/state#the-state-decorator-state) declares an internal state of the component * [@Watch()](https://stenciljs.com/docs/next/reactive-data#the-watch-decorator-watch) declares a hook that runs when a property or state changes * [@Element()](https://stenciljs.com/docs/next/host-element#element-decorator) declares a reference to the host element * [@Method()](https://stenciljs.com/docs/next/methods) declares an exposed public method * [@Event()](https://stenciljs.com/docs/next/events#event-decorator) declares a DOM event the component might emit * [@Listen()](https://stenciljs.com/docs/next/events#listen-decorator) listens for DOM events Lifecycle hooks[​](https://stenciljs.com/docs/next/api#lifecycle-hooks "Direct link to Lifecycle hooks") --------------------------------------------------------------------------------------------------------- * [connectedCallback()](https://stenciljs.com/docs/next/component-lifecycle#connectedcallback) * [disconnectedCallback()](https://stenciljs.com/docs/next/component-lifecycle#disconnectedcallback) * [componentWillLoad()](https://stenciljs.com/docs/next/component-lifecycle#componentwillload) * [componentDidLoad()](https://stenciljs.com/docs/next/component-lifecycle#componentdidload) * [componentShouldUpdate(newValue, oldValue, propName): boolean](https://stenciljs.com/docs/next/component-lifecycle#componentshouldupdate) * [componentWillRender()](https://stenciljs.com/docs/next/component-lifecycle#componentwillrender) * [componentDidRender()](https://stenciljs.com/docs/next/component-lifecycle#componentdidrender) * [componentWillUpdate()](https://stenciljs.com/docs/next/component-lifecycle#componentwillupdate) * [componentDidUpdate()](https://stenciljs.com/docs/next/component-lifecycle#componentdidupdate) * **[render()](https://stenciljs.com/docs/next/templating-jsx) ** componentOnReady()[​](https://stenciljs.com/docs/next/api#componentonready "Direct link to componentOnReady()") ---------------------------------------------------------------------------------------------------------------- This isn't a true "lifecycle" method that would be declared on the component class definition, but instead is a utility method that can be used by an implementation consuming your Stencil component to detect when a component has finished its first render cycle. This method returns a promise which resolves after `componentDidRender()` on the _first_ render cycle. note `componentOnReady()` only resolves once per component lifetime. If you need to hook into subsequent render cycle, use `componentDidRender()` or `componentDidUpdate()`. Executing code after `componentOnReady()` resolves could look something like this: // Get a reference to the elementconst el = document.querySelector('my-component');el.componentOnReady().then(() => { // Place any code in here you want to execute when the component is ready console.log('my-component is ready');}); The availability of `componentOnReady()` depends on the component's compiled output type. This method is only available for lazy-loaded distribution types ([`dist`](https://stenciljs.com/docs/next/distribution) and [`www`](https://stenciljs.com/docs/next/www) ) and, as such, is not available for [`dist-custom-elements`](https://stenciljs.com/docs/next/custom-elements) output. If you want to simulate the behavior of `componentOnReady()` for non-lazy builds, you can implement a helper method to wrap the functionality similar to what the Ionic Framework does [here](https://github.com/ionic-team/ionic-framework/blob/main/core/src/utils/helpers.ts#L60-L79) . The `appload` event[​](https://stenciljs.com/docs/next/api#the-appload-event "Direct link to the-appload-event") ----------------------------------------------------------------------------------------------------------------- In addition to component-specific lifecycle hooks, a special event called `appload` will be emitted when the app and all of its child components have finished loading. You can listen for it on the `window` object. If you have multiple apps on the same page, you can determine which app emitted the event by checking `event.detail.namespace`. This will be the value of the [namespace config option](https://stenciljs.com/docs/next/config#namespace) you've set in your Stencil config. window.addEventListener('appload', (event) => { console.log(event.detail.namespace);}); Other[​](https://stenciljs.com/docs/next/api#other "Direct link to Other") --------------------------------------------------------------------------- The following primitives can be imported from the `@stencil/core` package and used within the lifecycle of a component: * [**Host**](https://stenciljs.com/docs/next/host-element) : ``, is a functional component that can be used at the root of the render function to set attributes and event listeners to the host element itself. Refer to the [Host Element](https://stenciljs.com/docs/next/host-element) page for usage info. * **Fragment**: ``, often used via `<>...` syntax, lets you group elements without a wrapper node. To use this feature, ensure that the following TypeScript compiler options are set: * [`jsxFragmentFactory` is set](https://www.typescriptlang.org/tsconfig#jsxFragmentFactory) to "Fragment" * [`jsxFactory` is set](https://www.typescriptlang.org/tsconfig#jsxFactory) to "h" **Type:** `FunctionalComponent` **Example:** import { Component, Fragment, h } from '@stencil/core'@Component({ tag: 'cmp-fragment',})export class CmpFragment { render() { return ( <>
...
...
...
); }} * [**h()**](https://stenciljs.com/docs/next/templating-jsx) : It's used within the `render()` to turn the JSX into Virtual DOM elements. * **render()**: a utility method to render a virtual DOM created by `h()` into a container. **Type:** `(vnode: VNode, container: Element) => void` **Example:** import { render } from '@stencil/core'const vdom = (
Hello World!
)render(vdom, document.body) * [**readTask()**](https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing) : Schedules a DOM-read task. The provided callback will be executed in the best moment to perform DOM reads without causing layout thrashing. **Type:** `(task: Function) => void` * [**writeTask()**](https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing) : Schedules a DOM-write task. The provided callback will be executed in the best moment to perform DOM mutations without causing layout thrashing. **Type:** `(task: Function) => void` * **forceUpdate()**: Schedules a new render of the given instance or element even if no state changed. Notice `forceUpdate()` is not synchronous and might perform the DOM render in the next frame. **Type:** `(ref: any) => void` **Example:** import { forceUpdate } from '@stencil/core'// inside a class component functionforceUpdate(this); * **getAssetPath()**: Gets the path to local assets. Refer to the [Assets](https://stenciljs.com/docs/next/assets#getassetpath) page for usage info. **Type:** `(path: string) => string` **Example:** import { Component, Prop, getAssetPath, h } from '@stencil/core'@Component({ tag: 'cmp-asset',})export class CmpAsset { @Prop() icon: string; render() { return ( ); }} * **setAssetPath()**: Sets the path for Stencil to resolve local assets. Refer to the [Assets](https://stenciljs.com/docs/next/assets#setassetpath) page for usage info. **Type:** `(path: string) => string` **Example:** import { setAssetPath } from '@stencil/core';setAssetPath(`{window.location.origin}/`); * **setMode()**: Sets the style mode of a component. Refer to the [Styling](https://stenciljs.com/docs/next/styling#style-modes) page for usage info. **Type:** `((elm: HTMLElement) => string | undefined | null) => void` **Example:** import { setMode } from '@stencil/core'// set mode based on a propertysetMode((el) => el.getAttribute('mode')); * **getMode()**: Get the current style mode of your application. Refer to the [Styling](https://stenciljs.com/docs/next/styling#style-modes) page for usage info. **Type:** `(ref: any) => string | undefined` **Example:** import { getMode } from '@stencil/core'getMode(this); * **getElement()**: Retrieve a Stencil element for a given reference. **Type:** `(ref: any) => HTMLStencilElement` **Example:** import { getElement } from '@stencil/core'const stencilComponent = getElement(document.querySelector('my-cmp'))if (stencilComponent) { stencilComponent.componentOnReady().then(() => { ... })} Contents -------- * [Decorators](https://stenciljs.com/docs/next/api#decorators) * [Lifecycle hooks](https://stenciljs.com/docs/next/api#lifecycle-hooks) * [componentOnReady()](https://stenciljs.com/docs/next/api#componentonready) * [The `appload` event](https://stenciljs.com/docs/next/api#the-appload-event) * [Other](https://stenciljs.com/docs/next/api#other) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/components/api.md) --- # Documentation Generation Config | Stencil [Skip to main content](https://stenciljs.com/docs/next/docs-config#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/docs-config) ** (v4.35). Version: Next On this page The `docs` config option allows global configuration of certain behaviors related to [documentation generation output targets](https://stenciljs.com/docs/next/doc-generation) . note These configurations are **global** and will be applied to all output target instances including those defined in the [`outputTargets`](https://stenciljs.com/docs/next/output-targets) configuration, as well as those injected by CLI flags (like `--docs`). markdown[​](https://stenciljs.com/docs/next/docs-config#markdown "Direct link to markdown") -------------------------------------------------------------------------------------------- The `markdown` config object allows certain customizations for markdown files generated by the [`docs-readme` output target](https://stenciljs.com/docs/next/docs-readme) or the `--docs` CLI flag. ### targetComponent[​](https://stenciljs.com/docs/next/docs-config#targetcomponent "Direct link to targetComponent") **Optional** **Default: `{ textColor: '#333', background: '#f9f' }`** This option allows you to change the colors used when generating the dependency graph mermaid diagrams for components. Any hex color string is a valid value. stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { docs: { markdown: { targetComponent: { textColor: '#fff', background: '#000', }, }, },}; Contents -------- * [markdown](https://stenciljs.com/docs/next/docs-config#markdown) * [targetComponent](https://stenciljs.com/docs/next/docs-config#targetcomponent) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/config/docs.md) --- # Component Decorator | Stencil [Skip to main content](https://stenciljs.com/docs/next/component#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/component) ** (v4.35). Version: Next On this page `@Component()` is a decorator that designates a TypeScript class as a Stencil component. Every Stencil component gets transformed into a web component at build time. import { Component } from '@stencil/core';@Component({ tag: 'todo-list', // additional options})export class TodoList { // implementation omitted} Component Options[​](https://stenciljs.com/docs/next/component#component-options "Direct link to Component Options") --------------------------------------------------------------------------------------------------------------------- The `@Component()` decorator takes one argument, an object literal containing configuration options for the component. This allows each component to be individually configured to suit the unique needs of each project. Each option, its type, and whether it's required is described below. ### tag[​](https://stenciljs.com/docs/next/component#tag "Direct link to tag") **Required** **Type: `string`** **Details:** This value sets the name of the custom element that Stencil will generate. To adhere to the [HTML spec](https://html.spec.whatwg.org/#valid-custom-element-name) , the tag name must contain a dash ('-'). Ideally, the tag name is a globally unique value. Having a globally unique value helps prevent naming collisions with the global `CustomElementsRegistry`, where all custom elements are defined. It's recommended to choose a unique prefix for all your components within the same collection. **Example**: import { Component } from '@stencil/core';@Component({ tag: 'todo-list',})export class TodoList { // implementation omitted} After compilation, the component defined in `TodoList` can be used in HTML or another TSX file: {/* Here we use the component in a TSX file */} ### assetsDirs[​](https://stenciljs.com/docs/next/component#assetsdirs "Direct link to assetsDirs") **Optional** **Type: `string[]`** **Details:** `assetsDirs` is an array of relative paths from the component to a directory containing the static files (assets) the component requires. **Example**: Below is an example project's directory structure containing an example component and assets directory. src/└── components/ ├── assets/ │ └── sunset.jpg └── todo-list.tsx Below, the `todo-list` component will correctly load the `sunset.jpg` image from the `assets/` directory, using Stencil's [`getAssetPath()`](https://stenciljs.com/docs/next/assets#getassetpath) . import { Component, Prop, getAssetPath, h } from '@stencil/core';@Component({ tag: 'todo-list', // 1. assetsDirs lists the 'assets' directory as a relative (sibling) // directory assetsDirs: ['assets']})export class TodoList { image = "sunset.jpg"; render() { // 2. the asset path is retrieved relative to the asset base path to use in // the tag const imageSrc = getAssetPath(`./assets/${this.image}`); return }} In the example above, the following allows `todo-list` to display the provided asset: 1. The `TodoList`'s `@Component()` decorator has the `assetsDirs` property, and lists the file's sibling directory, `assets/`. This will copy the `assets` directory over to the distribution directory. 2. Stencil's [`getAssetPath()`](https://stenciljs.com/docs/next/assets#getassetpath) is used to retrieve the path to the image to be used in the `` tag For more information on configuring assets, please see Stencil's [Assets Guide](https://stenciljs.com/docs/next/assets) ### formAssociated[​](https://stenciljs.com/docs/next/component#formassociated "Direct link to formAssociated") **Optional** **Type: `boolean`** **Default: `false`** If `true` the component will be [form-associated](https://html.spec.whatwg.org/dev/custom-elements.html#form-associated-custom-element) , allowing you to take advantage of the [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals) API to enable your Stencil component to participate in forms. A minimal form-associated Stencil component could look like this: import { Component } from '@stencil/core';@Component({ tag: 'form-associated', formAssociated: true})export class FormAssociated { render() { return form associated! }} See the documentation for [form-associated components](https://stenciljs.com/docs/next/form-associated) for more info and examples. ### scoped[​](https://stenciljs.com/docs/next/component#scoped "Direct link to scoped") **Optional** **Type: `boolean`** **Default: `false`** **Details:** If `true`, the component will use [scoped stylesheets](https://stenciljs.com/docs/next/styling#scoped-css) . Scoped CSS is an alternative to using the native [shadow DOM](https://stenciljs.com/docs/next/styling#shadow-dom) style encapsulation. It appends a data attribute to your styles to make them unique and thereby scope them to your component. It does not, however, prevent styles from the light DOM from seeping into your component. To use the native [shadow DOM](https://stenciljs.com/docs/next/styling#shadow-dom) , see the configuration for [`shadow`](https://stenciljs.com/docs/next/component#shadow) . This option cannot be set to `true` if `shadow` is enabled. **Example**: import { Component } from '@stencil/core';@Component({ tag: 'todo-list', scoped: true})export class TodoList { // implementation omitted} ### shadow[​](https://stenciljs.com/docs/next/component#shadow "Direct link to shadow") **Optional** **Type: `boolean | { delegatesFocus: boolean }`** **Default: `false`** **Details:** If `true`, the component will use [native Shadow DOM encapsulation](https://stenciljs.com/docs/next/styling#shadow-dom) . It will fall back to `scoped` if the browser does not support shadow-dom natively. `delegatesFocus` is a property that [provides focus](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/delegatesFocus) to the first focusable entry in a component using Shadow DOM. If an object literal containing `delegatesFocus` is provided, the component will use [native Shadow DOM encapsulation](https://stenciljs.com/docs/next/styling#shadow-dom) , regardless of the value assigned to `delegatesFocus`. When `delegatesFocus` is set to `true`, the component will have `delegatesFocus: true` added to its shadow DOM. When `delegatesFocus` is `true` and a non-focusable part of the component is clicked: * the first focusable part of the component is given focus * the component receives any available `focus` styling If `shadow` is set to `false`, the component will not use native shadow DOM encapsulation. This option cannot be set to enabled if `scoped` is enabled. **Example 1**: import { Component } from '@stencil/core';@Component({ tag: 'todo-list', shadow: true})export class TodoList { // implementation omitted} **Example 2**: import { Component } from '@stencil/core';@Component({ tag: 'todo-list', shadow: { delegatesFocus: true, }})export class TodoList { // implementation omitted} ### styleUrl[​](https://stenciljs.com/docs/next/component#styleurl "Direct link to styleUrl") **Optional** **Type: `string`** **Details:** Relative URL to an external stylesheet containing styles to apply to your component. Out of the box, Stencil will only process CSS files (files ending with `.css`). Support for additional CSS variants, like Sass, can be added via [a plugin](https://stenciljs.com/docs/plugins#related-plugins) . **Example**: Below is an example project's directory structure containing an example component and stylesheet. src/└── components/ ├── todo-list.css └── todo-list.tsx By setting `styleUrl`, Stencil will apply the `todo-list.css` stylesheet to the `todo-list` component: import { Component } from '@stencil/core';@Component({ tag: 'todo-list', styleUrl: './todo-list.css',})export class TodoList { // implementation omitted} ### styleUrls[​](https://stenciljs.com/docs/next/component#styleurls "Direct link to styleUrls") **Optional** **Type: `string[] | { [modeName: string]: string | string[]; }`** **Details:** A list of relative URLs to external stylesheets containing styles to apply to your component. Alternatively, an object can be provided that maps a named "mode" to one or more stylesheets. Out of the box, Stencil will only process CSS files (ending with `.css`). Support for additional CSS variants, like Sass, can be added via [a plugin](https://stenciljs.com/docs/plugins#related-plugins) . **Example**: Below is an example project's directory structure containing an example component and stylesheet. src/└── components/ ├── todo-list-1.css ├── todo-list-2.css └── todo-list.tsx By setting `styleUrls`, Stencil will apply both stylesheets to the `todo-list` component: Using an array of styles import { Component } from '@stencil/core';@Component({ tag: 'todo-list', styleUrls: ['./todo-list-1.css', './todo-list-2.css']})export class TodoList { // implementation omitted} Using modes import { Component } from '@stencil/core';@Component({ tag: 'todo-list', styleUrls: { ios: 'todo-list-1.ios.scss', md: 'todo-list-2.md.scss', }})export class TodoList { // implementation omitted} Read more on styling modes in the Components [Styling](https://stenciljs.com/docs/next/styling#style-modes) section. ### styles[​](https://stenciljs.com/docs/next/component#styles "Direct link to styles") **Optional** **Type: `string | { [modeName: string]: any }`** **Details:** A string that contains inlined CSS instead of using an external stylesheet. The performance characteristics of this feature are the same as using an external stylesheet. When using `styles`, only CSS is permitted. See [`styleUrl`](https://stenciljs.com/docs/next/component#styleurl) if you need more advanced features. **Example**: import { Component } from '@stencil/core';@Component({ tag: 'todo-list', styles: 'div { background-color: #fff }'})export class TodoList { // implementation omitted} Embedding or Nesting Components[​](https://stenciljs.com/docs/next/component#embedding-or-nesting-components "Direct link to Embedding or Nesting Components") --------------------------------------------------------------------------------------------------------------------------------------------------------------- Components can be composed easily by adding the HTML tag to the JSX code. Since the components are just HTML tags, nothing needs to be imported to use a Stencil component within another Stencil component. Here's an example of using a component within another component: import { Component, Prop, h } from '@stencil/core';@Component({ tag: 'my-embedded-component'})export class MyEmbeddedComponent { @Prop() color: string = 'blue'; render() { return (
My favorite color is {this.color}
); }} import { Component, h } from '@stencil/core';@Component({ tag: 'my-parent-component'})export class MyParentComponent { render() { return (
); }} The `my-parent-component` includes a reference to the `my-embedded-component` in the `render()` function. Contents -------- * [Component Options](https://stenciljs.com/docs/next/component#component-options) * [tag](https://stenciljs.com/docs/next/component#tag) * [assetsDirs](https://stenciljs.com/docs/next/component#assetsdirs) * [formAssociated](https://stenciljs.com/docs/next/component#formassociated) * [scoped](https://stenciljs.com/docs/next/component#scoped) * [shadow](https://stenciljs.com/docs/next/component#shadow) * [styleUrl](https://stenciljs.com/docs/next/component#styleurl) * [styleUrls](https://stenciljs.com/docs/next/component#styleurls) * [styles](https://stenciljs.com/docs/next/component#styles) * [Embedding or Nesting Components](https://stenciljs.com/docs/next/component#embedding-or-nesting-components) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/components/component.md) --- # Integrated Dev Server Config | Stencil [Skip to main content](https://stenciljs.com/docs/next/dev-server#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/dev-server) ** (v4.35). Version: Next On this page Stencil comes with an integrated dev server in order to simplify development. By integrating the build process and the dev server, Stencil is able to drastically improve the development experience without requiring complicated build scripts and configuration. As app builds and re-builds take place, the compiler is able to communicate with the dev server, and vice versa. Hot Module Replacement[​](https://stenciljs.com/docs/next/dev-server#hot-module-replacement "Direct link to Hot Module Replacement") ------------------------------------------------------------------------------------------------------------------------------------- The compiler already provides a watch mode, but coupled with the dev server it's able to go one step farther by reloading only what has changed within the browser. Hot Module Replacement allows the app to keep its state within the browser, while switching out individual components with their updated logic after file saves. Style Replacement[​](https://stenciljs.com/docs/next/dev-server#style-replacement "Direct link to Style Replacement") ---------------------------------------------------------------------------------------------------------------------- Web components can come with their own css, can use shadow dom, and can have individual style tags. Traditionally, live-reload external css links usually does the trick, however, updating components with inline styles within shadow roots has been a challenge. With the integrated dev server, Stencil is able to dynamically update styles for all components, whether they're using shadow dom or not, without requiring a page refresh. Development Errors[​](https://stenciljs.com/docs/next/dev-server#development-errors "Direct link to Development Errors") ------------------------------------------------------------------------------------------------------------------------- When errors happen during development, such as printing an error for invalid syntax, Stencil will not only log the error and the source of the error in the console, but also overlay the app with the error so it's easier to read. Open In Editor[​](https://stenciljs.com/docs/next/dev-server#open-in-editor "Direct link to Open In Editor") ------------------------------------------------------------------------------------------------------------- When a development error is shown and overlays the project within the browser, line numbers pointing to the source text are clickable, which will open the source file directly in your IDE. Dev Server Config[​](https://stenciljs.com/docs/next/dev-server#dev-server-config "Direct link to Dev Server Config") ---------------------------------------------------------------------------------------------------------------------- ### `address`[​](https://stenciljs.com/docs/next/dev-server#address "Direct link to address") **Optional** **Type: `string`** **Default: `0.0.0.0`** IP address used by the dev server. The default is `0.0.0.0`, which points to all IPv4 addresses on the local machine, such as `localhost`. ### `basePath`[​](https://stenciljs.com/docs/next/dev-server#basepath "Direct link to basepath") **Optional** **Type: `string`** **Default: `/`** Base path to be used by the server. Defaults to the root pathname. ### `https`[​](https://stenciljs.com/docs/next/dev-server#https "Direct link to https") **Optional** **Type: `{ key: string; cert: string; } | false`** **Default: `false`** By default the dev server runs over the http protocol. Instead you can run it over https by providing your own SSL certificate and key (see example below). #### Example[​](https://stenciljs.com/docs/next/dev-server#example "Direct link to Example") import { readFileSync } from 'fs';import { Config } from '@stencil/core';export const config: Config = { devServer: { reloadStrategy: 'pageReload', port: 4444, https: { cert: readFileSync('cert.pem', 'utf8'), key: readFileSync('key.pem', 'utf8'), }, },}; ### `initialLoadUrl`[​](https://stenciljs.com/docs/next/dev-server#initialloadurl "Direct link to initialloadurl") **Optional** **Type: `string`** **Default: `/`** The URL the dev server should first open to. ### `logRequests`[​](https://stenciljs.com/docs/next/dev-server#logrequests "Direct link to logrequests") **Optional** **Type: `boolean`** **Default: `false`** Every request to the server will be logged within the terminal. ### `openBrowser`[​](https://stenciljs.com/docs/next/dev-server#openbrowser "Direct link to openbrowser") **Optional** **Type: `boolean`** **Default: `true`** By default, when dev server is started the local dev URL is opened in your default browser. However, to prevent this URL to be opened change this value to `false`. ### `pingRoute`[​](https://stenciljs.com/docs/next/dev-server#pingroute "Direct link to pingroute") **Optional** **Type: `string | null`** **Default: `/ping`** Route to be registered on the dev server that will respond with a 200 OK response once the Stencil build has completed. The Stencil dev server will "spin up" before the build process has completed, which can cause issues with processes that rely on the compiled and served output (like E2E testing). This route provides a way for these processes to know when the build has finished and is ready to be accessed. If set to `null`, no route will be registered. ### `port`[​](https://stenciljs.com/docs/next/dev-server#port "Direct link to port") **Optional** **Type: `number`** **Default: `3333`** Sets the server's port. ### `reloadStrategy`[​](https://stenciljs.com/docs/next/dev-server#reloadstrategy "Direct link to reloadstrategy") **Optional** **Type: `'hmr' | 'pageReload' | null`** **Default: `hmr`** When files are watched and updated, by default the dev server will use `hmr` (Hot Module Replacement) to update the page without a full page refresh. To have the page do a full refresh use `pageReload`. To disable any reloading, use `null`. ### `root`[​](https://stenciljs.com/docs/next/dev-server#root "Direct link to root") **Optional** **Type: `string`** **Default: `www` output directory if exists, project root otherwise** The directory to serve files from. Contents -------- * [Hot Module Replacement](https://stenciljs.com/docs/next/dev-server#hot-module-replacement) * [Style Replacement](https://stenciljs.com/docs/next/dev-server#style-replacement) * [Development Errors](https://stenciljs.com/docs/next/dev-server#development-errors) * [Open In Editor](https://stenciljs.com/docs/next/dev-server#open-in-editor) * [Dev Server Config](https://stenciljs.com/docs/next/dev-server#dev-server-config) * [`address`](https://stenciljs.com/docs/next/dev-server#address) * [`basePath`](https://stenciljs.com/docs/next/dev-server#basepath) * [`https`](https://stenciljs.com/docs/next/dev-server#https) * [`initialLoadUrl`](https://stenciljs.com/docs/next/dev-server#initialloadurl) * [`logRequests`](https://stenciljs.com/docs/next/dev-server#logrequests) * [`openBrowser`](https://stenciljs.com/docs/next/dev-server#openbrowser) * [`pingRoute`](https://stenciljs.com/docs/next/dev-server#pingroute) * [`port`](https://stenciljs.com/docs/next/dev-server#port) * [`reloadStrategy`](https://stenciljs.com/docs/next/dev-server#reloadstrategy) * [`root`](https://stenciljs.com/docs/next/dev-server#root) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/config/dev-server.md) --- # Build Constants | Stencil [Skip to main content](https://stenciljs.com/docs/v2/build-variables#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/build-variables) ** (v4.35). Version: v2 On this page Build Constants in Stencil allow you to run specific code only when Stencil is running in development mode. This code is stripped from your bundles when doing a production build, therefore keeping your bundles as small as possible. ### Using Build Constants[​](https://stenciljs.com/docs/v2/build-variables#using-build-constants "Direct link to Using Build Constants") Lets dive in and look at an example of how to use our build constants: import { Component, Build } from '@stencil/core';@Component({ tag: 'stencil-app', styleUrl: 'stencil-app.scss'})export class StencilApp { componentDidLoad() { if (Build.isDev) { console.log('im in dev mode'); } else { console.log('im running in production'); } if (Build.isBrowser) { console.log('im in the browser'); } else { console.log('im in prerendering (server)'); } }} As you can see from this example, we just need to import `Build` from `@stencil/core` and then we can use the `isDev` constant to detect when we are running in dev mode or production mode. ### Use Cases[​](https://stenciljs.com/docs/v2/build-variables#use-cases "Direct link to Use Cases") Some use cases we have come up with are: * Diagnostics code that runs in dev to make sure logic is working like you would expect * `console.log()`'s that may be useful for debugging in dev mode but that you don't want to ship * Disabling auth checks when in dev mode Contents -------- * [Using Build Constants](https://stenciljs.com/docs/v2/build-variables#using-build-constants) * [Use Cases](https://stenciljs.com/docs/v2/build-variables#use-cases) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v2/build-variables.md) --- # Custom Docs Generation | Stencil [Skip to main content](https://stenciljs.com/docs/next/docs-custom#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/docs-custom) ** (v4.35). Version: Next On this page Stencil exposes an output target titled `docs-custom` where users can access the generated docs json data. This feature can be used to generate custom markdown or to execute other logic on the json data during the build. As with other docs output targets, `strict` mode is supported. To make use of this output target, simply add the following to your Stencil configuration. import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-custom', generator: (docs: JsonDocs) => { // Custom logic goes here } } ]}; Config[​](https://stenciljs.com/docs/next/docs-custom#config "Direct link to Config") -------------------------------------------------------------------------------------- | Property | Description | Default | | --- | --- | --- | | `generator` | A function with the docs json data as argument. | | | `strict` | If set to true, Stencil will output a warning whenever there is missing documentation. | `false` | Custom Docs Data Model ====================== The generated docs JSON data will in the type of `JsonDocs` which consists of main `components` array which consists of components that stencil core found and meta information such as `timestamp` and `compiler` JsonDocs[​](https://stenciljs.com/docs/next/docs-custom#jsondocs "Direct link to JsonDocs") -------------------------------------------------------------------------------------------- | Property | Description | | --- | --- | | `components` | Array with type of `JsonDocsComponent[]` which consists component information | | `timestamp` | `string` with timestamp | | `compiler` | `Object` with `typescriptVersion`, `compiler`, and `version` | JsonDocsComponent[​](https://stenciljs.com/docs/next/docs-custom#jsondocscomponent "Direct link to JsonDocsComponent") ----------------------------------------------------------------------------------------------------------------------- | Property | Description | | --- | --- | | `dirPath` | Component directory path | | `fileName` | File name | | `filePath` | File path | | `readmePath` | Readme file path | | `usagesDir` | Stencil looks in a directory named `usages/` in the same directory as your component to find usage examples. This holds the full path to that directory. | | `encapsulation` | Component `encapsulation` type. Possible values are `shadow`, `scoped`, `none` | | `tag` | Component tag described in `.tsx` file | | `readme` | Component readme file first line content | | `docs` | Description written in top of `@Component` e.g. /\*\* Documentation Example \*/. If no JSDoc is present, default to any manually written text in the component's markdown file. Empty otherwise. | | `docsTags` | Annotations (In the way of JSDoc ) written in `.tsx` file will be collected here | | `overview` | Description written in top of `@Component` e.g. /\*\* Documentation Example \*/ | | `usage` | Array of [usage examples](https://stenciljs.com/docs/next/docs-json#usage)
, written in Markdown files in the `usages/` directory adjacent to the current component. | | `props` | Array of metadata objects for each usage of the [`@Prop` decorator](https://stenciljs.com/docs/next/properties#the-prop-decorator-prop)
on the current component. | | `methods` | Array of metadata objects for each usage of the [`@Method` decorator](https://stenciljs.com/docs/next/methods)
on the current component. | | `events` | Array of metadata objects for each usage of the [`@Event` decorator](https://stenciljs.com/docs/next/events#event-decorator)
on the current component. | | `listeners` | Array of metadata objects for each usage of the [`@Listen` decorator](https://stenciljs.com/docs/next/events#listen-decorator)
on the current component. | | `styles` | Array of objects documenting annotated [CSS variables](https://stenciljs.com/docs/next/docs-json#css-variables)
used in the current component's CSS. | | `slots` | Array of objects documenting [slots](https://stenciljs.com/docs/next/docs-json#slots)
which are tagged with `@slot` in the current component's JSDoc comment. | | `parts` | Array of objects derived from `@part` tags in the current component's JSDoc comment. | | `dependents` | Array of components where current component is used | | `dependencies` | Array of components which is used in current component | | `dependencyGraph` | Describes a tree of components coupling | Contents -------- * [Config](https://stenciljs.com/docs/next/docs-custom#config) * [JsonDocs](https://stenciljs.com/docs/next/docs-custom#jsondocs) * [JsonDocsComponent](https://stenciljs.com/docs/next/docs-custom#jsondocscomponent) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/documentation-generation/docs-custom.md) --- # Content Security Policy Nonces | Stencil [Skip to main content](https://stenciljs.com/docs/next/csp-nonce#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/csp-nonce) ** (v4.35). Version: Next On this page [Content Security Policies (CSPs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) can help protect an application from Cross-Site Scripting (XSS) attacks by adding a security layer to help prevent unauthorized code from running in the browser. An application that is served with a CSP other than 'unsafe-inline' and contains web components without a Shadow DOM will likely run into errors on load. This is often first detected in the browser's console, which reports an error stating that certain styles or scripts violate the effective CSP. To resolve this issue, Stencil supports using [CSP nonces](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) in many of the output targets. caution NOTE: CSPs and some CSP strategies are not supported by certain browsers. For a more detailed list, please see the [CSP browser compatibility table](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#browser_compatibility) . How to Use a Nonce[​](https://stenciljs.com/docs/next/csp-nonce#how-to-use-a-nonce "Direct link to How to Use a Nonce") ------------------------------------------------------------------------------------------------------------------------ The actual generation of the nonce value and enforcement of the correct CSP are not the responsibility of Stencil. Instead, the server of the application will need to generate the nonce value for each page view, construct the CSP, and then correctly handle passing the generated nonce to Stencil based on which output target is being consumed. There are many resources available that walk through setting up a CSP and using the nonce behavior. [This](https://towardsdatascience.com/content-security-policy-how-to-create-an-iron-clad-nonce-based-csp3-policy-with-webpack-and-nginx-ce5a4605db90) article walks through the process using Nginx and Webpack. Obviously, these resources don't account for the Stencil specifics, but any specifics will be called out in this guide. Per the [MDN Guide on nonces](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#generating_values) , a nonce should be "a random base64-encoded string of at least 128 bits of data from a cryptographically secure random number generator". ### Output Targets[​](https://stenciljs.com/docs/next/csp-nonce#output-targets "Direct link to Output Targets") Using nonces may differ slightly between output targets, so please be sure to use the correct pattern based on the context in which your Stencil components are consumed. #### Dist[​](https://stenciljs.com/docs/next/csp-nonce#dist "Direct link to Dist") Consuming a `nonce` in the `dist` output target is easy using the provided `setNonce` helper function. This function is exported from the index file of the output target's designated output directory. This function simply accepts the `nonce` string value that you want set for every `style` and `script` tag. This is an example of consuming the `dist` output in an Angular app's entrypoint: // main.tsimport { defineCustomElements, setNonce } from 'my-lib/loader';// Will set the `nonce` attribute for all scripts/style tags// i.e. will run styleTag.setAttribute('nonce', 'r4nd0m')// Obviously, you should use the nonce generated by your serversetNonce('r4nd0m');// Generic Angular bootstrappingplatformBrowserDynamic() .bootstrapModule(AppModule) .catch(err => console.log(err));defineCustomElements(); #### Custom Elements[​](https://stenciljs.com/docs/next/csp-nonce#custom-elements "Direct link to Custom Elements") Consuming a `nonce` in the `dist-custom-elements` output target is easy using the provided `setNonce` helper function. This function is exported from the index file of the output target's designated output directory. This function simply accepts the `nonce` string value that you want set for every `style` and `script` tag. This is an example of consuming the `dist-custom-elements` output in an Angular app's entrypoint: // main.tsimport { defineCustomElements, setNonce } from 'my-lib/dist/components';// Assume `customElementsExportBehavior: 'auto-define-custom-elements'` is setimport 'my-lib/dist/components/my-component';// Will set the `nonce` attribute for all scripts/style tags// i.e. will run styleTag.setAttribute('nonce', 'r4nd0m')// Obviously, you should use the nonce generated by your serversetNonce('r4nd0m');// Generic Angular bootstrappingplatformBrowserDynamic() .bootstrapModule(AppModule) .catch(err => console.log(err)); #### WWW[​](https://stenciljs.com/docs/next/csp-nonce#www "Direct link to WWW") Unfortunately, setting `nonce` attributes gets a bit trickier when it comes to [SSR and SSG](https://stenciljs.com/docs/next/static-site-generation) . As a `nonce` needs to be unique per page view, it cannot be defined/set at build time. So, this responsibility now falls on the [hydrate app](https://stenciljs.com/docs/next/hydrate-app) 's execution of runtime code. **SSR** Since there is not an easy way (or any way) of exposing and executing helper functions to manipulate the outcome of the runtime code, Stencil has fallback behavior for pulling the `nonce` off of a `meta` tag in the DOM head. So, for SSR, your app can simply inject a `meta` element into the header _on each page request_. Yes, this does involve some manual configuration for the code served by your server. To work correctly, the created tag must be generated as follows: This isn't a security risk because, for an attacker to execute a script to pull the nonce from the meta tag, they would have needed to know the nonce _ahead_ of the script's execution. **SSG** Stencil cannot support CSP nonces with SSG. Because all of the code is generated during [pre-rendering](https://stenciljs.com/docs/next/static-site-generation#how-static-site-generation-and-prerendering-works) , Stencil doesn't generate the `style` or `script` tags at runtime. If an application wants to leverage nonces in SSG, they can build a mechanism to scrape the pre-rendered code and apply the attribute server-side before it is served to the client. Contents -------- * [How to Use a Nonce](https://stenciljs.com/docs/next/csp-nonce#how-to-use-a-nonce) * [Output Targets](https://stenciljs.com/docs/next/csp-nonce#output-targets) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/guides/csp-nonce.md) --- # VS Code Documentation | Stencil [Skip to main content](https://stenciljs.com/docs/next/docs-vscode#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/docs-vscode) ** (v4.35). Version: Next On this page One of the core features of web components is the ability to create [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) , which allow developers to reuse custom functionality defined in their components. When Stencil compiles a project, it generates a custom element for each component in the project. Each of these [custom elements has an associated `tag` name](https://stenciljs.com/docs/next/component#component-options) that allows the custom element to be used in HTML files. By default, integrated development environments (IDEs) like VS Code are not aware of a project's custom elements when authoring HTML. In order to enable more intelligent features in VS Code, such as auto-completion, hover tooltips, etc., developers need to inform it of their project's custom elements. The `docs-vscode` output target tells Stencil to generate a JSON file containing this information. This is an opt-in feature and will save a JSON file containing [custom data](https://github.com/microsoft/vscode-custom-data) in a directory specified by the output target. Once the feature is enabled and VS Code is informed of the JSON file's location, HTML files can gain code editing features similar to TSX files. Enabling[​](https://stenciljs.com/docs/next/docs-vscode#enabling "Direct link to Enabling") -------------------------------------------------------------------------------------------- To generate custom element information for VS Code, add the `docs-vscode` output target to your `stencil.config.ts`: import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-vscode', file: 'vscode-data.json', } ]}; where `file` is the name & location of the file to be generated. By default, Stencil assumes that the file will be generated in the project's root directory. To generate the JSON file, have Stencil build your project. Configuring VS Code[​](https://stenciljs.com/docs/next/docs-vscode#configuring-vs-code "Direct link to Configuring VS Code") ----------------------------------------------------------------------------------------------------------------------------- Once the `docs-vscode` output target has been enabled and the JSON file generated, VS Code needs to be informed of it. Recent versions of VS Code have a settings option named `html.customData`, which resolves to a list of JSON files to use when augmenting the default list of HTML elements. Add the path to the generated JSON file for your project's types to be added: { "html.customData": [ "./vscode-data.json" ]} Contents -------- * [Enabling](https://stenciljs.com/docs/next/docs-vscode#enabling) * [Configuring VS Code](https://stenciljs.com/docs/next/docs-vscode#configuring-vs-code) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/documentation-generation/docs-vscode.md) --- # Config | Stencil [Skip to main content](https://stenciljs.com/docs/next/config#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/config) ** (v4.35). Version: Next On this page In most cases, the `stencil.config.ts` file does not require any customization since Stencil comes with great default values out-of-the-box. In general, it's preferred to keep the config as minimal as possible. In fact, you could even delete the `stencil.config.ts` file entirely and an app would compile just fine. But at the same time, the compiler can be configured at the lowest levels using this config. Below are the many _optional_ config properties. Example `stencil.config.ts`: import { Config } from '@stencil/core';export const config: Config = { namespace: 'MyApp', srcDir: 'src'}; buildDist[​](https://stenciljs.com/docs/next/config#builddist "Direct link to buildDist") ------------------------------------------------------------------------------------------ _default: true (prod), false (dev)_ Sets whether or not Stencil will execute output targets and write output to `dist/` when `stencil build` is called. Defaults to `false` when building for development and `true` when building for production. If set to `true` then Stencil will always build all output targets, regardless of whether the build is in dev or prod mode or using watch mode. buildDist: true buildEs5[​](https://stenciljs.com/docs/next/config#buildes5 "Direct link to buildEs5") --------------------------------------------------------------------------------------- Sets if the ES5 build should be generated or not. It defaults to `false`. Setting `buildEs5` to `true` will also create ES5 builds for both dev and prod modes. Setting `buildEs5` to `prod` will only build ES5 in prod mode. buildEs5: boolean | 'prod' bundles[​](https://stenciljs.com/docs/next/config#bundles "Direct link to bundles") ------------------------------------------------------------------------------------ By default, Stencil will statically analyze the application and generate a component graph of how all the components are interconnected. From the component graph it is able to best decide how components should be grouped depending on their usage with one another within the app. By doing so it's able to bundle components together in order to reduce network requests. However, bundles can be manually generated using the `bundles` config. The `bundles` config is an array of objects that represent how components are grouped together in lazy-loaded bundles. This config is rarely needed as Stencil handles this automatically behind the scenes. bundles: [ { components: ['ion-button'] }, { components: ['ion-card', 'ion-card-header'] }] cacheDir[​](https://stenciljs.com/docs/next/config#cachedir "Direct link to cacheDir") --------------------------------------------------------------------------------------- _default: '.stencil'_ The directory where sub-directories will be created for caching when [`enableCache`](https://stenciljs.com/docs/next/config#enablecache) is set `true` or if using [Stencil's Screenshot Connector](https://stenciljs.com/docs/next/screenshot-connector) . A Stencil config like the following: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { ..., enableCache: true, cacheDir: '.cache', testing: { screenshotConnector: 'connector.js' }} Will result in the following file structure: stencil-project-root└── .cache ├── .build <-- Where build related file caching is written | └── screenshot-cache.json <-- Where screenshot caching is written devServer[​](https://stenciljs.com/docs/next/config#devserver "Direct link to devServer") ------------------------------------------------------------------------------------------ Please see the [Dev-Server docs](https://stenciljs.com/docs/next/dev-server) . docs[​](https://stenciljs.com/docs/next/config#docs "Direct link to docs") --------------------------------------------------------------------------- Please see the [docs config](https://stenciljs.com/docs/next/docs-config) . enableCache[​](https://stenciljs.com/docs/next/config#enablecache "Direct link to enableCache") ------------------------------------------------------------------------------------------------ _default: `true`_ Stencil will cache build results in order to speed up rebuilds. To disable this feature, set `enableCache` to `false`. enableCache: true extras[​](https://stenciljs.com/docs/next/config#extras "Direct link to extras") --------------------------------------------------------------------------------- Please see the [Extras docs](https://stenciljs.com/docs/next/config-extras) . env[​](https://stenciljs.com/docs/next/config#env "Direct link to env") ------------------------------------------------------------------------ _default: `{}`_ An object that can hold environment variables for your components to import and use. These variables can hold data objects depending on the environment you compile the components for. For example, let's say we want to provide an URL to our API based on a specific environment, we could provide it as such: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { ..., env: { API_BASE_URL: process.env.API_BASE_URL }} Now when you build your components with this environment variable set, you can import it in your component as follows: import { Component, h, Env, Host } from '@stencil/core';@Component({ tag: 'api-component',})export class APIComponent { async connectedCallback () { const res = await fetch(Env.API_BASE_URL) // ... }} generateExportMaps[​](https://stenciljs.com/docs/next/config#generateexportmaps "Direct link to generateExportMaps") --------------------------------------------------------------------------------------------------------------------- _default: `false`_ Stencil will generate [export maps](https://nodejs.org/api/packages.html#packages_exports) that correspond with various output target outputs. This includes the root entry point based on the [primary output target](https://stenciljs.com/docs/next/output-targets#primary-package-output-target-validation) (or first eligible output target if not specified), the entry point for the lazy-loader (if using the `dist` output target), and entry points for each component (if using `dist-custom-elements`). globalScript[​](https://stenciljs.com/docs/next/config#globalscript "Direct link to globalScript") --------------------------------------------------------------------------------------------------- The global script config option takes a file path as a string. The global script runs once before your library/app loads, so you can do things like setting up a connection to an external service or configuring a library you are using. The code to be executed should be placed within a default function that is exported by the global script. Ensure all of the code in the global script is wrapped in the function that is exported: export default function() { // or export default async function() initServerConnection();} note The exported function can also be `async` but be aware that this can have implications on the performance of your application as all rendering operations will be deferred until after the global script finishes. Imported methods from Stencil, such as `setMode`, `BUILD` and others, can only be accessed within the function exported by the script. They will not be available in the global scope outside of this function. import { setMode, BUILD } from '@stencil/core';// ❌ This won't work as Stencil primitives are not initialized at this point// console.log('Build mode:', BUILD.isDev);export default function() { // ✅ This works - Stencil methods are available within the exported function if (BUILD.isDev) { console.log('Development mode detected'); setMode((elm) => elm.getAttribute('mode') || 'dev'); } else { console.log('Production mode'); setMode((elm) => elm.getAttribute('mode') || 'prod'); }} globalStyle[​](https://stenciljs.com/docs/next/config#globalstyle "Direct link to globalStyle") ------------------------------------------------------------------------------------------------ Stencil is traditionally used to compile many components into an app, and each component comes with its own compartmentalized styles. However, it's still common to have styles which should be "global" across all components and the website. A global CSS file is often useful to set [CSS Variables](https://stenciljs.com/docs/next/styling) . Additionally, the `globalStyle` config can be used to precompile styles with Sass, PostCSS, etc. Below is an example folder structure containing a webapp's global css file, named `app.css`. src/ components/ global/ app.css The global style config takes a file path as a string. The output from this build will go to the `buildDir`. In this example it would be saved to `www/build/app.css`. Additionally, these global styles are automatically applied to all components with shadow roots via constructable stylesheets, allowing you to style shadow DOM components directly. globalStyle: 'src/global/app.css' Check out the [styling docs](https://stenciljs.com/docs/next/styling#global-styles) of how to use global styles in your app. hashedFileNameLength[​](https://stenciljs.com/docs/next/config#hashedfilenamelength "Direct link to hashedFileNameLength") --------------------------------------------------------------------------------------------------------------------------- _default: `8`_ When the `hashFileNames` config is set to `true`, and it is a production build, the `hashedFileNameLength` config is used to determine how many characters the file name's hash should be. hashedFileNameLength: 8 hashFileNames[​](https://stenciljs.com/docs/next/config#hashfilenames "Direct link to hashFileNames") ------------------------------------------------------------------------------------------------------ _default: `true`_ During production builds, the content of each generated file is hashed to represent the content, and the hashed value is used as the filename. If the content isn't updated between builds, then it receives the same filename. When the content is updated, then the filename is different. By doing this, deployed apps can "forever-cache" the build directory and take full advantage of content delivery networks (CDNs) and heavily caching files for faster apps. hashFileNames: true hydratedFlag[​](https://stenciljs.com/docs/next/config#hydratedflag "Direct link to hydratedFlag") --------------------------------------------------------------------------------------------------- When using the [lazy build](https://stenciljs.com/docs/distribution) Stencil has support for automatically applying a class or attribute to a component and all of its child components when they have finished hydrating. This can be used to prevent a [flash of unstyled content (FOUC)](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) , a typically-undesired 'flicker' of unstyled HTML that might otherwise occur during component rendering while various components are asynchronously downloaded and rendered. By default, Stencil will add the `hydrated` CSS class to elements to indicate hydration. The `hydratedFlag` config field allows this behavior to be customized, by changing the name of the applied CSS class, setting it to use an attribute to indicate hydration, or changing which type of CSS properties and values are assigned before and after hydrating. This config can also be used to turn off this behavior by setting it to `null`. If a Stencil configuration does not supply a value for `hydratedFlag` then Stencil will automatically generate the following default configuration: const defaultHydratedFlag: HydratedFlag = { hydratedValue: 'inherit', initialValue: 'hidden', name: 'hydrated', property: 'visibility', selector: 'class',}; If `hydratedFlag` is explicitly set to `null`, Stencil will not set a default configuration and the behavior of marking hydration with a class or attribute will be disabled. hydratedFlag: null | { name?: string, selector?: 'class' | 'attribute', property?: string, initialValue?: string, hydratedValue?: string} The supported options are as follows: ### name[​](https://stenciljs.com/docs/next/config#name "Direct link to name") _default: 'hydrated'_ The name which Stencil will use for the attribute or class that it sets on elements to indicate that they are hydrated. name: string ### selector[​](https://stenciljs.com/docs/next/config#selector "Direct link to selector") _default: 'class'_ The way that Stencil will indicate that a component has been hydrated. When `'class'`, Stencil will set the `name` option on the element as a class, and when `'attribute'`, Stencil will similarly set the `name` option as an attribute. selector: 'class' | 'attribute' ### property[​](https://stenciljs.com/docs/next/config#property "Direct link to property") _default: 'visibility'_ The CSS property used to show and hide components. This defaults to the CSS `visibility` property. Other possible CSS properties might include `display` with the `initialValue` setting as `none`, or `opacity` with the `initialValue` as `0`. Defaults to `visibility`. property: string ### initialValue[​](https://stenciljs.com/docs/next/config#initialvalue "Direct link to initialValue") _default: 'hidden'_ This is the value which should be set for the property specified by `property` on all components before hydration. initialValue: string ### hydratedValue[​](https://stenciljs.com/docs/next/config#hydratedvalue "Direct link to hydratedValue") _default: 'inherit'_ This is the value which should be set for the property specified by `property` on all components once they've completed hydration. hydratedValue: string invisiblePrehydration[​](https://stenciljs.com/docs/next/config#invisibleprehydration "Direct link to invisiblePrehydration") ------------------------------------------------------------------------------------------------------------------------------ _default: `true`_ When `true`, `invisiblePrehydration` will visually hide components before they are hydrated by adding an automatically injected style tag to the document's head. Setting `invisiblePrehydration` to `false` will not inject the style tag into the head, allowing you to style your web components pre-hydration. note Setting `invisiblePrehydration` to `false` will cause everything to be visible when your page is loaded, causing a more prominent Flash of Unstyled Content (FOUC). However, you can style your web component's fallback content to your preference. invisiblePrehydration: true minifyCss[​](https://stenciljs.com/docs/next/config#minifycss "Direct link to minifyCss") ------------------------------------------------------------------------------------------ _default: `true` in production_ When `true`, the browser CSS file will be minified. minifyJs[​](https://stenciljs.com/docs/next/config#minifyjs "Direct link to minifyJs") --------------------------------------------------------------------------------------- _default: `true` in production_ When `true`, the browser JS files will be minified. Stencil uses [Terser](https://terser.org/) under-the-hood for file minification. namespace[​](https://stenciljs.com/docs/next/config#namespace "Direct link to namespace") ------------------------------------------------------------------------------------------ _default: `App`_ The `namespace` config is a `string` representing a namespace for the app. For apps that are not meant to be a library of reusable components, the default of `App` is just fine. However, if the app is meant to be consumed as a third-party library, such as `Ionic`, a unique namespace is required. namespace: "Ionic" outputTargets[​](https://stenciljs.com/docs/next/config#outputtargets "Direct link to outputTargets") ------------------------------------------------------------------------------------------------------ Please see the [Output Target docs](https://stenciljs.com/docs/next/output-targets) . plugins[​](https://stenciljs.com/docs/next/config#plugins "Direct link to plugins") ------------------------------------------------------------------------------------ Please see the [Plugin docs](https://stenciljs.com/docs/next/plugins) . preamble[​](https://stenciljs.com/docs/next/config#preamble "Direct link to preamble") --------------------------------------------------------------------------------------- _default: `undefined`_ Used to help to persist a banner or add relevant information about the resulting build, the `preamble` configuration field is a `string` that will be converted into a pinned comment and placed at the top of all emitted JavaScript files, with the exception of any emitted polyfills. Escaped newlines may be placed in the provided value for this field and will be honored by Stencil. Example: preamble: 'Built with Stencil\nCopyright (c) SomeCompanyInc.' Will generate the following comment: /*! * Built with Stencil * Copyright (c) SomeCompanyInc. */ sourceMap[​](https://stenciljs.com/docs/next/config#sourcemap "Direct link to sourceMap") ------------------------------------------------------------------------------------------ _default: `true`_ When omitted or set to `true`, sourcemaps will be generated for a project. When set to `false`, sourcemaps will not be generated. sourceMap: true | false Sourcemaps create a translation between Stencil components that are written in TypeScript/JSX and the resulting JavaScript that is output by Stencil. Enabling source maps in your project allows for an improved debugging experience for Stencil components. For example, they allow external tools (such as an Integrated Development Environment) to add breakpoints directly in the original source code, which allows you to 'step through' your code line-by-line, to inspect the values held in variables, to observe logic flow, and more. Please note: Stencil will always attempt to minify a component's source code as much as possible during compilation. When `sourceMap` is enabled, it is possible that a slightly different minified result will be produced by Stencil when compared to the minified result produced when `sourceMap` is not enabled. Developers are responsible for determining whether or not they choose to serve sourcemaps in each environment their components are served and implementing their decision accordingly. srcDir[​](https://stenciljs.com/docs/next/config#srcdir "Direct link to srcDir") --------------------------------------------------------------------------------- _default: `src`_ The `srcDir` config specifies the directory which should contain the source typescript files for each component. The standard for Stencil apps is to use `src`, which is the default. srcDir: 'src' taskQueue[​](https://stenciljs.com/docs/next/config#taskqueue "Direct link to taskQueue") ------------------------------------------------------------------------------------------ _default: `async`_ Sets the task queue used by stencil's runtime. The task queue schedules DOM read and writes across the frames to efficiently render and reduce layout thrashing. By default, the `async` is used. It's recommended to also try each setting to decide which works best for your use-case. In all cases, if your app has many CPU intensive tasks causing the main thread to periodically lock-up, it's always recommended to try [Web Workers](https://stenciljs.com/docs/next/web-workers) for those tasks. * `congestionAsync`: DOM reads and writes are scheduled in the next frame to prevent layout thrashing. When the app is heavily tasked and the queue becomes congested it will then split the work across multiple frames to prevent blocking the main thread. However, it can also introduce unnecessary reflows in some cases, especially during startup. `congestionAsync` is ideal for apps running animations while also simultaneously executing intensive tasks which may lock-up the main thread. * `async`: DOM read and writes are scheduled in the next frame to prevent layout thrashing. During intensive CPU tasks it will not reschedule rendering to happen in the next frame. `async` is ideal for most apps, and if the app has many intensive tasks causing the main thread to lock-up, it's recommended to try [Web Workers](https://stenciljs.com/docs/next/web-workers) rather than the congestion async queue. * `immediate`: Makes writeTask() and readTask() callbacks to be executed synchronously. Tasks are not scheduled to run in the next frame, but do note there is at least one microtask. The `immediate` setting is ideal for apps that do not provide long-running and smooth animations. Like the async setting, if the app has intensive tasks causing the main thread to lock-up, it's recommended to try [Web Workers](https://stenciljs.com/docs/next/web-workers) . taskQueue: 'async' testing[​](https://stenciljs.com/docs/next/config#testing "Direct link to testing") ------------------------------------------------------------------------------------ Please see the [testing config docs](https://stenciljs.com/docs/next/testing-config) . transformAliasedImportPaths[​](https://stenciljs.com/docs/next/config#transformaliasedimportpaths "Direct link to transformAliasedImportPaths") ------------------------------------------------------------------------------------------------------------------------------------------------ _default: `true`_ This sets whether or not Stencil should transform [path aliases](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping) set in a project's `tsconfig.json` from the assigned module aliases to resolved relative paths. This will not transform external imports (like `@stencil/core`) or relative imports (like `'../utils'`). This option applies globally and will affect all code processed by Stencil, including `.d.ts` files and spec tests. An example of path transformation could look something like the following. First, a set of `paths` aliases in `tsconfig.json`: tsconfig.json { "compilerOptions": { "paths": { "@utils": [ "../path/to/utils" ] } }} Then with the following input: src/my-module.ts import { utilFunc, UtilInterface } from '@utils'export function util(arg: UtilInterface) { utilFunc(arg)} Stencil will produce the following output: dist/my-module.js import { utilFunc } from '../path/to/utils';export function util(arg) { utilFunc(arg);} dist/my-module.d.ts import { UtilInterface } from '../path/to/utils';export declare function util(arg: UtilInterface): void; validatePrimaryPackageOutputTarget[​](https://stenciljs.com/docs/next/config#validateprimarypackageoutputtarget "Direct link to validatePrimaryPackageOutputTarget") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- _default: `false`_ When `true`, validation for common `package.json` fields will occur based on setting an output target's `isPrimaryPackageOutputTarget` flag. For more information on package validation, please see the [output target docs](https://stenciljs.com/docs/next/output-targets#primary-package-output-target-validation) . rollupConfig[​](https://stenciljs.com/docs/next/config#rollupconfig "Direct link to rollupConfig") --------------------------------------------------------------------------------------------------- Passes custom configuration down to rollup itself. The following options can be overwritten: * `inputOptions`: [`context`](https://rollupjs.org/configuration-options/#context) , [`external`](https://rollupjs.org/configuration-options/#external) , [`moduleContext`](https://rollupjs.org/configuration-options/#modulecontext) [`treeshake`](https://rollupjs.org/configuration-options/#treeshake) * `outputOptions`: [`globals`](https://rollupjs.org/configuration-options/#output-globals) _default: `{}`_ watchIgnoredRegex[​](https://stenciljs.com/docs/next/config#watchignoredregex "Direct link to watchIgnoredRegex") ------------------------------------------------------------------------------------------------------------------ _default: `[]`_ _type: `RegExp | RegExp[]`_ A regular expression (or array of regular expressions) that can be used to omit files from triggering a rebuild in watch mode. During compile-time, each file in the Stencil project will be tested against each regular expression to determine if changes to the file (or directory) should trigger a project rebuild. note If you want to ignore TS files such as `.ts`/`.js` or `.tsx`/`.jsx` extensions, these files will also need to be specified in your project's tsconfig's [`watchOptions`](https://www.typescriptlang.org/docs/handbook/configuring-watch.html#configuring-file-watching-using-a-tsconfigjson) _in addition_ to the `watchIgnoredRegex` option. For instance, if we wanted to ignore the `my-component.tsx` file, we'd specify: tsconfig.json { ..., "watchOptions": { "excludeFiles": ["src/components/my-component/my-component.tsx"] }} Contents -------- * [buildDist](https://stenciljs.com/docs/next/config#builddist) * [buildEs5](https://stenciljs.com/docs/next/config#buildes5) * [bundles](https://stenciljs.com/docs/next/config#bundles) * [cacheDir](https://stenciljs.com/docs/next/config#cachedir) * [devServer](https://stenciljs.com/docs/next/config#devserver) * [docs](https://stenciljs.com/docs/next/config#docs) * [enableCache](https://stenciljs.com/docs/next/config#enablecache) * [extras](https://stenciljs.com/docs/next/config#extras) * [env](https://stenciljs.com/docs/next/config#env) * [generateExportMaps](https://stenciljs.com/docs/next/config#generateexportmaps) * [globalScript](https://stenciljs.com/docs/next/config#globalscript) * [globalStyle](https://stenciljs.com/docs/next/config#globalstyle) * [hashedFileNameLength](https://stenciljs.com/docs/next/config#hashedfilenamelength) * [hashFileNames](https://stenciljs.com/docs/next/config#hashfilenames) * [hydratedFlag](https://stenciljs.com/docs/next/config#hydratedflag) * [name](https://stenciljs.com/docs/next/config#name) * [selector](https://stenciljs.com/docs/next/config#selector) * [property](https://stenciljs.com/docs/next/config#property) * [initialValue](https://stenciljs.com/docs/next/config#initialvalue) * [hydratedValue](https://stenciljs.com/docs/next/config#hydratedvalue) * [invisiblePrehydration](https://stenciljs.com/docs/next/config#invisibleprehydration) * [minifyCss](https://stenciljs.com/docs/next/config#minifycss) * [minifyJs](https://stenciljs.com/docs/next/config#minifyjs) * [namespace](https://stenciljs.com/docs/next/config#namespace) * [outputTargets](https://stenciljs.com/docs/next/config#outputtargets) * [plugins](https://stenciljs.com/docs/next/config#plugins) * [preamble](https://stenciljs.com/docs/next/config#preamble) * [sourceMap](https://stenciljs.com/docs/next/config#sourcemap) * [srcDir](https://stenciljs.com/docs/next/config#srcdir) * [taskQueue](https://stenciljs.com/docs/next/config#taskqueue) * [testing](https://stenciljs.com/docs/next/config#testing) * [transformAliasedImportPaths](https://stenciljs.com/docs/next/config#transformaliasedimportpaths) * [validatePrimaryPackageOutputTarget](https://stenciljs.com/docs/next/config#validateprimarypackageoutputtarget) * [rollupConfig](https://stenciljs.com/docs/next/config#rollupconfig) * [watchIgnoredRegex](https://stenciljs.com/docs/next/config#watchignoredregex) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/config/01-overview.md) --- # Design Systems | Stencil [Skip to main content](https://stenciljs.com/docs/next/design-systems#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/design-systems) ** (v4.35). Version: Next On this page What is a Design System?[​](https://stenciljs.com/docs/next/design-systems#what-is-a-design-system "Direct link to What is a Design System?") ---------------------------------------------------------------------------------------------------------------------------------------------- A Design System consists of UI components and a clearly defined visual style, released as both code implementations and design artifacts. When adopted by all product teams, a more cohesive customer experience emerges. There are several aspects that Design Systems consist of: ### Components[​](https://stenciljs.com/docs/next/design-systems#components "Direct link to Components") A component is a standalone UI element designed to be reusable across many projects. Its goal is to do one thing well, while remaining abstract enough to allow for a variety of use cases. Developers can use them as building blocks to build new user experiences. One of the key benefits of reusable components is that developers don't have to worry about the core design and functionality of each component every time they use them. Examples include buttons, links, forms, input fields, and modals. ### Patterns[​](https://stenciljs.com/docs/next/design-systems#patterns "Direct link to Patterns") A pattern is an opinionated use of components. Often, multiple components are combined in order to create a standardized user experience (UX). As a result, they improve both the user and developer experience. After implementing patterns, users will understand the application better and accomplish their tasks faster. When the development team understands the proper way to use components together, software applications become easier to use. Examples include saving data to the system, capturing data from forms, and filtering and analyzing data. ### Visual Language[​](https://stenciljs.com/docs/next/design-systems#visual-language "Direct link to Visual Language") A cohesive company brand strengthens its value in the minds of the customer. In the context of design systems, this means defining various aspects of the visual style, including colors, typography, and icons. Defining primary, secondary, and tertiary colors helps an application stand out and is more user-friendly. The right typography ensures users are not distracted while using an app. Finally, icons increase engagement in a product and make it “pop” visually. ### Design Artifacts and Code Implementations[​](https://stenciljs.com/docs/next/design-systems#design-artifacts-and-code-implementations "Direct link to Design Artifacts and Code Implementations") By leveraging the components, patterns, and visual language of the design system, designers can create design artifacts representing UI workflows. Developers refer to the artifacts as guidance for implementing the design with code. The Value of Design Systems[​](https://stenciljs.com/docs/next/design-systems#the-value-of-design-systems "Direct link to The Value of Design Systems") -------------------------------------------------------------------------------------------------------------------------------------------------------- With a design system in place, its true value is revealed. The entire product development team is freed up to focus on what matters most: solving customer problems and delivering value. Additionally, the avoidance of having teams working in parallel, recreating the same UI elements over and over, has a real-world project impact in terms of reduced time to market and increased cost savings. Design systems allow project teams to work better together. Designers define a centralized “source of truth” for software application best practices which can be referenced by anyone in a product organization. Developers no longer need to spend time rethinking how to build common app scenarios, such as application search or data table grids. When the business inevitably makes changes to the design system, they can easily be applied to all projects. The end result is a better product for your users. Using Stencil to Build a Design System[​](https://stenciljs.com/docs/next/design-systems#using-stencil-to-build-a-design-system "Direct link to Using Stencil to Build a Design System") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- There’s a lot that goes into creating amazing UI components. Performance, accessibility, cross-platform capabilities, and user experience (not only of the UI component itself but how it fits into the entire design system) all must be considered. These aspects take real effort to do well. Enter Stencil, a robust and highly extensible tool for building components and patterns, the building blocks of a design system. With its intentionally minimalistic tooling and API footprint, it’s simple to incorporate into your existing development workflows. It brings substantial performance out of the box by leveraging a tiny runtime. Most importantly, all UI components built with Stencil are based 100% on open web standards. ### The Importance of Open Web Standards[​](https://stenciljs.com/docs/next/design-systems#the-importance-of-open-web-standards "Direct link to The Importance of Open Web Standards") By using the web components standard, supported in all modern browsers, Stencil-built UI components offer many distinct advantages for use in a design system, namely: * They work on any platform or device * They work with any front-end framework, so they can easily be used across teams and projects using different tech stacks * They facilitate the creation of one company-wide code implementation instead of one per framework or platform Learn more about why web components are ideal for design systems in [this blog post](https://blog.ionicframework.com/5-reasons-web-components-are-perfect-for-design-systems/) . ### How to Get Started[​](https://stenciljs.com/docs/next/design-systems#how-to-get-started "Direct link to How to Get Started") Stencil’s out-the-box features will help you build your own library of universal UI components that will work across platforms, devices, and front-end frameworks. Review the documentation on this site to get started. Contents -------- * [What is a Design System?](https://stenciljs.com/docs/next/design-systems#what-is-a-design-system) * [Components](https://stenciljs.com/docs/next/design-systems#components) * [Patterns](https://stenciljs.com/docs/next/design-systems#patterns) * [Visual Language](https://stenciljs.com/docs/next/design-systems#visual-language) * [Design Artifacts and Code Implementations](https://stenciljs.com/docs/next/design-systems#design-artifacts-and-code-implementations) * [The Value of Design Systems](https://stenciljs.com/docs/next/design-systems#the-value-of-design-systems) * [Using Stencil to Build a Design System](https://stenciljs.com/docs/next/design-systems#using-stencil-to-build-a-design-system) * [The Importance of Open Web Standards](https://stenciljs.com/docs/next/design-systems#the-importance-of-open-web-standards) * [How to Get Started](https://stenciljs.com/docs/next/design-systems#how-to-get-started) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/guides/design-systems.md) --- # Ember Integration with Stencil | Stencil [Skip to main content](https://stenciljs.com/docs/next/ember#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/ember) ** (v4.35). Version: Next On this page For Monorepos (recommended)[​](https://stenciljs.com/docs/next/ember#for-monorepos-recommended "Direct link to For Monorepos (recommended)") --------------------------------------------------------------------------------------------------------------------------------------------- It's recommended to use the [getting started](https://stenciljs.com/docs/getting-started) docs for creating a Stencil project using the native Stencil tooling. This way, in your Ember project, you don't need to configure anything extra, and you can use Stencil components natively. For example, if using the [Ionic Framework](https://ionicframework.com/) in your Ember project: 1. Add the Ionic Framework to your app: * npm * Yarn * pnpm npm install @ionic/core yarn add @ionic/core pnpm add @ionic/core 2. Install the components from the library: app/app.js import '@ionic/core'; // installs all the components from Ionic Framework 3. Use the components anywhere: app/components/example.gjs 4. You can hook up events / state (controlled component pattern): app/components/example-with-state.gjs import { on } from '@ember/modifier';import Component from '@glimmer/component';import { tracked } from '@glimmer/tracking';export default class Demo extends Component { @tracked isOn = true; toggle = () => this.isOn = !this.isOn;} [Live Demo](https://limber.glimdown.com/edit?c=MQAgqgzglgdg5iAygFwKYwMZQDYliAUQFsAjVAJwChKB9AQRhpAEMYIB3CkZAe24AsoEEAG0IyZhgDWPAG4UAZth7sQARwCuqcVB4wAuiLUBGfSAXkeREAAMAAgBkeABx42AdNSOmAXCH7IyM4QPgD0oeKSMvLkSiruGFahmtrIumyhAOwAbDkALAAMAMwArKGopBQAtCVVxlXsUMj8VRVk5FUY2FBV4uhY2FWsACZVzVDko87M5MgAnp1WrjDoyBBVMDzIDTzkUrBw1JQAPACEVVUglPjjwqjDTbsA5MIAREQzUsMqMCBEPMNUK8ADRXTggDCsEDdeStAAeqAwGjQEIBqBAJDmLGGD3gIFeMKB3D4zXRcAAVsJEoCFP1UJQLgA%2Bag2VkU4SE65EVyzEAAbxAehAAF9zJZrE87G0KKF-g8FFAKE8ANxcnnIEAAYSWelWYqsIElcG6RCIMsS3N1MGQKrVuw1AuQ5Ci9xF%2BoldmNUFNMqdUQOtsoXWYEGEABEKnxUHC0DBhsJtZaVtb%2BZQQCBjmhudhmGhmen00IAPIwPx8vm3dzFmDC4VpgvHEjkfMN9JjHhwY3ojD8RFSe4AXle5cr1drr35fKFr3Smv4rDgRMrvE72FQtcZx1CbZXXZb6cbzcP%2B4zJGRvF%2B5aFTy6UGkTwEQncu7XG%2BjaHIMGYuB7C9QW7PQI9BbLcs2cHM82odM7D9aRXWrEAB24cgtFVesX3RJCAAoAEpEMZR8ICrCAS0QkBTlHEiYFVdNKDrTMKnA3NUBAiAMHIKBnA1CByAwIcAiCEJwgwYYYHcSlARhch3BWZBQhgZwiFCOx0jvUJEnIVBQgecRtz0O9xIgV5NwidjOOQZl62OCN-hAUJmVAxiIJYyhWRsIA&format=glimdown) (using Ionic from a CDN) Legacy[​](https://stenciljs.com/docs/next/ember#legacy "Direct link to Legacy") -------------------------------------------------------------------------------- Working with Stencil components in Ember is really easy thanks to the `ember-cli-stencil` addon. It handles: * Importing the required files into your `vendor.js` * Copying the component definitions into your `assets` directory * Optionally generating a wrapper component for improved compatibility with older Ember versions Start off by installing the Ember addon ember install ember-cli-stencil Now, when you build your application, Stencil collections in your dependencies will automatically be discovered and pulled into your application. You can just start using the custom elements in your `hbs` files with no further work needed. For more information, check out the [`ember-cli-stencil` documentation](https://github.com/alexlafroscia/ember-cli-stencil) . _NOTE_: `ember-cli-stencil` hasn't kept up with ember's evolution and will not work in newer ember apps. Contents -------- * [For Monorepos (recommended)](https://stenciljs.com/docs/next/ember#for-monorepos-recommended) * [Legacy](https://stenciljs.com/docs/next/ember#legacy) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/framework-integration/ember.md) --- # Stencil Goals and Objectives | Stencil [Skip to main content](https://stenciljs.com/docs/next/goals-and-objectives#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/goals-and-objectives) ** (v4.35). Version: Next On this page Stencil aims to combine the best concepts of the most popular frontend frameworks into a compile-time tool rather than run-time tool. It's important to stress that Stencil's goal is to _not_ become or be seen as a "framework", but rather our goal is to provide a great developer experience and tooling expected from a framework, while using web-standards within the browser at run-time. In many cases, Stencil can be used as a drop in replacement for traditional frontend frameworks given the capabilities now available in the browser, though using it as such is certainly not required. Web Standards[​](https://stenciljs.com/docs/next/goals-and-objectives#web-standards "Direct link to Web Standards") -------------------------------------------------------------------------------------------------------------------- Components generated by Stencil in the end are built on top of web components, so they work in any major framework or with no framework at all. Additionally, other standards heavily relied on include ES Modules and dynamic imports which have proven to replace traditional bundlers which add unnecessary complexities and run-time JavaScript. By using web-standards, developers can learn and adopt a standard API documented across the world, rather than custom framework APIs that continue to change. Automatic Optimizations[​](https://stenciljs.com/docs/next/goals-and-objectives#automatic-optimizations "Direct link to Automatic Optimizations") -------------------------------------------------------------------------------------------------------------------------------------------------- There are countless optimizations and tweaks developers must do to improve performance of components and websites. With a compiler, Stencil is able to analyze component code as an input, and generate optimized components as an output. Future-Friendly[​](https://stenciljs.com/docs/next/goals-and-objectives#future-friendly "Direct link to Future-Friendly") -------------------------------------------------------------------------------------------------------------------------- As the world of software development continues to evolve, so too can the compiler. Instead of requiring complete rewrites of components, the compiler can continue to make optimizations using the standard component model as the common input. The compiler allows developers to create future-friendly components, while still staying up-to-date on the latest optimizations without starting over again and again. Additionally, if something changes about any API, the compiler is able to make automatic adjustments and notify the developer exactly what needs to be updated. Run-time Performance[​](https://stenciljs.com/docs/next/goals-and-objectives#run-time-performance "Direct link to Run-time Performance") ----------------------------------------------------------------------------------------------------------------------------------------- Instead of writing custom client-side JavaScript which every user needs to download and parse for the app to work, Stencil instead prefers to use the already amazing APIs built directly within the browser. These APIs include Custom Elements. Tiny API[​](https://stenciljs.com/docs/next/goals-and-objectives#tiny-api "Direct link to Tiny API") ----------------------------------------------------------------------------------------------------- Stencil purposely does not come with a large custom API which needs to be learned and re-learned, but rather heavily relies on, you guessed it, web-standards. Again, our goal is to not create yet-another-framework, but rather provide tooling for developers to generate future-friendly components using APIs already baked within the browser. The smaller the API, the easier to learn, and the less that can be broken. Framework Features During Development[​](https://stenciljs.com/docs/next/goals-and-objectives#framework-features-during-development "Direct link to Framework Features During Development") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you haven't noticed already we think web-standards are great and offer many benefits. While using web-standards without any structure is certainly possible, and there are actually many use-cases where this would be appropriate, we found that as apps and teams scale it quickly becomes difficult to manage. Developers often gravitate to frameworks because of their great tooling, defined structure, and ability to allow developers to build apps quickly. One of the largest goals of Stencil is to be that intersection of having great framework features and first-class tooling during development but generating future-proof web-standard code, rather than custom framework specific code. Wide Browser Support[​](https://stenciljs.com/docs/next/goals-and-objectives#wide-browser-support "Direct link to Wide Browser Support") ----------------------------------------------------------------------------------------------------------------------------------------- For the small minority of browsers that do not support modern browser features and APIs, Stencil will automatically polyfill them on-demand. What this means is that for browsers that already support the feature natively, they will not have to download and parse any unnecessary JavaScript. The great news is that in today's web landscape, most modern APIs are already shipping for what Stencil requires. Contents -------- * [Web Standards](https://stenciljs.com/docs/next/goals-and-objectives#web-standards) * [Automatic Optimizations](https://stenciljs.com/docs/next/goals-and-objectives#automatic-optimizations) * [Future-Friendly](https://stenciljs.com/docs/next/goals-and-objectives#future-friendly) * [Run-time Performance](https://stenciljs.com/docs/next/goals-and-objectives#run-time-performance) * [Tiny API](https://stenciljs.com/docs/next/goals-and-objectives#tiny-api) * [Framework Features During Development](https://stenciljs.com/docs/next/goals-and-objectives#framework-features-during-development) * [Wide Browser Support](https://stenciljs.com/docs/next/goals-and-objectives#wide-browser-support) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/introduction/02-goals-and-objectives.md) --- # Assets | Stencil [Skip to main content](https://stenciljs.com/docs/next/assets#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/assets) ** (v4.35). Version: Next On this page Stencil components may need one or more static files as a part of their design. These types of files are referred to as 'assets', and include images, fonts, etc. In this guide, we describe different strategies for resolving assets on the filesystem. note CSS files are handled differently than assets; for more on using CSS, please see the [styling documentation](https://stenciljs.com/docs/next/styling) . Asset Base Path[​](https://stenciljs.com/docs/next/assets#asset-base-path "Direct link to Asset Base Path") ------------------------------------------------------------------------------------------------------------ The **asset base path** is the directory that Stencil will use to resolve assets. When a component uses an asset, the asset's location is resolved relative to the asset base path. The asset base path is automatically set for the following output targets: * [dist](https://stenciljs.com/docs/next/distribution) * [hydrate](https://stenciljs.com/docs/next/hydrate-app) * [www](https://stenciljs.com/docs/next/www) For all other output targets, assets must be [moved](https://stenciljs.com/docs/next/assets#manually-moving-assets) and the asset base path must be [manually set](https://stenciljs.com/docs/next/assets#setassetpath) . For each instance of the Stencil runtime that is loaded, there is a single asset base path. Oftentimes, this means there is only one asset base path per application using Stencil. Resolution Overview[​](https://stenciljs.com/docs/next/assets#resolution-overview "Direct link to Resolution Overview") ------------------------------------------------------------------------------------------------------------------------ The process of resolving an asset involves asking Stencil to build a path to the asset on the filesystem. When an asset's path is built, the resolution is always done in a project's compiled output, not the directory containing the original source code. The example below uses the output of the [`www` output target](https://stenciljs.com/docs/next/www) to demonstrate how assets are resolved. Although the example uses the output of `www` builds, the general principle of how an asset is found holds for all output targets. When using the `www` output target, a `build/` directory is automatically created and set as the asset base path. An example `build/` directory and the assets it contains can be found below. www/├── build/│ ├── assets/│ │ ├── logo.png│ │ └── scenery/│ │ ├── beach.png│ │ └── sunset.png│ └── other-assets/│ └── font.tiff└── ... To resolve the path to an asset, Stencil's [`getAssetPath()` API](https://stenciljs.com/docs/next/assets#getassetpath) may be used. When using `getAssetPath`, the assets in the directory structure above are resolved relative to `build/`. The code sample below demonstrates the return value of `getAssetPath` for different `path` arguments. The return value is a path that Stencil has built to retrieve the asset on the filesystem. import { getAssetPath } from '@stencil/core';// with an asset base path of "/build/":// '/build/assets/logo.png'getAssetPath('assets/logo.png');// '/build/assets/scenery/beach.png'getAssetPath('assets/scenery/beach.png');// '/build/other-assets/font.tiff'getAssetPath('other-assets/font.tiff'); Making Assets Available[​](https://stenciljs.com/docs/next/assets#making-assets-available "Direct link to Making Assets Available") ------------------------------------------------------------------------------------------------------------------------------------ In order to be able to find assets at runtime, they need to be found on the filesystem from the output of a Stencil build. In other words, we need to ensure they exist in the distribution directory. This section describes how to make assets available under the asset base path. ### assetsDirs[​](https://stenciljs.com/docs/next/assets#assetsdirs "Direct link to assetsDirs") The `@Component` decorator can be [configured with the `assetsDirs` option](https://stenciljs.com/docs/next/component#component-options) . `assetsDirs` takes an array of strings, where each entry is a relative path from the component to a directory containing the assets the component requires. When using the `dist` or `www` output targets, setting `assetsDirs` instructs Stencil to copy that folder into the distribution folder. When using other output targets, Stencil will not copy assets into the distribution folder. Below is an example project's directory structure containing an example component and an assets directory. src/└── components/ ├── assets/ │ ├── beach.jpg │ └── sunset.jpg └── my-component.tsx Below, the `my-component` component will correctly load the assets based on it's `image` prop. // file: my-component.tsx// 1. getAssetPath is imported from '@stencil/core'import { Component, Prop, getAssetPath, h } from '@stencil/core';@Component({ tag: 'my-component', // 2. assetsDirs lists the 'assets' directory as a relative // (sibling) directory assetsDirs: ['assets']})export class MyComponent { @Prop() image = "sunset.jpg"; render() { // 3. the asset path is retrieved relative to the asset // base path to use in the tag const imageSrc = getAssetPath(`./assets/${this.image}`); return }} In the example above, the following allows `my-component` to display the provided asset: 1. [`getAssetPath()`](https://stenciljs.com/docs/next/assets#getassetpath) is imported from `@stencil/core` 2. The `my-component`'s component decorator has the `assetsDirs` property, and lists the sibling directory, `assets`. This will copy `assets` over to the distribution directory. 3. `getAssetPath` is used to retrieve the path to the image to be used in the `` tag ### Manually Moving Assets[​](https://stenciljs.com/docs/next/assets#manually-moving-assets "Direct link to Manually Moving Assets") For the [dist-custom-elements](https://stenciljs.com/docs/next/custom-elements) output target, options like `assetsDirs` do not copy assets to the distribution directory. It's recommended that a bundler (such as rollup) or a Stencil `copy` task is used to ensure the static assets are copied to the distribution directory. #### Stencil Copy Task[​](https://stenciljs.com/docs/next/assets#stencil-copy-task "Direct link to Stencil Copy Task") [Stencil `copy` task](https://stenciljs.com/docs/next/copy-tasks) s can be used to define files and folders to be copied over to the distribution directory. The example below shows how a copy task can be used to find all '.jpg' and '.png' files under a project's `src` directory and copy them to `dist/components/assets` at build time. import { Config } from '@stencil/core';export const config: Config = { namespace: 'your-component-library', outputTargets: [ { type: 'dist-custom-elements', copy: [ { src: '**/*.{jpg,png}', dest: 'dist/components/assets', warn: true, } ] }, ], // ...}; #### Rollup Configuration[​](https://stenciljs.com/docs/next/assets#rollup-configuration "Direct link to Rollup Configuration") [Rollup Plugins](https://stenciljs.com/docs/next/plugins#rollup-plugins) 's can be used to define files and folders to be copied over to the distribution directory. The example below shows how a the `rollup-plugin-copy` NPM module can be used to find all '.jpg' and '.png' files under a project's `src` directory and copy them to `dist/components/assets` at build time. import { Config } from '@stencil/core';import copy from 'rollup-plugin-copy';export const config: Config = { namespace: 'copy', outputTargets: [ { type: 'dist-custom-elements', }, ], rollupPlugins: { after: [ copy({ targets: [ { src: 'src/**/*.{jpg,png}', dest: 'dist/components/assets', }, ], }), ] }}; API Reference[​](https://stenciljs.com/docs/next/assets#api-reference "Direct link to API Reference") ------------------------------------------------------------------------------------------------------ ### getAssetPath[​](https://stenciljs.com/docs/next/assets#getassetpath "Direct link to getAssetPath") `getAssetPath()` is an API provided by Stencil to build the path to an asset, relative to the asset base path. /** * Builds a URL to an asset. This is achieved by combining the * provided `path` argument with the base asset path. * @param path the path of the asset to build a URL to * @returns the built URL */declare function getAssetPath(path: string): string; The code sample below demonstrates the return value of `getAssetPath` for different `path` arguments, when an asset base path of `/build/` has been set. import { getAssetPath } from '@stencil/core';// with an asset base path of "/build/":// "/build/"getAssetPath('');// "/build/my-image.png"getAssetPath('my-image.png');// "/build/assets/my-image.png"getAssetPath('assets/my-image.png');// "/build/assets/my-image.png"getAssetPath('./assets/my-image.png');// "/assets/my-image.png"getAssetPath('../assets/my-image.png');// "/assets/my-image.png"getAssetPath('/assets/my-image.png'); ### setAssetPath[​](https://stenciljs.com/docs/next/assets#setassetpath "Direct link to setAssetPath") `setAssetPath` is an API provided by Stencil's runtime to manually set the asset base path where assets can be found. If you are using `getAssetPath` to compose the path for your component assets, `setAssetPath` allows you or the consumer of the component to change that path. /** * Set the base asset path for resolving components * @param path the base asset path * @returns the new base asset path */export declare function setAssetPath(path: string): string; Calling this API will set the asset base path for all Stencil components attached to a Stencil runtime. As a result, calling `setAssetPath` should not be done from within a component in order to prevent unwanted side effects when using a component. Make sure as component author to export this function as part of your module in order to also make it accessible to the consumer of your component, e.g. in your package entry file export the function via: /src/index.ts export { setAssetPath } from '@stencil/core'; Now your users can import it directly from your component library, e.g.: import { setAssetPath } from 'my-component-library';setAssetPath(`${window.location.protocol}//assets.${window.location.host}/`); Alternatively, one may use [`document.currentScript.src`](https://developer.mozilla.org/en-US/docs/Web/API/Document/currentScript) when working in the browser and not using modules or environment variables (e.g. `document.env.ASSET_PATH`) to set the asset base path. This configuration depends on how your script is bundled, (or lack of bundling), and where your assets can be loaded from. note If your component library exports components compiled with [`dist-output-target`](https://stenciljs.com/docs/next/custom-elements) and `externalRuntime` set to `true`, then `setAssetPath` has to be imported from `@stencil/core` directly. In case you import a component directly via script tag, this would look like: Contents -------- * [Asset Base Path](https://stenciljs.com/docs/next/assets#asset-base-path) * [Resolution Overview](https://stenciljs.com/docs/next/assets#resolution-overview) * [Making Assets Available](https://stenciljs.com/docs/next/assets#making-assets-available) * [assetsDirs](https://stenciljs.com/docs/next/assets#assetsdirs) * [Manually Moving Assets](https://stenciljs.com/docs/next/assets#manually-moving-assets) * [API Reference](https://stenciljs.com/docs/next/assets#api-reference) * [getAssetPath](https://stenciljs.com/docs/next/assets#getassetpath) * [setAssetPath](https://stenciljs.com/docs/next/assets#setassetpath) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/guides/assets.md) --- # Custom Elements with Stencil | Stencil [Skip to main content](https://stenciljs.com/docs/next/custom-elements#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/custom-elements) ** (v4.35). Version: Next On this page The `dist-custom-elements` output target creates custom elements that directly extend `HTMLElement` and provides simple utility functions for easily defining these elements on the [Custom Element Registry](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry) . This output target excels in use in frontend frameworks and projects that will handle bundling, lazy-loading, and custom element registration themselves. This target can be used outside of frameworks as well, if lazy-loading functionality is not required or desired. For using lazily loaded Stencil components, please refer to the [dist output target](https://stenciljs.com/docs/next/distribution) . To generate components using the `dist-custom-elements` output target, add it to a project's `stencil.config.ts` file like so: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { // Other top-level config options here outputTargets: [ { type: 'dist-custom-elements', // Output target config options here }, // Other output targets here ],}; Config[​](https://stenciljs.com/docs/next/custom-elements#config "Direct link to Config") ------------------------------------------------------------------------------------------ ### copy[​](https://stenciljs.com/docs/next/custom-elements#copy "Direct link to copy") _default: `undefined`_ An array of [copy tasks](https://stenciljs.com/docs/next/copy-tasks) to be executed during the build process. ### customElementsExportBehavior[​](https://stenciljs.com/docs/next/custom-elements#customelementsexportbehavior "Direct link to customElementsExportBehavior") _default: `'default'`_ By default, the `dist-custom-elements` output target generates a single file per component, and exports each of those files individually. In some cases, library authors may want to change this behavior, for instance to automatically define component children, provide a single file containing all component exports, etc. This config option provides additional behaviors that will alter the default component export _OR_ custom element definition behaviors for this target. The desired behavior can be set via the following in a project's Stencil config: // stencil.config.tsimport { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'dist-custom-elements', customElementsExportBehavior: 'default' | 'auto-define-custom-elements' | 'bundle' | 'single-export-module', }, // ... ], // ...}; | Option | Description | | --- | --- | | `default` | No additional re-export or auto-definition behavior will be performed.

This value will be used if no explicit value is set in the config, or if a given value is not a valid option. | | `auto-define-custom-elements` | A component and its children will be automatically defined with the `CustomElementRegistry` when the component's module is imported. | | `bundle` | A utility `defineCustomElements()` function is exported from the `index.js` file of the output directory. This function can be used to quickly define all Stencil components in a project on the custom elements registry. | | `single-export-module` | All component and custom element definition helper functions will be exported from the `index.js` file in the output directory. This file can be used as the root module when distributing your component library, see [Publishing](https://stenciljs.com/docs/publishing)
for more details. | note At this time, components that do not use JSX cannot be automatically defined. This is a known limitation of Stencil that users should be aware of. ### dir[​](https://stenciljs.com/docs/next/custom-elements#dir "Direct link to dir") _default: `'dist/components'`_ This config option allows you to change the output directory where the compiled output for this output target will be written. ### empty[​](https://stenciljs.com/docs/next/custom-elements#empty "Direct link to empty") _default: `true`_ Setting this flag to `true` will remove the contents of the [output directory](https://stenciljs.com/docs/next/custom-elements#dir) between builds. ### externalRuntime[​](https://stenciljs.com/docs/next/custom-elements#externalruntime "Direct link to externalRuntime") _default: `true`_ Setting this flag to `true` results in the following behaviors: 1. Minification will follow what is specified in the [Stencil config](https://stenciljs.com/docs/next/config#minifyjs) . 2. Filenames will not be hashed. 3. All imports from packages under `@stencil/core/*` will be marked as external and therefore not included in the generated Rollup bundle. Ensure that `@stencil/core` is included in your list of dependencies if you set this option to `true`. This is crucial to prevent any runtime errors. ### generateTypeDeclarations[​](https://stenciljs.com/docs/next/custom-elements#generatetypedeclarations "Direct link to generateTypeDeclarations") _default: `true`_ By default, Stencil will generate type declaration files (`.d.ts` files) as a part of the `dist-custom-elements` output target through the `generateTypeDeclarations` field on the target options. Type declaration files will be placed in the `dist/types` directory in the root of a Stencil project. At this time, this output destination is not able to be configured. Setting this flag to `false` will not generate type declaration files for the `dist-custom-elements` output target. note When set to generate type declarations, Stencil respects the export behavior selected via `customElementsExportBehavior` and generates type declarations specific to the content of the generated [output directory's](https://stenciljs.com/docs/next/custom-elements#dir) `index.js` file. ### includeGlobalScripts[​](https://stenciljs.com/docs/next/custom-elements#includeglobalscripts "Direct link to includeGlobalScripts") _default: `false`_ Setting this flag to `true` will include [global scripts](https://stenciljs.com/docs/next/config#globalscript) in the bundle and execute them once the bundle entry point in loaded. ### isPrimaryPackageOutputTarget[​](https://stenciljs.com/docs/next/custom-elements#isprimarypackageoutputtarget "Direct link to isPrimaryPackageOutputTarget") _default: `false`_ If `true`, this output target will be used to validate `package.json` fields for your project's distribution. See the overview of [primary package output target validation](https://stenciljs.com/docs/next/output-targets#primary-package-output-target-validation) for more information. ### minify[​](https://stenciljs.com/docs/next/custom-elements#minify "Direct link to minify") _default: `false`_ Setting this flag to `true` will cause file minification to follow what is specified in the [Stencil config](https://stenciljs.com/docs/next/config#minifyjs) . _However_, if [`externalRuntime`](https://stenciljs.com/docs/next/custom-elements#externalruntime) is enabled, it will override this option and always result in minification being disabled. Making Assets Available[​](https://stenciljs.com/docs/next/custom-elements#making-assets-available "Direct link to Making Assets Available") --------------------------------------------------------------------------------------------------------------------------------------------- For performance reasons, the generated bundle does not include [local assets](https://stenciljs.com/docs/next/assets) built within the JavaScript output, but instead it's recommended to keep static assets as external files. By keeping them external this ensures they can be requested on-demand, rather than either welding their content into the JS file, or adding many URLs for the bundler to add to the output. One method to ensure [assets](https://stenciljs.com/docs/next/assets) are available to external builds and http servers is to set the asset path using `setAssetPath()`. The `setAssetPath()` function is used to manually set the base path where static assets can be found. For the lazy-loaded output target the asset path is automatically set and assets copied to the correct build directory. However, for custom elements builds, the `setAssetPath(path)` should be used to customize the asset path depending on where they are found on the http server. If the component's script is a `type="module"`, it's recommended to use `import.meta.url`, such as `setAssetPath(import.meta.url)`. Other options include `setAssetPath(document.currentScript.src)`, or using a bundler's replace plugin to dynamically set the path at build time, such as `setAssetPath(process.env.ASSET_PATH)`. import { setAssetPath } from 'my-library/dist/components';setAssetPath(document.currentScript.src); Make sure to copy the assets over to a public directory in your app. This configuration depends on how your script is bundled, or lack of bundling, and where your assets can be loaded from. How the files are copied to the production build directory depends on the bundler or tooling. The configs below provide examples of how to do this automatically with popular bundlers. Example Bundler Configs[​](https://stenciljs.com/docs/next/custom-elements#example-bundler-configs "Direct link to Example Bundler Configs") --------------------------------------------------------------------------------------------------------------------------------------------- Instructions for consuming the custom elements bundle vary depending on the bundler you're using. These examples will help your users consume your components with webpack and Rollup. The following examples assume your component library is published to NPM as `my-library`. You should change this to the name you actually publish your library with. Users will need to install your library before importing them. * npm * Yarn * pnpm npm install my-library yarn add my-library pnpm add my-library ### webpack.config.js[​](https://stenciljs.com/docs/next/custom-elements#webpackconfigjs "Direct link to webpack.config.js") A webpack config will look something like the one below. Note how assets are copied from the library's `node_module` folder to `dist/assets` via the `CopyPlugin` utility. This is important if your library includes [local assets](https://stenciljs.com/docs/next/assets) . const path = require('path');const CopyPlugin = require('copy-webpack-plugin');module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ { test: /\.css$/i, use: ['style-loader', 'css-loader'], }, ], }, plugins: [ new CopyPlugin({ patterns: [ { from: path.resolve(__dirname, 'node_modules/my-library/dist/my-library/assets'), to: path.resolve(__dirname, 'dist/assets'), }, ], }), ],}; ### rollup.config.js[​](https://stenciljs.com/docs/next/custom-elements#rollupconfigjs "Direct link to rollup.config.js") A Rollup config will look something like the one below. Note how assets are copied from the library's `node_module` folder to `dist/assets` via the `rollup-copy-plugin` utility. This is important if your library includes [local assets](https://stenciljs.com/docs/next/assets) . import path from 'path';import commonjs from '@rollup/plugin-commonjs';import copy from 'rollup-plugin-copy';import postcss from 'rollup-plugin-postcss';import resolve from '@rollup/plugin-node-resolve';export default { input: 'src/index.js', output: [{ dir: path.resolve('dist/'), format: 'es' }], plugins: [ resolve(), commonjs(), postcss({ extensions: ['.css'], }), copy({ targets: [ { src: path.resolve(__dirname, 'node_modules/my-library/dist/my-library/assets'), dest: path.resolve(__dirname, 'dist'), }, ], }), ],}; Contents -------- * [Config](https://stenciljs.com/docs/next/custom-elements#config) * [copy](https://stenciljs.com/docs/next/custom-elements#copy) * [customElementsExportBehavior](https://stenciljs.com/docs/next/custom-elements#customelementsexportbehavior) * [dir](https://stenciljs.com/docs/next/custom-elements#dir) * [empty](https://stenciljs.com/docs/next/custom-elements#empty) * [externalRuntime](https://stenciljs.com/docs/next/custom-elements#externalruntime) * [generateTypeDeclarations](https://stenciljs.com/docs/next/custom-elements#generatetypedeclarations) * [includeGlobalScripts](https://stenciljs.com/docs/next/custom-elements#includeglobalscripts) * [isPrimaryPackageOutputTarget](https://stenciljs.com/docs/next/custom-elements#isprimarypackageoutputtarget) * [minify](https://stenciljs.com/docs/next/custom-elements#minify) * [Making Assets Available](https://stenciljs.com/docs/next/custom-elements#making-assets-available) * [Example Bundler Configs](https://stenciljs.com/docs/next/custom-elements#example-bundler-configs) * [webpack.config.js](https://stenciljs.com/docs/next/custom-elements#webpackconfigjs) * [rollup.config.js](https://stenciljs.com/docs/next/custom-elements#rollupconfigjs) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/output-targets/custom-elements.md) --- # Docs JSON Data Output Target | Stencil [Skip to main content](https://stenciljs.com/docs/next/docs-json#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/docs-json) ** (v4.35). Version: Next On this page Stencil supports automatically [generating `README` files](https://stenciljs.com/docs/next/docs-readme) in your project which pull in [JSDoc comments](https://jsdoc.app/) and provide a straightforward way to document your components. If you need more flexibility, Stencil can also write documentation to a JSON file which you could use for a custom downstream documentation website. You can try this out is using the `--docs-json` CLI flag like so: stencil build --docs-json path/to/docs.json You can also add the `docs-json` output target to your project's configuration file in order to auto-generate this file every time you build: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-json', file: 'path/to/docs.json' } ]}; The JSON file output by Stencil conforms to the [`JsonDocs` interface in Stencil's public TypeScript declarations](https://github.com/ionic-team/stencil/blob/main/src/declarations/stencil-public-docs.ts) . `supplementalPublicTypes`[​](https://stenciljs.com/docs/next/docs-json#supplementalpublictypes "Direct link to supplementalpublictypes") ----------------------------------------------------------------------------------------------------------------------------------------- As of Stencil v4 the JSON documentation generation functionality in Stencil supports a new configuration option, `supplementalPublicTypes`. This functionality makes it easy to automatically document types and interfaces which otherwise wouldn't be included in the documentation that Stencil generates. By default, Stencil includes extensive information about the types used in the public APIs of all your components, meaning the properties on your components decorated with `@Watch`, `@Event`, `@Prop` and so on. This makes it easy to document your components' APIs; however, if your project uses other types which aren't found in the public API of a component then those types won't be included. The new `supplementalPublicTypes` option fills in this gap by allowing you to designate a file of types which should be included in the output of the `docs-json` output target. This information will be found in a top-level property called `typeLibrary` on the JSON output and will conform to the [`JsonDocsTypeLibrary` interface in Stencil's public TypeScript declarations](https://github.com/ionic-team/stencil/blob/main/src/declarations/stencil-public-docs.ts) . Using this option could look something like this: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-json', file: 'path/to/docs.json', supplementalPublicTypes: 'src/public-interfaces.ts', } ]}; CSS Variables[​](https://stenciljs.com/docs/next/docs-json#css-variables "Direct link to CSS Variables") --------------------------------------------------------------------------------------------------------- Stencil can document CSS variables if you annotate them with JSDoc-style comments in your CSS/SCSS files. If, for instance, you had a component with a CSS file like the following: src/components/my-button/my-button.css :host { /** * @prop --background: Background of the button * @prop --background-activated: Background of the button when activated * @prop --background-focused: Background of the button when focused */ --background: pink; --background-activated: aqua; --background-focused: fuchsia;} Then you'd get the following in the JSON output: Example docs-json Output [ { "name": "--background", "annotation": "prop", "docs": "Background of the button" }, { "name": "--background-activated", "annotation": "prop", "docs": "Background of the button when activated" }, { "name": "--background-focused", "annotation": "prop", "docs": "Background of the button when focused" }] If the style sheet is configured to be used with [a specific mode](https://stenciljs.com/docs/next/styling) , the mode associated with the CSS property will be provided as well: Example docs-json Output with Mode [ { "name": "--background", "annotation": "prop", "docs": "Background of the button"+ "mode": "ios", }, { "name": "--background-activated", "annotation": "prop", "docs": "Background of the button when activated"+ "mode": "ios", }, { "name": "--background-focused", "annotation": "prop", "docs": "Background of the button when focused"+ "mode": "ios", }] note This functionality works with both standard CSS and with Sass, although for the latter you'll need to have the [@stencil/sass](https://github.com/ionic-team/stencil-sass) plugin installed and configured. Slots[​](https://stenciljs.com/docs/next/docs-json#slots "Direct link to Slots") --------------------------------------------------------------------------------- If one of your Stencil components makes use of [slots](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) for rendering children you can document them by using the `@slot` JSDoc tag in the component's comment. For instance, if you had a `my-button` component with a slot you might document it like so: src/components/my-button/my-button.tsx import { Component, h } from '@stencil/core';/** * @slot buttonContent - Slot for the content of the button */@Component({ tag: 'my-button', styleUrl: 'my-button.css', shadow: true,})export class MyButton { render() { return }} This would show up in the generated JSON file like so: "slots": { "name": "buttonContent", "docs": "Slot for the content of the button"} caution Stencil does not check that the slots you document in a component's JSDoc comment using the `@slot` tag are actually present in the JSX returned by the component's `render` function. It is up to you as the component author to ensure the `@slot` tags on a component are kept up to date. Usage[​](https://stenciljs.com/docs/next/docs-json#usage "Direct link to Usage") --------------------------------------------------------------------------------- You can save usage examples for a component in the `usage/` subdirectory within that component's directory. The content of these files will be added to the `usage` property of the generated JSON. This allows you to keep examples right next to the code, making it easy to include them in a documentation site or other downstream consumer(s) of your docs. caution Stencil doesn't check that your usage examples are up-to-date! If you make any changes to your component's API you'll need to remember to update your usage examples manually. If, for instance, you had a usage example like this: src/components/my-button/usage/my-button-usage.md # How to use `my-button`A button is often a great help in adding interactivity to an app!You could use it like this:```htmlMy Button!``` You'd get the following in the JSON output under the `"usage"` key: "usage": { "a-usage-example": "# How to use `my-button`\n\nA button is often a great help in adding interactivity to an app!\n\nYou could use it like this:\n\n```html\nMy Button!\n```\n"} Custom JSDocs Tags[​](https://stenciljs.com/docs/next/docs-json#custom-jsdocs-tags "Direct link to Custom JSDocs Tags") ------------------------------------------------------------------------------------------------------------------------ In addition to reading the [standard JSDoc tags](https://jsdoc.app/) , users can use their own custom tags which will be included in the JSON data without any configuration. This can be useful if your team has your own documentation conventions which you'd like to stick with. If, for example, we had a component with custom JSDoc tags like this: import { Component, h } from '@stencil/core';/** * @customDescription This is just the best button around! */@Component({ tag: 'my-button', styleUrl: 'my-button.css', shadow: true,})export class MyButton { render() { return }} It would end up in the JSON data like this: "docsTags": [ { "name": "customDescription", "text": "This is just the best button around!" }], Contents -------- * [`supplementalPublicTypes`](https://stenciljs.com/docs/next/docs-json#supplementalpublictypes) * [CSS Variables](https://stenciljs.com/docs/next/docs-json#css-variables) * [Slots](https://stenciljs.com/docs/next/docs-json#slots) * [Usage](https://stenciljs.com/docs/next/docs-json#usage) * [Custom JSDocs Tags](https://stenciljs.com/docs/next/docs-json#custom-jsdocs-tags) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/documentation-generation/docs-json.md) --- # Stencil - A Compiler for Web Components | Stencil [Skip to main content](https://stenciljs.com/docs/next/introduction#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/introduction) ** (v4.35). Version: Next On this page Stencil: A Web Components Compiler[​](https://stenciljs.com/docs/next/introduction#stencil-a-web-components-compiler "Direct link to Stencil: A Web Components Compiler") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Stencil is a compiler that generates Web Components (more specifically, Custom Elements). Stencil combines the best concepts of the most popular frameworks into a simple build-time tool. Stencil uses TypeScript, JSX, and CSS to create standards-compliant Web Components that can be used to craft high quality component libraries. Web Components generated with Stencil can be used with popular frameworks right out of the box. In addition, Stencil can generate framework-specific wrappers that allow Stencil components to be used with a framework-specific developer experience. Compared with using the [Custom Elements APIs](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) directly, Stencil provides [convenient APIs](https://stenciljs.com/docs/next/api) which make writing fast components simpler. With a Virtual DOM, JSX, and async rendering, it is easy to create fast and powerful components which are still 100% compatible with Web Components standards. In addition to making it easier to author Custom Elements, Stencil also adds a number of key capabilities on top of Web Components, such as prerendering and objects-as-properties (instead of just strings). The developer experience is also tuned, and comes with live reload and a small dev server baked into the compiler. How can I use Stencil?[​](https://stenciljs.com/docs/next/introduction#how-can-i-use-stencil "Direct link to How can I use Stencil?") -------------------------------------------------------------------------------------------------------------------------------------- ### Design Systems & Component Libraries[​](https://stenciljs.com/docs/next/introduction#design-systems--component-libraries "Direct link to Design Systems & Component Libraries") Stencil's primary objective is providing amazing tools for design systems and component libraries. Components as a concept provide similar language for engineers and designers to have productive conversations about design implementation. [Visit the Stencil for Design Systems page to learn more.](https://stenciljs.com/docs/next/design-systems) The History of Stencil[​](https://stenciljs.com/docs/next/introduction#the-history-of-stencil "Direct link to The History of Stencil") --------------------------------------------------------------------------------------------------------------------------------------- Stencil was originally created by the **[Ionic Framework](http://ionicframework.com/) ** team in order to build faster, more capable components that worked across every major framework. The emergence of Progressive Web Apps as a rapidly growing target for web developers demanded a different approach to web app development performance. With Ionic's classic use of traditional frameworks and bundling techniques, the team was struggling to meet latency and code size demands for Progressive Web Apps that ran equally well on fast and slow networks, across a diversity of platforms and devices. Additionally, framework fragmentation had created a web development interoperability nightmare, where components built for one framework didn't work with another framework. Web Components offered a solution to both problems, pushing more work to the browser for better performance, and targeting a standards-based component model that all frameworks could use. Web Components by themselves, however, weren't enough. Building fast web apps required innovations that were previously locked up inside of traditional web frameworks. Stencil was built to pull these features out of traditional frameworks and bring them to the fast emerging Web Component standard. While Stencil is intended to be used primarily to build design systems and component libraries, these innovations allowed entire applications to be built using only Stencil. Contents -------- * [Stencil: A Web Components Compiler](https://stenciljs.com/docs/next/introduction#stencil-a-web-components-compiler) * [How can I use Stencil?](https://stenciljs.com/docs/next/introduction#how-can-i-use-stencil) * [Design Systems & Component Libraries](https://stenciljs.com/docs/next/introduction#design-systems--component-libraries) * [The History of Stencil](https://stenciljs.com/docs/next/introduction#the-history-of-stencil) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/introduction/01-overview.md) --- # Framework Integration | Stencil [Skip to main content](https://stenciljs.com/docs/next/overview#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/overview) ** (v4.35). Version: Next Stencil's primary goal is to remove the need for components to be written using a specific framework's API. It accomplishes this by using standardized web platform APIs that work across all modern browsers. Using the low-level component model that is provided by the browser (which all frameworks are built on) allows Stencil components to work inside a framework or without one. The experience of integrating web components directly into existing applications can be tricky at times, as frameworks have varying support for vanilla web components. In order to accommodate the various issues the Stencil team has created Framework Wrappers to make the process simpler. The Framework Wrappers are configured like output targets, and emit a native library, just like if your components were originally written using any of these frameworks: * [Angular](https://stenciljs.com/docs/next/angular) * [React](https://stenciljs.com/docs/next/react) * [Vue](https://stenciljs.com/docs/next/vue) * [Ember (Community)](https://stenciljs.com/docs/next/ember) By using Stencil bindings, you can build your components once, and have Stencil emit Angular/React/Vue libraries. This way, the consumers of your components can enjoy all the features of their framework of choice. --- # Stencil Frequently Asked Questions | Stencil [Skip to main content](https://stenciljs.com/docs/next/faq#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/faq) ** (v4.35). Version: Next On this page Introduction[​](https://stenciljs.com/docs/next/faq#introduction "Direct link to Introduction") ------------------------------------------------------------------------------------------------ ### What is Stencil?[​](https://stenciljs.com/docs/next/faq#what-is-stencil "Direct link to What is Stencil?") Stencil is a developer-focused toolchain for building reusable, scalable component libraries. It provides a compiler that generates highly optimized Web Components, and combines the best concepts of the most popular frameworks into a simple build-time tool. Stencil focuses on building components with web standards. It’s used by developers and organizations around the world, and is [100% free and MIT open source](https://github.com/ionic-team/stencil/blob/main/LICENSE.md) . ### What does Stencil do?[​](https://stenciljs.com/docs/next/faq#what-does-stencil-do "Direct link to What does Stencil do?") Stencil helps developers and teams build and share custom components. Since Stencil generates standards-compliant Web Components, the components you build with Stencil will work with many popular frameworks right out of the box, and can even be used without a framework because they are just Web Components. Stencil also enables a number of key capabilities on top of Web Components, in particular, prerendering, and objects-as-properties (instead of just strings). ### Who is Stencil for?[​](https://stenciljs.com/docs/next/faq#who-is-stencil-for "Direct link to Who is Stencil for?") Stencil is for developers and teams that want to build custom component libraries that can be shared across teams, frameworks and large organizations. Stencil can also be used by designers who want their original design visions delivered consistently, with high fidelity, to all users. ### Who makes Stencil?[​](https://stenciljs.com/docs/next/faq#who-makes-stencil "Direct link to Who makes Stencil?") Stencil is an open source project started by the [Ionic core team](https://ionicframework.com/) , with contributions also coming from the community. ### Why was Stencil created?[​](https://stenciljs.com/docs/next/faq#why-was-stencil-created "Direct link to Why was Stencil created?") Stencil was created by the Ionic Framework team to make our own component library faster, smaller, and compatible with all major frameworks. Web Components offered a solution by pushing more work to the browser for better performance, and targeting a standards-based component model that all frameworks could use. ### Who uses Stencil?[​](https://stenciljs.com/docs/next/faq#who-uses-stencil "Direct link to Who uses Stencil?") Stencil was initially developed for Ionic Framework which is a very successful Web Component-based library & UI framework. Web Components are now in thousands of app store apps, and nearly 4 million new Ionic Framework projects are being created every year. ### How does Stencil compare to traditional frameworks?[​](https://stenciljs.com/docs/next/faq#how-does-stencil-compare-to-traditional-frameworks "Direct link to How does Stencil compare to traditional frameworks?") The Web Component ecosystem has a diverse set of players, each with a different long-term vision for what Web Components can and should do. Some think Web Components should replace third-party app frameworks, while others think that Web Components are more suited for leaf/style/design nodes and shouldn’t get in the business of your app’s component system. There are also many framework developers that don’t see the point of Web Components, or consider them to be an affront to front-end innovation. With Stencil, our vision is somewhere in the middle. In the long term, we see app development teams continuing to use their framework of choice. We envision these frameworks continuing to get better, smaller, and more efficient, with increasingly good support for targeting and consuming Web Components -- and big teams will be consuming an increasing amount of Web Components as companies continue to embrace them for shared component libraries. At the same time, we believe an indispensable feature for Web Components is solving those component distribution and design system problems. We also believe, however, that 90% of the market doesn’t have those problems to begin with, so the current debate about the merits of Web Components is somewhat unproductive. ### Why is Stencil considered framework-agnostic?[​](https://stenciljs.com/docs/next/faq#why-is-stencil-considered-framework-agnostic "Direct link to Why is Stencil considered framework-agnostic?") Perhaps the most appealing benefit of Web Components is that they give your development teams the flexibility to choose the underlying tools and frameworks - and versions of those frameworks - and tools that they prefer. As pointed out earlier, one of the great challenges of implementing a universal set of components is getting all of your development teams to standardize on just one set of technologies. With Web Components, each team can use what works best for them, giving them complete freedom to use the tools they love—today and tomorrow. What does Stencil provide?[​](https://stenciljs.com/docs/next/faq#what-does-stencil-provide "Direct link to What does Stencil provide?") ----------------------------------------------------------------------------------------------------------------------------------------- ### Does Stencil have a component library?[​](https://stenciljs.com/docs/next/faq#does-stencil-have-a-component-library "Direct link to Does Stencil have a component library?") The most widely used Stencil component library is the Ionic Framework, however, Stencil itself is only a toolchain and does not provide its own component library. We encourage you to first review Ionic components if you are building an application. ### Is Stencil a framework?[​](https://stenciljs.com/docs/next/faq#is-stencil-a-framework "Direct link to Is Stencil a framework?") Stencil purposely does not strive to act as a stand-alone framework, but rather a tool which allows developers to scale framework-agnostic components across many projects, teams and large organizations. One of Stencil’s superpowers is its flexibility: its components could be used stand-alone, or within traditional frameworks. ### Does Stencil come with a testing framework?[​](https://stenciljs.com/docs/next/faq#does-stencil-come-with-a-testing-framework "Direct link to Does Stencil come with a testing framework?") Yes, Stencil provides a rich set of APIs for unit and End-to-end tests. [Learn more about testing with Stencil](https://stenciljs.com/docs/next/testing-overview) . Technology[​](https://stenciljs.com/docs/next/faq#technology "Direct link to Technology") ------------------------------------------------------------------------------------------ ### Why does Stencil use web components?[​](https://stenciljs.com/docs/next/faq#why-does-stencil-use-web-components "Direct link to Why does Stencil use web components?") By using a consistent set of web standards, Web Components do not depend on a specific framework runtime to execute. As frameworks change their APIs, Web Components do not, allowing for the original source to continue to work natively in a browser. ### How is Stencil able to optimize component file size and startup?[​](https://stenciljs.com/docs/next/faq#how-is-stencil-able-to-optimize-component-file-size-and-startup "Direct link to How is Stencil able to optimize component file size and startup?") Traditional frameworks provide a runtime API, and developers can pick and choose which APIs to use per component. However, this means every feature needs to be available to every component, just in case the component may or may not use the API. With Stencil, the compiler is able to perform static analysis on each component in order to understand which APIs are and are not being used. By doing so, Stencil is able to customize each build to use exactly what each component needs, making for a highly optimized runtime with minimal size. Since Stencil uses a compiler, it is able to adjust code as new improvements and features become available. Source code can continue to be written using the same public API and syntax, while the compiler can adjust the code to further take advantage of modern features, without requiring re-writes. ### What template syntax does Stencil use?[​](https://stenciljs.com/docs/next/faq#what-template-syntax-does-stencil-use "Direct link to What template syntax does Stencil use?") Stencil uses [JSX](https://react.dev/learn/writing-markup-with-jsx) , a markup language popularized by the React library. ### Can Stencil components be lazy loaded?[​](https://stenciljs.com/docs/next/faq#can-stencil-components-be-lazy-loaded "Direct link to Can Stencil components be lazy loaded?") Yes! Lazy loading components helps to reduce application startup times, decrease bundle sizes, and improve distribution. Because users are able to dynamically load only what is used, startup times are drastically reduced and users only load exactly what their application’s first paint requires. At the same time, components built with Stencil can still be imported and consumed by traditional bundlers. ### Why are Stencil components written with TypeScript?[​](https://stenciljs.com/docs/next/faq#why-are-stencil-components-written-with-typescript "Direct link to Why are Stencil components written with TypeScript?") Stencil was originally built for Ionic, and in our experience we’ve found TypeScript to be a valuable tool for maintaining a large codebase across multiple teams. ### What dependencies does the Stencil runtime have?[​](https://stenciljs.com/docs/next/faq#what-dependencies-does-the-stencil-runtime-have "Direct link to What dependencies does the Stencil runtime have?") None. The code generated by Stencil does not rely on Stencil, but rather it generates highly-optimized, framework-free, stand-alone code which runs natively in the browser. ### Can data be passed to Web Components?[​](https://stenciljs.com/docs/next/faq#can-data-be-passed-to-web-components "Direct link to Can data be passed to Web Components?") Just like any other DOM element in a webpage, any data in the form of arrays, objects, strings and numbers can be passed to element properties. Stencil is designed from the ground up to ensure this capability stays unlocked for application developers. ### What technology is Stencil built with?[​](https://stenciljs.com/docs/next/faq#what-technology-is-stencil-built-with "Direct link to What technology is Stencil built with?") The Stencil compiler is built with TypeScript and is [distributed on npm](https://www.npmjs.com/package/@stencil/core) . Its distribution includes types, making it easier for developers to use Stencil APIs. Capabilities[​](https://stenciljs.com/docs/next/faq#capabilities "Direct link to Capabilities") ------------------------------------------------------------------------------------------------ ### Where can Stencil components be used?[​](https://stenciljs.com/docs/next/faq#where-can-stencil-components-be-used "Direct link to Where can Stencil components be used?") One great advantage of using Web Components is that your component library will work across all projects, not just desktop web apps. For example, using a hybrid mobile framework like Ionic, you can deploy Web Components across just about any platform or device, from native iOS and Android apps, to Electron and desktop web apps, and even Progressive Web Apps. ### What are the limitations of Web Components?[​](https://stenciljs.com/docs/next/faq#what-are-the-limitations-of-web-components "Direct link to What are the limitations of Web Components?") The [Web Component](https://developer.mozilla.org/en-US/docs/Web/Web_Components) specs are purposely low-level, and on their own, they do not provide a framework quality developer experience. Web Components run on a fairly primitive set of standards, so you will need a little help to get them to meet your objectives. Some limitations include: When you try to use pure vanilla Web Components in an application, functionality like server-side rendering and progressive enhancement is not supported by default, and some out-of-date clients don’t support the Web Components standard. In addition, while Web Components technically work with any framework, there are some limitations like lack of type support and input bindings, and challenges passing properties to components, as noted above. The good news is that, with help from open source tools like Stencil, you can overcome all of these challenges. Stencil includes framework bindings for Angular, React, and Vue, so you can easily import Web Component libraries into any framework, and interact with them just like they were native to that framework, with all the functionality you’re used to. ### What are framework bindings?[​](https://stenciljs.com/docs/next/faq#what-are-framework-bindings "Direct link to What are framework bindings?") While Web Components can be paired with any JavaScript framework, Stencil has built-in special-purpose bindings to deliver the more advanced features enterprise teams expect when building applications in Angular, React, and Vue. ### What features does Stencil add to Web Components?[​](https://stenciljs.com/docs/next/faq#what-features-does-stencil-add-to-web-components "Direct link to What features does Stencil add to Web Components?") Web Components by themselves weren't enough to provide a quality development experience. Building fast web apps required innovations that were previously locked up inside traditional web frameworks. Stencil was built to pull these features out of traditional frameworks and bring them to the fast emerging Web Component standard. Compared to using Web Components directly, Stencil provides extra APIs that make writing fast components simpler. APIs like Virtual DOM, JSX, and async rendering make fast, powerful components easy to create, while still maintaining 100% compatibility with Web Components. ### What browsers can support Stencil components?[​](https://stenciljs.com/docs/next/faq#what-browsers-can-support-stencil-components "Direct link to What browsers can support Stencil components?") Stencil works on modern browsers. [Learn more about browser support](https://stenciljs.com/docs/next/support-policy#browser-support) . Stencil Project[​](https://stenciljs.com/docs/next/faq#stencil-project "Direct link to Stencil Project") --------------------------------------------------------------------------------------------------------- ### How do I get involved?[​](https://stenciljs.com/docs/next/faq#how-do-i-get-involved "Direct link to How do I get involved?") Stencil is an open source project, and we encourage you to contribute. You can start by creating issues on GitHub, submitting feature requests, and helping to replicate bugs. If you’re interested in contributing, please see our [Contributor Guide](https://github.com/ionic-team/stencil/blob/main/.github/CONTRIBUTING.md) and check out our [issue tracker](https://github.com/ionic-team/stencil/issues) . ### Is Stencil open source?[​](https://stenciljs.com/docs/next/faq#is-stencil-open-source "Direct link to Is Stencil open source?") Yes, Stencil is open source and its source code can be [found on GitHub](https://github.com/ionic-team/stencil) . Contributions are welcomed from the community. ### Which software license does Stencil use?[​](https://stenciljs.com/docs/next/faq#which-software-license-does-stencil-use "Direct link to Which software license does Stencil use?") Stencil’s software [license is MIT](https://github.com/ionic-team/stencil/blob/main/LICENSE.md) . ### Who works on Stencil?[​](https://stenciljs.com/docs/next/faq#who-works-on-stencil "Direct link to Who works on Stencil?") The majority of the development is done by engineers at [Ionic](https://github.com/ionic-team/ionic) . If you’re excited about Stencil, we encourage you to join the community and contribute! Best place to start is on the [discord channel](https://chat.stenciljs.com/) . Contents -------- * [Introduction](https://stenciljs.com/docs/next/faq#introduction) * [What is Stencil?](https://stenciljs.com/docs/next/faq#what-is-stencil) * [What does Stencil do?](https://stenciljs.com/docs/next/faq#what-does-stencil-do) * [Who is Stencil for?](https://stenciljs.com/docs/next/faq#who-is-stencil-for) * [Who makes Stencil?](https://stenciljs.com/docs/next/faq#who-makes-stencil) * [Why was Stencil created?](https://stenciljs.com/docs/next/faq#why-was-stencil-created) * [Who uses Stencil?](https://stenciljs.com/docs/next/faq#who-uses-stencil) * [How does Stencil compare to traditional frameworks?](https://stenciljs.com/docs/next/faq#how-does-stencil-compare-to-traditional-frameworks) * [Why is Stencil considered framework-agnostic?](https://stenciljs.com/docs/next/faq#why-is-stencil-considered-framework-agnostic) * [What does Stencil provide?](https://stenciljs.com/docs/next/faq#what-does-stencil-provide) * [Does Stencil have a component library?](https://stenciljs.com/docs/next/faq#does-stencil-have-a-component-library) * [Is Stencil a framework?](https://stenciljs.com/docs/next/faq#is-stencil-a-framework) * [Does Stencil come with a testing framework?](https://stenciljs.com/docs/next/faq#does-stencil-come-with-a-testing-framework) * [Technology](https://stenciljs.com/docs/next/faq#technology) * [Why does Stencil use web components?](https://stenciljs.com/docs/next/faq#why-does-stencil-use-web-components) * [How is Stencil able to optimize component file size and startup?](https://stenciljs.com/docs/next/faq#how-is-stencil-able-to-optimize-component-file-size-and-startup) * [What template syntax does Stencil use?](https://stenciljs.com/docs/next/faq#what-template-syntax-does-stencil-use) * [Can Stencil components be lazy loaded?](https://stenciljs.com/docs/next/faq#can-stencil-components-be-lazy-loaded) * [Why are Stencil components written with TypeScript?](https://stenciljs.com/docs/next/faq#why-are-stencil-components-written-with-typescript) * [What dependencies does the Stencil runtime have?](https://stenciljs.com/docs/next/faq#what-dependencies-does-the-stencil-runtime-have) * [Can data be passed to Web Components?](https://stenciljs.com/docs/next/faq#can-data-be-passed-to-web-components) * [What technology is Stencil built with?](https://stenciljs.com/docs/next/faq#what-technology-is-stencil-built-with) * [Capabilities](https://stenciljs.com/docs/next/faq#capabilities) * [Where can Stencil components be used?](https://stenciljs.com/docs/next/faq#where-can-stencil-components-be-used) * [What are the limitations of Web Components?](https://stenciljs.com/docs/next/faq#what-are-the-limitations-of-web-components) * [What are framework bindings?](https://stenciljs.com/docs/next/faq#what-are-framework-bindings) * [What features does Stencil add to Web Components?](https://stenciljs.com/docs/next/faq#what-features-does-stencil-add-to-web-components) * [What browsers can support Stencil components?](https://stenciljs.com/docs/next/faq#what-browsers-can-support-stencil-components) * [Stencil Project](https://stenciljs.com/docs/next/faq#stencil-project) * [How do I get involved?](https://stenciljs.com/docs/next/faq#how-do-i-get-involved) * [Is Stencil open source?](https://stenciljs.com/docs/next/faq#is-stencil-open-source) * [Which software license does Stencil use?](https://stenciljs.com/docs/next/faq#which-software-license-does-stencil-use) * [Who works on Stencil?](https://stenciljs.com/docs/next/faq#who-works-on-stencil) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/reference/faq.md) --- # Plugin Config | Stencil [Skip to main content](https://stenciljs.com/docs/next/plugins#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/plugins) ** (v4.35). Version: Next On this page Stencil plugins[​](https://stenciljs.com/docs/next/plugins#stencil-plugins "Direct link to Stencil plugins") ------------------------------------------------------------------------------------------------------------- By default, Stencil does not come with `Sass` or `PostCSS` support. However, either can be added using the `plugins` array. import { Config } from '@stencil/core';import { sass } from '@stencil/sass';export const config: Config = { plugins: [ sass() ]}; Rollup plugins[​](https://stenciljs.com/docs/next/plugins#rollup-plugins "Direct link to Rollup plugins") ---------------------------------------------------------------------------------------------------------- The `rollupPlugins` config can be used to add your own [Rollup](https://rollupjs.org/) plugins. Under the hood, stencil ships with some built-in plugins including `node-resolve` and `commonjs`, since the execution order of rollup plugins is important, stencil provides an API to inject custom plugin **before node-resolve** and after **commonjs transform**: export const config = { rollupPlugins: { before: [ // Plugins injected before rollupNodeResolve() resolvePlugin() ], after: [ // Plugins injected after commonjs() nodePolyfills() ] }} ### Related Plugins[​](https://stenciljs.com/docs/next/plugins#related-plugins "Direct link to Related Plugins") * [@stencil/sass](https://www.npmjs.com/package/@stencil/sass) * [@stencil-community/postcss](https://www.npmjs.com/package/@stencil-community/postcss) * [@stencil-community/less](https://www.npmjs.com/package/@stencil-community/less) * (Deprecated) [@stencil/stylus](https://www.npmjs.com/package/@stencil/stylus) Node Polyfills[​](https://stenciljs.com/docs/next/plugins#node-polyfills "Direct link to Node Polyfills") ---------------------------------------------------------------------------------------------------------- See the [Node Polyfills in Module bundling](https://stenciljs.com/docs/next/module-bundling#node-polyfills) for other examples. Contents -------- * [Stencil plugins](https://stenciljs.com/docs/next/plugins#stencil-plugins) * [Rollup plugins](https://stenciljs.com/docs/next/plugins#rollup-plugins) * [Related Plugins](https://stenciljs.com/docs/next/plugins#related-plugins) * [Node Polyfills](https://stenciljs.com/docs/next/plugins#node-polyfills) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/config/plugins.md) --- # Stencil Output Targets | Stencil [Skip to main content](https://stenciljs.com/docs/next/output-targets#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/output-targets) ** (v4.35). Version: Next On this page One of the more powerful features of the compiler is its ability to generate various builds depending on _"how"_ the components are going to be used. Stencil is able to take an app's source and compile it to numerous targets, such as a webapp to be deployed on an http server, as a third-party component lazy-loaded library to be distributed on [npm](https://www.npmjs.com/) , or a vanilla custom elements bundle. By default, Stencil apps have an output target type of `www`, which is best suited for a webapp. Output Target Types:[​](https://stenciljs.com/docs/next/output-targets#output-target-types "Direct link to Output Target Types:") ---------------------------------------------------------------------------------------------------------------------------------- * [`dist`: Distribution](https://stenciljs.com/docs/next/distribution) * [`www`: Website](https://stenciljs.com/docs/next/www) * [`dist-custom-elements`: Custom Elements](https://stenciljs.com/docs/next/custom-elements) Example:[​](https://stenciljs.com/docs/next/output-targets#example "Direct link to Example:") ---------------------------------------------------------------------------------------------- import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'dist' }, { type: 'www' } ]}; Primary Package Output Target Validation[​](https://stenciljs.com/docs/next/output-targets#primary-package-output-target-validation "Direct link to Primary Package Output Target Validation") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If `validatePrimaryPackageOutputTarget: true` is set in your project's [Stencil config](https://stenciljs.com/docs/next/config#validateprimarypackageoutputtarget) Stencil will attempt to validate certain fields in your `package.json` that correspond with the generated distribution code. Because Stencil can output many different formats from a single project, it can only validate that the `package.json` has field values that align with one of the specified output targets in your project's config. So, Stencil allows you to designate which output target should be used for this validation and thus which will be the default distribution when bundling your project. This behavior only affects a small subset of output targets so a flag exists on the following targets that are eligible for this level of validation: `dist`, `dist-types`, `dist-collection`, and `dist-custom-elements`. For any of these output targets, you can configure the target to be validated as follows: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { ..., outputTargets: [ { type: 'dist', // This flag is what tells Stencil to use this target for validation isPrimaryPackageOutputTarget: true, ... }, ... ], // If this is not set, Stencil will not validate any targets validatePrimaryPackageOutputTarget: true,}; note Stencil can only validate one of these output targets for your build. If multiple output targets are marked for validation, Stencil will use the first designated target in the array and ignore all others. Contents -------- * [Output Target Types:](https://stenciljs.com/docs/next/output-targets#output-target-types) * [Example:](https://stenciljs.com/docs/next/output-targets#example) * [Primary Package Output Target Validation](https://stenciljs.com/docs/next/output-targets#primary-package-output-target-validation) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/output-targets/01-overview.md) --- # Components without a Framework | Stencil [Skip to main content](https://stenciljs.com/docs/next/javascript#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/javascript) ** (v4.35). Version: Next On this page Integrating a component built with Stencil to a project without a JavaScript framework is straight forward. If you're using a simple HTML page, you can add your component via a script tag. For example, if we published a component to npm, we could load the component through a CDN like this: Alternatively, if you wanted to take advantage of ES Modules, you could include the components using an import statement. Passing object props from a non-JSX element[​](https://stenciljs.com/docs/next/javascript#passing-object-props-from-a-non-jsx-element "Direct link to Passing object props from a non-JSX element") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Setting the prop manually[​](https://stenciljs.com/docs/next/javascript#setting-the-prop-manually "Direct link to Setting the prop manually") import { Prop } from '@stencil/core';export class TodoList { @Prop() myObject: object; @Prop() myArray: Array;} ### Watching props changes[​](https://stenciljs.com/docs/next/javascript#watching-props-changes "Direct link to Watching props changes") import { Prop, State, Watch } from '@stencil/core';export class TodoList { @Prop() myObject: string; @Prop() myArray: string; @State() myInnerObject: object; @State() myInnerArray: Array; componentWillLoad() { this.parseMyObjectProp(this.myObject); this.parseMyArrayProp(this.myArray); } @Watch('myObject') parseMyObjectProp(newValue: string) { if (newValue) this.myInnerObject = JSON.parse(newValue); } @Watch('myArray') parseMyArrayProp(newValue: string) { if (newValue) this.myInnerArray = JSON.parse(newValue); }} Contents -------- * [Passing object props from a non-JSX element](https://stenciljs.com/docs/next/javascript#passing-object-props-from-a-non-jsx-element) * [Setting the prop manually](https://stenciljs.com/docs/next/javascript#setting-the-prop-manually) * [Watching props changes](https://stenciljs.com/docs/next/javascript#watching-props-changes) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/docs/framework-integration/javascript.md) --- # Build Constants | Stencil [Skip to main content](https://stenciljs.com/docs/v3/build-variables#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/build-variables) ** (v4.35). Version: v3 On this page Build Constants in Stencil allow you to run specific code only when Stencil is running in development mode. This code is stripped from your bundles when doing a production build, therefore keeping your bundles as small as possible. ### Using Build Constants[​](https://stenciljs.com/docs/v3/build-variables#using-build-constants "Direct link to Using Build Constants") Lets dive in and look at an example of how to use our build constants: import { Component, Build } from '@stencil/core';@Component({ tag: 'stencil-app', styleUrl: 'stencil-app.scss'})export class StencilApp { componentDidLoad() { if (Build.isDev) { console.log('im in dev mode'); } else { console.log('im running in production'); } if (Build.isBrowser) { console.log('im in the browser'); } else { console.log('im in prerendering (server)'); } }} As you can see from this example, we just need to import `Build` from `@stencil/core` and then we can use the `isDev` constant to detect when we are running in dev mode or production mode. ### Use Cases[​](https://stenciljs.com/docs/v3/build-variables#use-cases "Direct link to Use Cases") Some use cases we have come up with are: * Diagnostics code that runs in dev to make sure logic is working like you would expect * `console.log()`'s that may be useful for debugging in dev mode but that you don't want to ship * Disabling auth checks when in dev mode Contents -------- * [Using Build Constants](https://stenciljs.com/docs/v3/build-variables#using-build-constants) * [Use Cases](https://stenciljs.com/docs/v3/build-variables#use-cases) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v3/build-variables.md) --- # Prerender Config | Stencil [Skip to main content](https://stenciljs.com/docs/next/prerender-config#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is unreleased documentation for Stencil **Next** version. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/prerender-config) ** (v4.35). Version: Next On this page As of `1.13.0`, the optional prerender config can be used while prerendering a `www` output target. The `prerender.config.ts` file can further update the parsed document of each page, before it is serialized to HTML. Within `stencil.config.ts`, set the path to the prerendering config file path using the `prerenderConfig` property, such as: import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'www', baseUrl: 'https://stenciljs.com/', prerenderConfig: './prerender.config.ts', } ]}; Next, inside of the `prerender.config.ts` file, it should export a `config` object using the `PrerenderConfig` interface. import { PrerenderConfig } from '@stencil/core';export const config: PrerenderConfig = { ...}; | Config | Description | Default | | --- | --- | --- | | `afterHydrate(document, url)` | Run after each `document` is hydrated, but before it is serialized into an HTML string. Hook is passed the `document` and its `URL`. | | | `beforeHydrate(document, url)` | Run before each `document` is hydrated. Hook is passed the `document` it's `URL`. | | | `afterSerializeTemplate(html)` | Runs after the template Document object has serialize into an HTML formatted string. Returns an HTML string to be used as the base template for all prerendered pages. | | | `beforeSerializeTemplate(document)` | Runs before the template Document object is serialize into an HTML formatted string. Returns the Document to be serialized which will become the base template html for all prerendered pages. | | | `canonicalUrl(url)` | A hook to be used to generate the canonical `` tag which goes in the `` of every prerendered page. Returning `null` will not add a canonical url tag to the page. | | | `crawlUrls` | While prerendering, crawl same-origin URLs found within `` elements. | `true` | | `entryUrls` | URLs to start the prerendering from. By default the root URL of `/` is used. | `['/']` | | `filterAnchor(attrs, base)` | Return `true` the given `` element should be crawled or not. | | | `filterUrl(url, base)` | Return `true` if the given URL should be prerendered or not. | | | `filePath(url, filePath)` | Returns the file path which the prerendered HTML content should be written to. | | | `hydrateOptions(url)` | Returns the hydrate options to use for each individual prerendered page. | | | `loadTemplate(filePath)` | Returns the template file's content. The template is the base HTML used for all prerendered pages. | | | `normalizeUrl(href, base)` | Used to normalize the page's URL from a given a string and the current page's base URL. Largely used when reading an anchor's `href` attribute value and normalizing it into a `URL`. | | | `staticSite` | Static Site Generated (SSG). Does not include Stencil's client-side JavaScript, custom elements or preload modules. | `false` | | `trailingSlash` | If the prerendered URLs should have a trailing "/"" or not | `false` | Individual Page Hydrate Options[​](https://stenciljs.com/docs/next/prerender-config#individual-page-hydrate-options "Direct link to Individual Page Hydrate Options") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Beyond settings for the entire prerendering process with `prerender.config.ts`, you can also set individual hydrate options per each page. The `hydrateOptions(url)` hook can be used to further configure each page. Below is an example of the prerender config with the `hydrateOptions()` hook, which returns options for each page. import { PrerenderConfig } from '@stencil/core';export const config: PrerenderConfig = { hydrateOptions(url) { return { prettyHtml: true }; }}; | Option | Description | Default | | --- | --- | --- | | `addModulePreloads` | Adds `` for modules that will eventually be requested. | `true` | | `approximateLineWidth` | Sets an approximate line width the HTML should attempt to stay within. Note that this is "approximate", in that HTML may often not be able to be split at an exact line width. Additionally, new lines created is where HTML naturally already has whitespace, such as before an attribute or spaces between words. | `100` | | `canonicalUrl` | Sets the `href` attribute on the `` tag within the ``. If the value is not defined it will ensure a canonical link tag is no included in the ``. | | | `clientHydrateAnnotations` | Include the HTML comments and attributes used by the client-side JavaScript to read the structure of the HTML and rebuild each component. | `true` | | `constrainTimeouts` | Constrain `setTimeout()` to 1ms, but still async. Also only allows `setInterval()` to fire once, also constrained to 1ms. | `true` | | `cookie` | Sets `document.cookie`. | | | `direction` | Sets the `dir` attribute on the top level ``. | | | `excludeComponents` | Component tag names listed here will not be prerendered, nor will hydrated on the client-side. Components listed here will be ignored as custom elements and treated no differently than a `
`. | | | `inlineExternalStyleSheets` | External stylesheets from `` are instead inlined into ` `) ctx.body = res}) Please note that Stencil injects scoped component styles immediately after `` tags with a `rel="preconnect"` attribute, but before your custom styles. This setup allows you to define custom styles for your components effectively. #### hydrateDocument Options[​](https://stenciljs.com/docs/v4.33/hydrate-app#hydratedocument-options "Direct link to hydrateDocument Options") * `canonicalUrl` - string * `constrainTimeouts` - boolean * `clientHydrateAnnotations` - boolean * `cookie` - string * `direction` - string * `language` - string * `maxHydrateCount` - number * `referrer` - string * `removeScripts` - boolean * `removeUnusedStyles` - boolean * `resourcesUrl` - string * `timeout` - number * `title` - string * `url` - string * `userAgent` - string ### renderToString[​](https://stenciljs.com/docs/v4.33/hydrate-app#rendertostring "Direct link to renderToString") The hydrate app also has a `renderToString` function that takes an HTML string and returns a promise of `HydrateResults`. The optional second parameter is a config object that can alter the output of the markup. Like `hydrateDocument`, the hydrated HTML can be found under the `html` property. _Example taken from Ionic Core_ const results = await hydrate.renderToString( ``, { fullDocument: false, serializeShadowRoot: 'declarative-shadow-dom', prettyHtml: true, });console.log(results.html);/** * outputs: * ```html * * * * * ``` */ #### renderToString Options[​](https://stenciljs.com/docs/v4.33/hydrate-app#rendertostring-options "Direct link to renderToString Options") ##### `approximateLineWidth`[​](https://stenciljs.com/docs/v4.33/hydrate-app#approximatelinewidth "Direct link to approximatelinewidth") **Type:** `number` Determines when line breaks are being set when serializing the component. ##### `prettyHtml`[​](https://stenciljs.com/docs/v4.33/hydrate-app#prettyhtml "Direct link to prettyhtml") **Default:** `false` **Type:** `boolean` If set to `true` it prettifies the serialized HTML code, intends elements and escapes text nodes. ##### `removeAttributeQuotes`[​](https://stenciljs.com/docs/v4.33/hydrate-app#removeattributequotes "Direct link to removeattributequotes") **Type:** `boolean` **Default:** `false` If set to `true` it removes attribute quotes when possible, e.g. replaces `someAttribute="foo"` to `someAttribute=foo`. ##### `removeEmptyAttributes`[​](https://stenciljs.com/docs/v4.33/hydrate-app#removeemptyattributes "Direct link to removeemptyattributes") **Type:** `boolean` **Default:** `true` If set to `true` it removes attribute that don't have values, e.g. remove `class=""`. ##### `removeHtmlComments`[​](https://stenciljs.com/docs/v4.33/hydrate-app#removehtmlcomments "Direct link to removehtmlcomments") **Type:** `boolean` **Default:** `false` If set to `true` it removes any abundant HTML comments. Stencil still requires to insert hydration comments to be able to reconcile the component. ##### `beforeHydrate`[​](https://stenciljs.com/docs/v4.33/hydrate-app#beforehydrate "Direct link to beforehydrate") **Type:** `(document: Document, url: URL) => | Promise` Allows to modify the document and all its containing components to be modified before the hydration process starts. This allows e.g. to assign properties to the components dynamically: await renderToString(response.body, { beforeHydrate: (doc: Document) => { doc.querySelector(`my-component`).someComplexThing = new Map(...) },}) ##### `afterHydrate`[​](https://stenciljs.com/docs/v4.33/hydrate-app#afterhydrate "Direct link to afterhydrate") **Type:** `(document: Document, url: URL, results: PrerenderUrlResults) => | Promise` Allows to modify the document and all its containing components after the component was rendered in the virtual DOM and before the serialization process starts. ##### `serializeShadowRoot`[​](https://stenciljs.com/docs/v4.33/hydrate-app#serializeshadowroot "Direct link to serializeshadowroot") **Default:** `'declarative-shadow-dom'` **Type:** 'declarative-shadow-dom' | 'scoped' | { 'declarative-shadow-dom'?: string[]; scoped?: string[]; default: 'declarative-shadow-dom' | 'scoped';} | false; Configure how Stencil serializes a component's shadow-root: * `declarative-shadow-dom` - all `shadow: true` components will be rendered with a [Declarative Shadow DOM](https://developer.chrome.com/docs/css-ui/declarative-shadow-dom) . * `scoped` - all `shadow: true` components will be rendered with Stencil's custom scoped behavior; a light-dom tree and single ` *
* * Hello, World! I'm Stencil 'Don't call me a framework' JS *
* * * * ``` */ **Scoped Example:** const results = await hydrate.renderToString( ``, { fullDocument: true, serializeShadowRoot: `scoped`, prettyHtml: true, });console.log(results.html);/** * outputs: * ```html * * * * * * *
* * Hello, World! I'm Stencil 'Don't call me a framework' JS *
*
* * ``` */ ##### `fullDocument`[​](https://stenciljs.com/docs/v4.33/hydrate-app#fulldocument "Direct link to fulldocument") **Type:** `boolean` **Default:** `true` If set to `true`, Stencil will serialize a complete HTML document for a server to respond. If set to `false` it will only render the components within the given template. Contents -------- * [How to Use the Hydrate App](https://stenciljs.com/docs/v4.33/hydrate-app#how-to-use-the-hydrate-app) * [hydrateDocument](https://stenciljs.com/docs/v4.33/hydrate-app#hydratedocument) * [renderToString](https://stenciljs.com/docs/v4.33/hydrate-app#rendertostring) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/guides/hydrate-app.md) --- # Stencil Core CLI API | Stencil [Skip to main content](https://stenciljs.com/docs/cli-api#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page The CLI API can be found at `@stencil/core/cli` and ran by `bin/stencil`. createNodeLogger()[​](https://stenciljs.com/docs/cli-api#createnodelogger "Direct link to createNodeLogger()") --------------------------------------------------------------------------------------------------------------- createNodeLogger(process: any): Logger Creates a "logger", based off of NodeJS APIs, that will be used by the compiler and dev-server. By default the CLI uses this method to create the NodeJS logger. The NodeJS "process" object should be provided as the first argument. createNodeSystem()[​](https://stenciljs.com/docs/cli-api#createnodesystem "Direct link to createNodeSystem()") --------------------------------------------------------------------------------------------------------------- createNodeSystem(process: any): CompilerSystem Creates the "system", based off of NodeJS APIs, used by the compiler. This includes any and all file system reads and writes using NodeJS. The compiler itself is unaware of Node's `fs` module. Other system APIs include any use of `crypto` to hash content. The NodeJS "process" object should be provided as the first argument. parseFlags()[​](https://stenciljs.com/docs/cli-api#parseflags "Direct link to parseFlags()") --------------------------------------------------------------------------------------------- parseFlags(args: string[]): ConfigFlags Used by the CLI to parse command-line arguments into a typed `ConfigFlags` object. This is an example of how it's used internally: `parseFlags(process.argv.slice(2))`. run()[​](https://stenciljs.com/docs/cli-api#run "Direct link to run()") ------------------------------------------------------------------------ run(init: CliInitOptions): Promise Runs the CLI with the given options. This is used by Stencil's default `bin/stencil` file, but can be used externally too. runTask()[​](https://stenciljs.com/docs/cli-api#runtask "Direct link to runTask()") ------------------------------------------------------------------------------------ runTask(process: any, config: Config, task: TaskCommand, sys?: CompilerSystem): Promise Runs individual tasks giving a NodeJS `process`, Stencil `config`, and task command. You can optionally pass in the `sys` that's used by the compiler. See [createNodeSystem()](https://stenciljs.com/docs/cli-api#createnodesystem) for more details. Contents -------- * [createNodeLogger()](https://stenciljs.com/docs/cli-api#createnodelogger) * [createNodeSystem()](https://stenciljs.com/docs/cli-api#createnodesystem) * [parseFlags()](https://stenciljs.com/docs/cli-api#parseflags) * [run()](https://stenciljs.com/docs/cli-api#run) * [runTask()](https://stenciljs.com/docs/cli-api#runtask) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/core/cli-api.md) --- # Stencil Goals and Objectives | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/goals-and-objectives#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/goals-and-objectives) ** (v4.35). Version: v4.34 On this page Stencil aims to combine the best concepts of the most popular frontend frameworks into a compile-time tool rather than run-time tool. It's important to stress that Stencil's goal is to _not_ become or be seen as a "framework", but rather our goal is to provide a great developer experience and tooling expected from a framework, while using web-standards within the browser at run-time. In many cases, Stencil can be used as a drop in replacement for traditional frontend frameworks given the capabilities now available in the browser, though using it as such is certainly not required. Web Standards[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#web-standards "Direct link to Web Standards") --------------------------------------------------------------------------------------------------------------------- Components generated by Stencil in the end are built on top of web components, so they work in any major framework or with no framework at all. Additionally, other standards heavily relied on include ES Modules and dynamic imports which have proven to replace traditional bundlers which add unnecessary complexities and run-time JavaScript. By using web-standards, developers can learn and adopt a standard API documented across the world, rather than custom framework APIs that continue to change. Automatic Optimizations[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#automatic-optimizations "Direct link to Automatic Optimizations") --------------------------------------------------------------------------------------------------------------------------------------------------- There are countless optimizations and tweaks developers must do to improve performance of components and websites. With a compiler, Stencil is able to analyze component code as an input, and generate optimized components as an output. Future-Friendly[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#future-friendly "Direct link to Future-Friendly") --------------------------------------------------------------------------------------------------------------------------- As the world of software development continues to evolve, so too can the compiler. Instead of requiring complete rewrites of components, the compiler can continue to make optimizations using the standard component model as the common input. The compiler allows developers to create future-friendly components, while still staying up-to-date on the latest optimizations without starting over again and again. Additionally, if something changes about any API, the compiler is able to make automatic adjustments and notify the developer exactly what needs to be updated. Run-time Performance[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#run-time-performance "Direct link to Run-time Performance") ------------------------------------------------------------------------------------------------------------------------------------------ Instead of writing custom client-side JavaScript which every user needs to download and parse for the app to work, Stencil instead prefers to use the already amazing APIs built directly within the browser. These APIs include Custom Elements. Tiny API[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#tiny-api "Direct link to Tiny API") ------------------------------------------------------------------------------------------------------ Stencil purposely does not come with a large custom API which needs to be learned and re-learned, but rather heavily relies on, you guessed it, web-standards. Again, our goal is to not create yet-another-framework, but rather provide tooling for developers to generate future-friendly components using APIs already baked within the browser. The smaller the API, the easier to learn, and the less that can be broken. Framework Features During Development[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#framework-features-during-development "Direct link to Framework Features During Development") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you haven't noticed already we think web-standards are great and offer many benefits. While using web-standards without any structure is certainly possible, and there are actually many use-cases where this would be appropriate, we found that as apps and teams scale it quickly becomes difficult to manage. Developers often gravitate to frameworks because of their great tooling, defined structure, and ability to allow developers to build apps quickly. One of the largest goals of Stencil is to be that intersection of having great framework features and first-class tooling during development but generating future-proof web-standard code, rather than custom framework specific code. Wide Browser Support[​](https://stenciljs.com/docs/v4.34/goals-and-objectives#wide-browser-support "Direct link to Wide Browser Support") ------------------------------------------------------------------------------------------------------------------------------------------ For the small minority of browsers that do not support modern browser features and APIs, Stencil will automatically polyfill them on-demand. What this means is that for browsers that already support the feature natively, they will not have to download and parse any unnecessary JavaScript. The great news is that in today's web landscape, most modern APIs are already shipping for what Stencil requires. Contents -------- * [Web Standards](https://stenciljs.com/docs/v4.34/goals-and-objectives#web-standards) * [Automatic Optimizations](https://stenciljs.com/docs/v4.34/goals-and-objectives#automatic-optimizations) * [Future-Friendly](https://stenciljs.com/docs/v4.34/goals-and-objectives#future-friendly) * [Run-time Performance](https://stenciljs.com/docs/v4.34/goals-and-objectives#run-time-performance) * [Tiny API](https://stenciljs.com/docs/v4.34/goals-and-objectives#tiny-api) * [Framework Features During Development](https://stenciljs.com/docs/v4.34/goals-and-objectives#framework-features-during-development) * [Wide Browser Support](https://stenciljs.com/docs/v4.34/goals-and-objectives#wide-browser-support) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.34/introduction/02-goals-and-objectives.md) --- # Stencil Goals and Objectives | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/goals-and-objectives#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/goals-and-objectives) ** (v4.35). Version: v4.33 On this page Stencil aims to combine the best concepts of the most popular frontend frameworks into a compile-time tool rather than run-time tool. It's important to stress that Stencil's goal is to _not_ become or be seen as a "framework", but rather our goal is to provide a great developer experience and tooling expected from a framework, while using web-standards within the browser at run-time. In many cases, Stencil can be used as a drop in replacement for traditional frontend frameworks given the capabilities now available in the browser, though using it as such is certainly not required. Web Standards[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#web-standards "Direct link to Web Standards") --------------------------------------------------------------------------------------------------------------------- Components generated by Stencil in the end are built on top of web components, so they work in any major framework or with no framework at all. Additionally, other standards heavily relied on include ES Modules and dynamic imports which have proven to replace traditional bundlers which add unnecessary complexities and run-time JavaScript. By using web-standards, developers can learn and adopt a standard API documented across the world, rather than custom framework APIs that continue to change. Automatic Optimizations[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#automatic-optimizations "Direct link to Automatic Optimizations") --------------------------------------------------------------------------------------------------------------------------------------------------- There are countless optimizations and tweaks developers must do to improve performance of components and websites. With a compiler, Stencil is able to analyze component code as an input, and generate optimized components as an output. Future-Friendly[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#future-friendly "Direct link to Future-Friendly") --------------------------------------------------------------------------------------------------------------------------- As the world of software development continues to evolve, so too can the compiler. Instead of requiring complete rewrites of components, the compiler can continue to make optimizations using the standard component model as the common input. The compiler allows developers to create future-friendly components, while still staying up-to-date on the latest optimizations without starting over again and again. Additionally, if something changes about any API, the compiler is able to make automatic adjustments and notify the developer exactly what needs to be updated. Run-time Performance[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#run-time-performance "Direct link to Run-time Performance") ------------------------------------------------------------------------------------------------------------------------------------------ Instead of writing custom client-side JavaScript which every user needs to download and parse for the app to work, Stencil instead prefers to use the already amazing APIs built directly within the browser. These APIs include Custom Elements. Tiny API[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#tiny-api "Direct link to Tiny API") ------------------------------------------------------------------------------------------------------ Stencil purposely does not come with a large custom API which needs to be learned and re-learned, but rather heavily relies on, you guessed it, web-standards. Again, our goal is to not create yet-another-framework, but rather provide tooling for developers to generate future-friendly components using APIs already baked within the browser. The smaller the API, the easier to learn, and the less that can be broken. Framework Features During Development[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#framework-features-during-development "Direct link to Framework Features During Development") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you haven't noticed already we think web-standards are great and offer many benefits. While using web-standards without any structure is certainly possible, and there are actually many use-cases where this would be appropriate, we found that as apps and teams scale it quickly becomes difficult to manage. Developers often gravitate to frameworks because of their great tooling, defined structure, and ability to allow developers to build apps quickly. One of the largest goals of Stencil is to be that intersection of having great framework features and first-class tooling during development but generating future-proof web-standard code, rather than custom framework specific code. Wide Browser Support[​](https://stenciljs.com/docs/v4.33/goals-and-objectives#wide-browser-support "Direct link to Wide Browser Support") ------------------------------------------------------------------------------------------------------------------------------------------ For the small minority of browsers that do not support modern browser features and APIs, Stencil will automatically polyfill them on-demand. What this means is that for browsers that already support the feature natively, they will not have to download and parse any unnecessary JavaScript. The great news is that in today's web landscape, most modern APIs are already shipping for what Stencil requires. Contents -------- * [Web Standards](https://stenciljs.com/docs/v4.33/goals-and-objectives#web-standards) * [Automatic Optimizations](https://stenciljs.com/docs/v4.33/goals-and-objectives#automatic-optimizations) * [Future-Friendly](https://stenciljs.com/docs/v4.33/goals-and-objectives#future-friendly) * [Run-time Performance](https://stenciljs.com/docs/v4.33/goals-and-objectives#run-time-performance) * [Tiny API](https://stenciljs.com/docs/v4.33/goals-and-objectives#tiny-api) * [Framework Features During Development](https://stenciljs.com/docs/v4.33/goals-and-objectives#framework-features-during-development) * [Wide Browser Support](https://stenciljs.com/docs/v4.33/goals-and-objectives#wide-browser-support) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/introduction/02-goals-and-objectives.md) --- # Stencil - A Compiler for Web Components | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/introduction#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/introduction) ** (v4.35). Version: v4.33 On this page Stencil: A Web Components Compiler[​](https://stenciljs.com/docs/v4.33/introduction#stencil-a-web-components-compiler "Direct link to Stencil: A Web Components Compiler") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Stencil is a compiler that generates Web Components (more specifically, Custom Elements). Stencil combines the best concepts of the most popular frameworks into a simple build-time tool. Stencil uses TypeScript, JSX, and CSS to create standards-compliant Web Components that can be used to craft high quality component libraries. Web Components generated with Stencil can be used with popular frameworks right out of the box. In addition, Stencil can generate framework-specific wrappers that allow Stencil components to be used with a framework-specific developer experience. Compared with using the [Custom Elements APIs](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) directly, Stencil provides [convenient APIs](https://stenciljs.com/docs/v4.33/api) which make writing fast components simpler. With a Virtual DOM, JSX, and async rendering, it is easy to create fast and powerful components which are still 100% compatible with Web Components standards. In addition to making it easier to author Custom Elements, Stencil also adds a number of key capabilities on top of Web Components, such as prerendering and objects-as-properties (instead of just strings). The developer experience is also tuned, and comes with live reload and a small dev server baked into the compiler. How can I use Stencil?[​](https://stenciljs.com/docs/v4.33/introduction#how-can-i-use-stencil "Direct link to How can I use Stencil?") --------------------------------------------------------------------------------------------------------------------------------------- ### Design Systems & Component Libraries[​](https://stenciljs.com/docs/v4.33/introduction#design-systems--component-libraries "Direct link to Design Systems & Component Libraries") Stencil's primary objective is providing amazing tools for design systems and component libraries. Components as a concept provide similar language for engineers and designers to have productive conversations about design implementation. [Visit the Stencil for Design Systems page to learn more.](https://stenciljs.com/docs/v4.33/design-systems) The History of Stencil[​](https://stenciljs.com/docs/v4.33/introduction#the-history-of-stencil "Direct link to The History of Stencil") ---------------------------------------------------------------------------------------------------------------------------------------- Stencil was originally created by the **[Ionic Framework](http://ionicframework.com/) ** team in order to build faster, more capable components that worked across every major framework. The emergence of Progressive Web Apps as a rapidly growing target for web developers demanded a different approach to web app development performance. With Ionic's classic use of traditional frameworks and bundling techniques, the team was struggling to meet latency and code size demands for Progressive Web Apps that ran equally well on fast and slow networks, across a diversity of platforms and devices. Additionally, framework fragmentation had created a web development interoperability nightmare, where components built for one framework didn't work with another framework. Web Components offered a solution to both problems, pushing more work to the browser for better performance, and targeting a standards-based component model that all frameworks could use. Web Components by themselves, however, weren't enough. Building fast web apps required innovations that were previously locked up inside of traditional web frameworks. Stencil was built to pull these features out of traditional frameworks and bring them to the fast emerging Web Component standard. While Stencil is intended to be used primarily to build design systems and component libraries, these innovations allowed entire applications to be built using only Stencil. Contents -------- * [Stencil: A Web Components Compiler](https://stenciljs.com/docs/v4.33/introduction#stencil-a-web-components-compiler) * [How can I use Stencil?](https://stenciljs.com/docs/v4.33/introduction#how-can-i-use-stencil) * [Design Systems & Component Libraries](https://stenciljs.com/docs/v4.33/introduction#design-systems--component-libraries) * [The History of Stencil](https://stenciljs.com/docs/v4.33/introduction#the-history-of-stencil) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/introduction/01-overview.md) --- # Functional Components | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/functional-components#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/functional-components) ** (v4.35). Version: v4.33 On this page Functional components are quite different to normal Stencil web components because they are a part of Stencil's JSX compiler. A functional component is basically a function that takes an object of props and turns it into JSX. const Hello = props =>

Hello, {props.name}!

; When the JSX transpiler encounters such a component, it will take its attributes, pass them into the function as the `props` object, and replace the component with the JSX that is returned by the function. Functional components also accept a second argument `children`. const Hello = (props, children) => [

Hello, {props.name}

, children]; The JSX transpiler passes all child elements of the component as an array into the function's `children` argument.

I'm a child element.

Stencil provides a `FunctionalComponent` generic type that allows to specify an interface for the component's properties. // Hello.tsximport { FunctionalComponent, h } from '@stencil/core';interface HelloProps { name: string;}export const Hello: FunctionalComponent = ({ name }) => (

Hello, {name}!

); Working with children[​](https://stenciljs.com/docs/v4.33/functional-components#working-with-children "Direct link to Working with children") ---------------------------------------------------------------------------------------------------------------------------------------------- The second argument of a functional component receives the passed children, but in order to work with them, `FunctionalComponent` provides a utils object that exposes a `map()` method to transform the children, and a `forEach()` method to read them. Reading the `children` array is not recommended since the stencil compiler can rename the vNode properties in prod mode. export interface FunctionalUtilities { forEach: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => void) => void; map: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => ChildNode) => VNode[];}export interface ChildNode { vtag?: string | number | Function; vkey?: string | number; vtext?: string; vchildren?: VNode[]; vattrs?: any; vname?: string;} **Example:** export const AddClass: FunctionalComponent = (_, children, utils) => ( utils.map(children, child => ({ ...child, vattrs: { ...child.vattrs, class: `${child.vattrs.class} add-class` } } ))); note When using a functional component in JSX, its name must start with a capital letter. Therefore it makes sense to export it as such. Disclaimer[​](https://stenciljs.com/docs/v4.33/functional-components#disclaimer "Direct link to Disclaimer") ------------------------------------------------------------------------------------------------------------- There are a few major differences between functional components and class components. Since functional components are just syntactic sugar within JSX, they... * aren't compiled into web components, * don't create a DOM node, * don't have a Shadow DOM or scoped styles, * don't have lifecycle hooks, * are stateless. When deciding whether to use functional components, one concept to keep in mind is that often the UI of your application can be a function of its state, i. e., given the same state, it always renders the same UI. If a component has to hold state, deal with events, etc, it should probably be a class component. If a component's purpose is to simply encapsulate some markup so it can be reused across your app, it can probably be a functional component (especially if you're using a component library and thus don't need to style it). caution Stencil does not support re-exporting a functional component from a "barrel file" and dynamically rendering it in another component. This is a [known limitation](https://github.com/ionic-team/stencil/issues/5246) within Stencil. Instead, either use class components and remove the import or import the functional component directly. Contents -------- * [Working with children](https://stenciljs.com/docs/v4.33/functional-components#working-with-children) * [Disclaimer](https://stenciljs.com/docs/v4.33/functional-components#disclaimer) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/components/functional-components.md) --- # Prerender Config | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/prerender-config#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/prerender-config) ** (v4.35). Version: v4.34 On this page As of `1.13.0`, the optional prerender config can be used while prerendering a `www` output target. The `prerender.config.ts` file can further update the parsed document of each page, before it is serialized to HTML. Within `stencil.config.ts`, set the path to the prerendering config file path using the `prerenderConfig` property, such as: import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'www', baseUrl: 'https://stenciljs.com/', prerenderConfig: './prerender.config.ts', } ]}; Next, inside of the `prerender.config.ts` file, it should export a `config` object using the `PrerenderConfig` interface. import { PrerenderConfig } from '@stencil/core';export const config: PrerenderConfig = { ...}; | Config | Description | Default | | --- | --- | --- | | `afterHydrate(document, url)` | Run after each `document` is hydrated, but before it is serialized into an HTML string. Hook is passed the `document` and its `URL`. | | | `beforeHydrate(document, url)` | Run before each `document` is hydrated. Hook is passed the `document` it's `URL`. | | | `afterSerializeTemplate(html)` | Runs after the template Document object has serialize into an HTML formatted string. Returns an HTML string to be used as the base template for all prerendered pages. | | | `beforeSerializeTemplate(document)` | Runs before the template Document object is serialize into an HTML formatted string. Returns the Document to be serialized which will become the base template html for all prerendered pages. | | | `canonicalUrl(url)` | A hook to be used to generate the canonical `` tag which goes in the `` of every prerendered page. Returning `null` will not add a canonical url tag to the page. | | | `crawlUrls` | While prerendering, crawl same-origin URLs found within `
` elements. | `true` | | `entryUrls` | URLs to start the prerendering from. By default the root URL of `/` is used. | `['/']` | | `filterAnchor(attrs, base)` | Return `true` the given `` element should be crawled or not. | | | `filterUrl(url, base)` | Return `true` if the given URL should be prerendered or not. | | | `filePath(url, filePath)` | Returns the file path which the prerendered HTML content should be written to. | | | `hydrateOptions(url)` | Returns the hydrate options to use for each individual prerendered page. | | | `loadTemplate(filePath)` | Returns the template file's content. The template is the base HTML used for all prerendered pages. | | | `normalizeUrl(href, base)` | Used to normalize the page's URL from a given a string and the current page's base URL. Largely used when reading an anchor's `href` attribute value and normalizing it into a `URL`. | | | `staticSite` | Static Site Generated (SSG). Does not include Stencil's client-side JavaScript, custom elements or preload modules. | `false` | | `trailingSlash` | If the prerendered URLs should have a trailing "/"" or not | `false` | Individual Page Hydrate Options[​](https://stenciljs.com/docs/v4.34/prerender-config#individual-page-hydrate-options "Direct link to Individual Page Hydrate Options") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Beyond settings for the entire prerendering process with `prerender.config.ts`, you can also set individual hydrate options per each page. The `hydrateOptions(url)` hook can be used to further configure each page. Below is an example of the prerender config with the `hydrateOptions()` hook, which returns options for each page. import { PrerenderConfig } from '@stencil/core';export const config: PrerenderConfig = { hydrateOptions(url) { return { prettyHtml: true }; }}; | Option | Description | Default | | --- | --- | --- | | `addModulePreloads` | Adds `` for modules that will eventually be requested. | `true` | | `approximateLineWidth` | Sets an approximate line width the HTML should attempt to stay within. Note that this is "approximate", in that HTML may often not be able to be split at an exact line width. Additionally, new lines created is where HTML naturally already has whitespace, such as before an attribute or spaces between words. | `100` | | `canonicalUrl` | Sets the `href` attribute on the `` tag within the ``. If the value is not defined it will ensure a canonical link tag is no included in the ``. | | | `clientHydrateAnnotations` | Include the HTML comments and attributes used by the client-side JavaScript to read the structure of the HTML and rebuild each component. | `true` | | `constrainTimeouts` | Constrain `setTimeout()` to 1ms, but still async. Also only allows `setInterval()` to fire once, also constrained to 1ms. | `true` | | `cookie` | Sets `document.cookie`. | | | `direction` | Sets the `dir` attribute on the top level ``. | | | `excludeComponents` | Component tag names listed here will not be prerendered, nor will hydrated on the client-side. Components listed here will be ignored as custom elements and treated no differently than a `
`. | | | `inlineExternalStyleSheets` | External stylesheets from `` are instead inlined into ` Style Modes[​](https://stenciljs.com/docs/v4.33/styling#style-modes "Direct link to Style Modes") -------------------------------------------------------------------------------------------------- Component Style Modes enable you to create versatile designs for your components by utilizing different styling configurations. This is achieved by assigning the styleUrls property of a component to a collection of style mode names, each linked to their respective CSS files. ### Example: Styling a Button Component[​](https://stenciljs.com/docs/v4.33/styling#example-styling-a-button-component "Direct link to Example: Styling a Button Component") Consider a basic button component that supports both iOS and Material Design aesthetics: Using style modes to style a component @Component({ tag: 'simple-button', styleUrls: { md: './simple-button.md.css', // styles for Material Design ios: './simple-button.ios.css' // styles for iOS },})export class SimpleButton { // ...} In the example above, two different modes are declared. One mode is named `md` (for 'Material Design') and refers back to a Material Design-specific stylesheet. Likewise, the other is named `ios` (for iOS) and references a different stylesheet for iOS-like styling. Both stylesheets are relative paths to the file that declares the component. While we have chosen short names in the above example, there's no limitation to the keys used in the `styleUrls` object. To dictate the style mode (Material Design or iOS) in which the button should be rendered, you must initialize the desired mode before any component rendering occurs. This can be done as follows: import { setMode } from '@stencil/core';setMode(() => 'ios'); // Setting iOS as the default mode for all components The `setMode` function processes all elements, enabling the assignment of modes individually based on specific element attributes. For instance, by assigning the `mode` attribute to a component: You can conditionally set the style mode based on the `mode` property: import { setMode } from '@stencil/core';const defaultMode = 'md'; // Default to Material DesignsetMode((el) => el.getAttribute('mode') || defaultMode); The reason for deciding which mode to apply can be very arbitrary and based on your requirements, using an element property called `mode` is just one example. ### Important Considerations[​](https://stenciljs.com/docs/v4.33/styling#important-considerations "Direct link to Important Considerations") * **Initialization:** Style modes must be defined at the start of the component lifecycle and cannot be changed thereafter. If you like to change the components mode dynamically you will have to re-render it entirely. * **Usage Requirement:** A style mode must be set to ensure the component loads with styles. Without specifying a style mode, the component will not apply any styles. * **Input Validation:** Verify a style mode is supported by a component you are setting it for. Setting an un-supported style mode keeps the component unstyled. * **Querying Style Mode:** To check the current style mode and e.g. provide different functionality based on the mode, use the `getMode` function: import { getMode } from '@stencil/core';const simpleButton = document.queryElement('simple-button')console.log(getMode(simpleButton)); // Outputs the current style mode of component This approach ensures your components are adaptable and can dynamically switch between different styles, enhancing the user experience across various platforms and design preferences. Global styles[​](https://stenciljs.com/docs/v4.33/styling#global-styles "Direct link to Global styles") -------------------------------------------------------------------------------------------------------- While most styles are usually scoped to each component, sometimes it's useful to have styles that are available to all the components in your project. To create styles that are globally available, start by creating a global stylesheet. For example, you can create a folder in your `src` directory called `global` and create a file called `global.css` within that. Most commonly, this file is used to declare CSS custom properties on the root element via the `:root` pseudo-class. This is because styles provided via the `:root` pseudo-class can pass through the shadow boundary. For example, you can define a primary color that all your components can use. :root { --color-primary: blue;} In addition to CSS custom properties, other use cases for a global stylesheet include * Theming: defining CSS variables used across the app * Load fonts with `@font-face` * App wide font-family * CSS resets To make the global styles available to all the components in your project, the `stencil.config.ts` file comes with an optional [`globalStyle` setting](https://stenciljs.com/docs/v4.33/config#globalstyle) that accepts the path to your global stylesheet. export const config: Config = { namespace: 'app', globalStyle: 'src/global/global.css', outputTarget: [ { type: 'www', }, ],}; The compiler will run the same minification, autoprefixing, and plugins over `global.css` and generate an output file for the [`www`](https://stenciljs.com/docs/v4.33/www) and [`dist`](https://stenciljs.com/docs/v4.33/distribution) output targets. The generated file will always have the `.css` extension and be named as the specified `namespace`. In the example above, since the namespace is `app`, the generated global styles file will be located at: `./www/build/app.css`. This file must be manually imported in the `index.html` of your application. ### Constructable Stylesheets[​](https://stenciljs.com/docs/v4.33/styling#constructable-stylesheets "Direct link to Constructable Stylesheets") In addition to being available in the light DOM, global styles are automatically registered to every shadow root via [constructable stylesheets](https://web.dev/constructable-stylesheets/) . This means that your global styles can target and style shadow DOM components directly. This allows you to apply styles to specific component types using the `:host()` pseudo-class with a tag name selector. For example, you can target all instances of a specific component: /* In your global stylesheet */:host(my-button) { --button-border-radius: 8px; display: inline-block;}:host(my-card) { --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); margin: 16px 0;}/* You can also use attribute selectors */:host(my-input[type="password"]) { --input-font-family: monospace;} The `:host()` function allows you to select the host element of a component when it matches the given selector. This is particularly useful for: * Setting default CSS custom properties for specific component types * Applying consistent spacing or layout styles across all instances of a component * Theming components based on their tag names or attributes note The `:host()` selector in global styles will only affect components that use shadow DOM. For scoped components, you should use regular tag selectors in your global styles. Contents -------- * [Shadow DOM](https://stenciljs.com/docs/v4.33/styling#shadow-dom) * [What is the Shadow DOM?](https://stenciljs.com/docs/v4.33/styling#what-is-the-shadow-dom) * [Shadow DOM in Stencil](https://stenciljs.com/docs/v4.33/styling#shadow-dom-in-stencil) * [Styling with the Shadow DOM](https://stenciljs.com/docs/v4.33/styling#styling-with-the-shadow-dom) * [Shadow DOM QuerySelector](https://stenciljs.com/docs/v4.33/styling#shadow-dom-queryselector) * [Shadow DOM Browser Support](https://stenciljs.com/docs/v4.33/styling#shadow-dom-browser-support) * [Scoped CSS](https://stenciljs.com/docs/v4.33/styling#scoped-css) * [CSS Custom Properties](https://stenciljs.com/docs/v4.33/styling#css-custom-properties) * [Customizing Components with Custom Properties](https://stenciljs.com/docs/v4.33/styling#customizing-components-with-custom-properties) * [CSS Parts](https://stenciljs.com/docs/v4.33/styling#css-parts) * [Exportparts](https://stenciljs.com/docs/v4.33/styling#exportparts) * [Style Modes](https://stenciljs.com/docs/v4.33/styling#style-modes) * [Example: Styling a Button Component](https://stenciljs.com/docs/v4.33/styling#example-styling-a-button-component) * [Important Considerations](https://stenciljs.com/docs/v4.33/styling#important-considerations) * [Global styles](https://stenciljs.com/docs/v4.33/styling#global-styles) * [Constructable Stylesheets](https://stenciljs.com/docs/v4.33/styling#constructable-stylesheets) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/components/styling.md) --- # Docs Readme Auto-Generation | Stencil [Skip to main content](https://stenciljs.com/docs/docs-readme#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page Stencil is able to auto-generate `readme.md` files for your components. This can help you to maintain consistently formatted documentation for your components which lives right next to them and renders in GitHub. Setup[​](https://stenciljs.com/docs/docs-readme#setup "Direct link to Setup") ------------------------------------------------------------------------------ To generate markdown files, it is recommended to add the `docs-readme` output target to your Stencil configuration file: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-readme' } ]}; Generating README Files[​](https://stenciljs.com/docs/docs-readme#generating-readme-files "Direct link to Generating README Files") ------------------------------------------------------------------------------------------------------------------------------------ ### Using the Build Command[​](https://stenciljs.com/docs/docs-readme#using-the-build-command "Direct link to Using the Build Command") If your project has a `docs-readme` output target configured in your Stencil configuration file, the Stencil [build command](https://stenciljs.com/docs/cli#stencil-build) is all that's needed to generate README docs: npx stencil build If you're running the build command with the `--watch` flag, your project's README files will automatically update without requiring multiple explicit build commands: npm stencil build --watch info When running the build command with the `--dev` flag, README files will not be generated. This is to prevent unnecessary I/O operations during the development cycle. If you choose not to include a `docs-readme` output target in your Stencil configuration file, use the `--docs` CLI flag as a part of the build command: npx stencil build --docs This will cause the Stencil compiler to perform a one-time build of your entire project, including README files. ### Using the Docs Command[​](https://stenciljs.com/docs/docs-readme#using-the-docs-command "Direct link to Using the Docs Command") As an alternative to the build command, the [docs command](https://stenciljs.com/docs/cli#stencil-docs) can be used to perform a one time generation of the documentation: npx stencil docs Running `stencil docs` will generate documentation for [all documentation output targets](https://stenciljs.com/docs/doc-generation) , not just `docs-readme`. info The `npx stencil docs` command runs with dev mode enabled, which does not run a full build. As a result, documentation that needs to be built first, like CSS styles, will not be generated. You will need to run `npx stencil build --docs` to generate documentation that requires building. README Sections[​](https://stenciljs.com/docs/docs-readme#readme-sections "Direct link to README Sections") ------------------------------------------------------------------------------------------------------------ Most generated markdown content will automatically be generated without requiring any additional configuration. Content is generated based on its Stencil component, rather than requiring you to configure multiple flags. Each section below describes the different types of content Stencil recognizes and will automatically generate. ### Custom Markdown Content[​](https://stenciljs.com/docs/docs-readme#custom-markdown-content "Direct link to Custom Markdown Content") Once you've generated a `readme.md` file, you can add your own markdown content to the file. You may add any content above the following comment in a component's `readme.md`: Custom content goes here! Any custom content placed above this comment will be persisted on subsequent builds of the README file. ### Internal Components[​](https://stenciljs.com/docs/docs-readme#internal-components "Direct link to Internal Components") A Stencil component may be marked as internal to a library using the unofficial JSDoc `@internal` tag. By placing `@internal` in a component's class-level JSDoc it will skip the generation of the README for the component. In the code block below, `@internal` is added to the JSDoc for `MyComponent`: A component with @internal in its JSDoc /** * @internal */@Component({ tag: 'my-component', shadow: true,})export class MyComponent { /* omitted */ } The usage of `@internal` causes no README to be generated for `MyComponent`. If a README already exists for the component, it will not be updated. ### Deprecation Notices[​](https://stenciljs.com/docs/docs-readme#deprecation-notices "Direct link to Deprecation Notices") A Stencil component may be marked as deprecated using the [JSDoc `@deprecated` tag](https://jsdoc.app/tags-deprecated) . By placing `@deprecated` in a component's class-level JSDoc it will cause the generated README to denote the component as deprecated. For a component with the JSDoc: A component with @deprecated in its JSDoc /** * @deprecated since v2.0.0 */@Component({ tag: 'my-component', shadow: true,})export class MyComponent { /* omitted */ } In the code block above, `@deprecated` is added to the JSDoc for `MyComponent`. This causes the generated README to contain: > **[DEPRECATED]** since v2.0.0 The deprecation notice will always begin with `> **[DEPRECATED]**`, followed by the description provided in the JSDoc. In this case, that description is "since v2.0.0". The deprecation notice will be placed after the [custom content](https://stenciljs.com/docs/docs-readme#custom-markdown-content) in the README. If a component is not marked as deprecated, this section will be omitted from the generated README. ### Component Overview[​](https://stenciljs.com/docs/docs-readme#component-overview "Direct link to Component Overview") A Stencil component that has a JSDoc comment on its class component like so: A component with an overview in its JSDoc /** * A simple component for formatting names * * This component will do some neat things! */@Component({ tag: 'my-component', shadow: true,})export class MyComponent { } will generate the following section in your component's README: ## OverviewA simple component for formatting namesThis component will do some neat things! The overview will be placed after the [deprecation notice](https://stenciljs.com/docs/docs-readme#deprecation-notices) section of the README. If a component's JSDoc does not contain an overview, this section will be omitted from the generated README. ### Usage Examples[​](https://stenciljs.com/docs/docs-readme#usage-examples "Direct link to Usage Examples") Usage examples are user-generated markdown files that demonstrate how another developer might use a component. These files are separate from a component's README file, and are placed in a `usage/` directory adjacent to a component's implementation. The content of these files will be added to a `Usage` section of the generated README. This allows you to keep examples right next to the code, making it easy to include them in a documentation site or other downstream consumer(s) of your docs. The example usage file below describes how to use a component defined in `src/components/my-component/my-component.tsx`: src/components/my-component/usage/my-component-usage.md # How to Use `my-component`This component is used to provide a way to greet a user using their first, middle, and last name.This component will properly format the provided name, even when all fields aren't provided:```html``` When the README for `my-component` is regenerated, following will be added to the README: ## Usage### My-component-usage# How to Use `my-component`This component is used to provide a way to greet a user using their first, middle, and last name.This component will properly format the provided name, even when all fields aren't provided:```html``` caution Stencil does not check that your usage examples are up-to-date. If you make any changes to your component's API, you'll need to update your usage examples manually. The usage section will be placed after the [overview section](https://stenciljs.com/docs/docs-readme#component-overview) of the README. If a component's directory does not contain any usage files, this section will be omitted from the generated README. ### @Prop() Details[​](https://stenciljs.com/docs/docs-readme#prop-details "Direct link to @Prop() Details") Usages of Stencil's [`@Prop()` decorator](https://stenciljs.com/docs/properties) are described in a table containing the following information for each usage of `@Prop()`: * **Property**: The name of the property on the TypeScript class. * **Attribute**: The name of the attribute associated with the property name. * **Description**: A description of the property, if one was given in a JSDoc comment for the property. * **Type**: The TypeScript type of the property. * **Default**: The default value of the property. For the following usages of `@Prop()` in a component: export class MyComponent { /** * The first name */ @Prop() first!: string; // the '!' denotes a required property /** * @deprecated since v2.1.0 */ @Prop() middle: string; @Prop() lastName = "Smith"; // ...} The following section will be generated: ## Properties| Property | Attribute | Description | Type | Default || -------------------- | ----------- | ---------------------------------------------------------------------- | -------- | ----------- || `first` _(required)_ | `first` | The first name | `string` | `undefined` || `lastName` | `last-name` | | `string` | `"Smith"` || `middle` | `middle` | **[DEPRECATED]** since v2.1.0

| `string` | `undefined` | The properties section will be placed after the [usage examples section](https://stenciljs.com/docs/docs-readme#usage-examples) of the README. If a component does not use the `@Prop()` decorator, this section will be omitted from the generated README. ### @Event() Details[​](https://stenciljs.com/docs/docs-readme#event-details "Direct link to @Event() Details") Usages of Stencil's [`@Event()` decorator](https://stenciljs.com/docs/events) are described in a table containing the following information for each usage of `@Event()`: * **Event**: The name of the property on the TypeScript class decorated with `@Event()`. * **Description**: A description of the property, if one was given in a JSDoc comment for the property. * **Type**: The TypeScript type of the property. For the following usages of `@Event()` in a component: export class MyComponent { /** * Emitted when an event is completed */ @Event() todoCompleted: EventEmitter; /** * @deprecated */ @Event() todoUndo: EventEmitter; // ...} The following section will be generated: ## Events| Event | Description | Type || --------------- | ---------------------------------------------------------- | --------------------- || `todoCompleted` | Emitted when an event is completed | `CustomEvent` || `todoUndo` | **[DEPRECATED]**

| `CustomEvent` | The events section will be placed after the [@Prop() section](https://stenciljs.com/docs/docs-readme#prop-details) of the README. If a component does not use the `@Event()` decorator, this section will be omitted from the generated README. ### @Method() Details[​](https://stenciljs.com/docs/docs-readme#method-details "Direct link to @Method() Details") Components that use Stencil's [`@Method()` decorator](https://stenciljs.com/docs/methods) will have a section describing each usage `@Method`. Each usage of `@Method` will be documented with its own subsection containing the following: * The method signature will be used as the heading for each subsection * A description of the method will immediately follow, if one was provided in a JSDoc * A 'Parameters' section that contains a table the describes the name, TypeScript type, and description of each parameter of the method * A 'Returns' section that contains the return type of the method, along with a description of the returned value. For the following usages of `@Method()` in a component: export class MyComponent { /** * Scroll by a specified X/Y distance in the component. * * @param x The amount to scroll by on the horizontal axis. * @param y The amount to scroll by on the vertical axis. * @param duration The amount of time to take scrolling by that amount. * @returns the total distance travelled */ @Method() async scrollByPoint(x: number, y: number, duration: number): Promise { /* omitted */ } // ...} The following section will be generated: ## Methods### `scrollByPoint(x: number, y: number, duration: number) => Promise`Scroll by a specified X/Y distance in the component.#### Parameters| Name | Type | Description || ---------- | -------- | ---------------------------------------------------- || `x` | `number` | The amount to scroll by on the horizontal axis. || `y` | `number` | The amount to scroll by on the vertical axis. || `duration` | `number` | The amount of time to take scrolling by that amount. |#### ReturnsType: `Promise`the total distance travelled The methods section will be placed after the [@Event section](https://stenciljs.com/docs/docs-readme#event-details) of the README. If a component does not use the `@Method()` decorator, this section will be omitted from the generated README. ### @slot Details[​](https://stenciljs.com/docs/docs-readme#slot-details "Direct link to @slot Details") A component that uses [slots](https://stenciljs.com/docs/templating-jsx#slots) may describe its slots in the component's JSDoc using the Stencil-specific `@slot` JSDoc tag. The `@slot` tag follows the following format: @slot [slot-name] - [description] where `slot-name` corresponds to the name of the slot in the markup, and `description` describes the usage of the slot. For this JSDoc tag to be read properly, the following is required: 1. Either `slot-name` or `description` must be included. Both may be included though. 2. The '-' separating the two is required. For the default slot, omit the `slot-name`. This information is presented in a table containing the following columns: * **Slot**: The name of the slot. The default slot will have no name/be empty. * **Description**: A description of the slot, if one was given. For the following usages of `@slot()` in a component: /** * @slot - Content is placed between the named slots if provided without a slot. * @slot primary - Content is placed to the left of the main slotted-in text. * @slot secondary - Content is placed to the right of the main slotted-in text. */@Component({ tag: 'my-component', shadow: true,})export class MyComponent { // ... render() { return (
); }} The following table is generated: ## Slots| Slot | Description || ------------- | --------------------------------------------------------------------- || | Content is placed between the named slots if provided without a slot. || `"primary"` | Content is placed to the left of the main slotted-in text. || `"secondary"` | Content is placed to the right of the main slotted-in text. | The slots section will be placed after the [@Method section](https://stenciljs.com/docs/docs-readme#method-details) of the README. If a component's top-level JSDoc does not use `@slot` tags, this section will be omitted from the generated README. ### Shadow Parts[​](https://stenciljs.com/docs/docs-readme#shadow-parts "Direct link to Shadow Parts") A component that uses [CSS shadow parts](https://stenciljs.com/docs/styling#css-parts) may describe the component's shadow parts in the component's JSDoc using the Stencil-specific `@part` JSDoc tag. The `@part` tag follows the following format: @part [part-name] - [description] where `part-name` corresponds to the name of the shadow part in the markup, and `description` describes its usage. For this tag to be read properly, the following is required: 1. Either `part-name` or `description` must be included, although using both is strongly encouraged. 2. The '-' separating the two is required. This information is presented in a table containing the following columns: * **Part**: The name of the shadow part. * **Description**: A description of the shadow part, if one was given. For the following usages of `@part()` in a component: /** * @part label - The label text describing the component. */@Component({ tag: 'my-component', styleUrl: 'my-component.css', shadow: true,})export class MyComponent { // ... render() { return (
); }} The following table will be generated: ## Shadow Parts| Part | Description || ----------------------------------------------------------- | ---------------------------------------- || `"label"` | The label text describing the component. | The shadow parts section will be placed after the [@Slot Details](https://stenciljs.com/docs/docs-readme#slot-details) of the README. If a component's top-level JSDoc does not use `@part` tags, this section will be omitted from the generated README. ### Styling Details[​](https://stenciljs.com/docs/docs-readme#styling-details "Direct link to Styling Details") Styling in CSS files can be documented in Stencil components as well. One use case for documenting styles using Stencil is to note a CSS variable that a component's styling depends on. Using the `@prop` JSDoc in a component's CSS file, Stencil can generate this documentation as well. This information is presented in a table containing the following columns: * **Name**: The name of the custom property. * **Description**: A description of the custom property, if one was given. For the following usages of `@prop` in a component's css file: :host { /** * @prop --border-radius: Border radius of the avatar and inner image */ border-radius: var(--border-radius);} The following table will be generated: ## CSS Custom Properties| Name | Description || ----------------- | ------------------------------------------- || `--border-radius` | Border radius of the avatar and inner image | The styling details section will be placed after the [Shadow Parts Details](https://stenciljs.com/docs/docs-readme#shadow-parts) of the README. If a component's styles does not include styling details, this section will be omitted from the generated README. ### Custom Footers[​](https://stenciljs.com/docs/docs-readme#custom-footers "Direct link to Custom Footers") Removing or customizing the footer can be done by adding a `footer` property to the output target. This string is added to the generated Markdown files without modification, so you can use Markdown syntax in it for rich formatting: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-readme', footer: '*Built with love!*', } ]}; The following footer will be placed at the bottom of your component's README file: *Built with love!* Configuration[​](https://stenciljs.com/docs/docs-readme#configuration "Direct link to Configuration") ------------------------------------------------------------------------------------------------------ ### Specifying the Output Directory[​](https://stenciljs.com/docs/docs-readme#specifying-the-output-directory "Direct link to Specifying the Output Directory") By default, a README file will be generated in the same directory as the component it corresponds to. This behavior can be changed by setting the `dir` property on the output target configuration. Specifying a directory will create the structure `{dir}/{component}/readme.md`. stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-readme', dir: 'output' } ]}; ### Strict Mode[​](https://stenciljs.com/docs/docs-readme#strict-mode "Direct link to Strict Mode") Adding `strict: true` to the output target configuration will cause Stencil to output a warning whenever the project is built with missing documentation. stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-readme', strict: true } ]}; When strict mode is enabled, the following items are checked: 1. `@Prop()` usages must be documented, unless the property is marked as `@deprecated` 2. `@Method()` usages must be documented, unless the method is marked as `@deprecated` 3. `@Event()` usages must be documented, unless the event is marked as `@deprecated` 4. CSS Part usages must be documented ### Controlling README Overwrites[​](https://stenciljs.com/docs/docs-readme#controlling-readme-overwrites "Direct link to Controlling README Overwrites") The `overwriteExisting` property can be added to the output target configuration to control how existing README files are handled when writing to a custom directory (specified via the `dir` property). By default, the README located beside a component is treated as the canonical source of truth for any manually-entered custom content. stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'docs-readme', dir: 'output', overwriteExisting: 'if-missing' } ]}; #### Available Options[​](https://stenciljs.com/docs/docs-readme#available-options "Direct link to Available Options") * `true`: Always overwrite the destination README with the full content from the component's `readme.md` file. * `false` (default): Update only the autogenerated content in the destination README, always preserving any existing custom content found above the autogenerated section. * `'if-missing'`: Write the full README from the component's `readme.md` only if no file currently exists at the destination. #### Example Use Case[​](https://stenciljs.com/docs/docs-readme#example-use-case "Direct link to Example Use Case") Projects that write component README files into a documentation library folder can use the `'if-missing'` option to maintain consistent, idempotent output across local builds and CI environments. This ensures that custom edits to the destination files will be preserved while new files are fully exported when they do not already exist. The `overwriteExisting` option is especially useful for workflows that expect documentation to remain tightly coupled with source code, while allowing flexibility to maintain custom versions of documentation in different parts of a project. Contents -------- * [Setup](https://stenciljs.com/docs/docs-readme#setup) * [Generating README Files](https://stenciljs.com/docs/docs-readme#generating-readme-files) * [Using the Build Command](https://stenciljs.com/docs/docs-readme#using-the-build-command) * [Using the Docs Command](https://stenciljs.com/docs/docs-readme#using-the-docs-command) * [README Sections](https://stenciljs.com/docs/docs-readme#readme-sections) * [Custom Markdown Content](https://stenciljs.com/docs/docs-readme#custom-markdown-content) * [Internal Components](https://stenciljs.com/docs/docs-readme#internal-components) * [Deprecation Notices](https://stenciljs.com/docs/docs-readme#deprecation-notices) * [Component Overview](https://stenciljs.com/docs/docs-readme#component-overview) * [Usage Examples](https://stenciljs.com/docs/docs-readme#usage-examples) * [@Prop() Details](https://stenciljs.com/docs/docs-readme#prop-details) * [@Event() Details](https://stenciljs.com/docs/docs-readme#event-details) * [@Method() Details](https://stenciljs.com/docs/docs-readme#method-details) * [@slot Details](https://stenciljs.com/docs/docs-readme#slot-details) * [Shadow Parts](https://stenciljs.com/docs/docs-readme#shadow-parts) * [Styling Details](https://stenciljs.com/docs/docs-readme#styling-details) * [Custom Footers](https://stenciljs.com/docs/docs-readme#custom-footers) * [Configuration](https://stenciljs.com/docs/docs-readme#configuration) * [Specifying the Output Directory](https://stenciljs.com/docs/docs-readme#specifying-the-output-directory) * [Strict Mode](https://stenciljs.com/docs/docs-readme#strict-mode) * [Controlling README Overwrites](https://stenciljs.com/docs/docs-readme#controlling-readme-overwrites) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/documentation-generation/docs-readme.md) --- # Form-Associated Components | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/form-associated#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/form-associated) ** (v4.35). Version: v4.33 On this page As of v4.5.0, Stencil has support for form-associated custom elements. This allows Stencil components to participate in a rich way in HTML forms, integrating with native browser features for validation and accessibility while maintaining encapsulation and control over their styling and presentation. caution Browser support for the APIs that this feature depends on is still not universal[1](https://stenciljs.com/docs/v4.33/form-associated#user-content-fn-1) and the Stencil team has no plans at present to support or incorporate any polyfills for the browser functionality. Before you ship form-associated Stencil components make sure that the browsers you need to support have shipped the necessary APIs. Creating a Form-Associated Component[​](https://stenciljs.com/docs/v4.33/form-associated#creating-a-form-associated-component "Direct link to Creating a Form-Associated Component") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- A form-associated Stencil component is one which sets the new [`formAssociated`](https://stenciljs.com/docs/v4.33/component#formassociated) option in the argument to the `@Component` decorator to `true`, like so: import { Component } from '@stencil/core';@Component({ tag: 'my-face', formAssociated: true,})export class MyFACE {} This element will now be marked as a form-associated custom element via the [`formAssociated`](https://html.spec.whatwg.org/#custom-elements-face-example) static property, but by itself this is not terribly useful. In order to meaningfully interact with a `
` element that is an ancestor of our custom element we'll need to get access to an [`ElementInternals`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals) object corresponding to our element instance. Stencil provides a decorator, `@AttachInternals`, which does just this, allowing you to decorate a property on your component and bind an `ElementInternals` object to that property which you can then use to interact with the surrounding form. info Under the hood the `AttachInternals` decorator makes use of the very similarly named [`attachInternals`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals) method on `HTMLElement` to associate your Stencil component with an ancestor `` element. During compilation, Stencil will generate code that calls this method at an appropriate point in the component lifecycle for both [lazy](https://stenciljs.com/docs/v4.33/distribution) and [custom elements](https://stenciljs.com/docs/v4.33/custom-elements) builds. A Stencil component using this API to implement a custom text input could look like this: src/components/custom-text-input.tsx import { Component, h, AttachInternals, State } from '@stencil/core';@Component({ tag: 'custom-text-input', shadow: true, formAssociated: true})export class CustomTextInput { @State() value: string; @AttachInternals() internals: ElementInternals; handleChange(event) { this.value = event.target.value; this.internals.setFormValue(event.target.value); } componentWillLoad() { this.internals.setFormValue("a default value"); } render() { return ( this.handleChange(event)} /> ) }} If this component is rendered within a `` element like so:
then it will automatically be linked up to the surrounding form. The `ElementInternals` object found at `this.internals` will have a bunch of methods on it for interacting with that form and getting key information out of it. In our `` example above we use the [`setFormValue`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue) method to set a value in the surrounding form. This will read the `name` attribute off of the element and use it when setting the value, so the value typed by a user into the `input` will added to the form under the `"my-custom-input"` name. This example just scratches the surface, and a great deal more is possible with the `ElementInternals` API, including [setting the element's validity](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setValidity) , reading the validity state of the form, reading other form values, and more. Lifecycle Callbacks[​](https://stenciljs.com/docs/v4.33/form-associated#lifecycle-callbacks "Direct link to Lifecycle Callbacks") ---------------------------------------------------------------------------------------------------------------------------------- Stencil allows developers building form-associated custom elements to define a [standard series of lifecycle callbacks](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions) which enable their components to react dynamically to events in their lifecycle. These could allow fetching data when a form loads, changing styles when a form's `disabled` state is toggled, resetting form data cleanly, and more. ### `formAssociatedCallback`[​](https://stenciljs.com/docs/v4.33/form-associated#formassociatedcallback "Direct link to formassociatedcallback") This callback is called when the browser both associates the element with and disassociates the element from a form element. The function is called with the form element as an argument. This could be used to set an `ariaLabel` when the form is ready to use, like so: src/components/form-associated-cb.tsx import { Component, h, AttachInternals } from '@stencil/core';@Component({ tag: 'form-associated', formAssociated: true,})export class FormAssociatedCmp { @AttachInternals() internals: ElementInternals; formAssociatedCallback(form) { form.ariaLabel = 'formAssociated called'; } render() { return ; }} ### `formDisabledCallback`[​](https://stenciljs.com/docs/v4.33/form-associated#formdisabledcallback "Direct link to formdisabledcallback") This is called whenever the `disabled` state on the element _changes_. This could be used to keep a CSS class in sync with the disabled state, like so: src/components/form-disabled-cb.tsx import { Component, h, State } from '@stencil/core';@Component({ tag: 'form-disabled-cb', formAssociated: true,})export class MyComponent { @State() cssClass: string = ""; formDisabledCallback(disabled: boolean) { if (disabled) { this.cssClass = "background-mode"; } else { this.cssClass = ""; } } render() { return }} ### `formResetCallback`[​](https://stenciljs.com/docs/v4.33/form-associated#formresetcallback "Direct link to formresetcallback") This is called when the form is reset, and should be used to reset the form-associated component's internal state and validation. For example, you could do something like the following: src/components/form-reset-cb.tsx import { Component, h, AttachInternals } from '@stencil/core';@Component({ tag: 'form-reset-cb', formAssociated: true,})export class MyComponent { @AttachInternals() internals: ElementInternals; formResetCallback() { this.internals.setValidity({}); this.internals.setFormValue(""); } render() { return }} ### `formStateRestoreCallback`[​](https://stenciljs.com/docs/v4.33/form-associated#formstaterestorecallback "Direct link to formstaterestorecallback") This method will be called in the event that the browser automatically fills out your form element, an event that could take place in two different scenarios. The first is that the browser can restore the state of an element after navigating or restarting, and the second is that an input was made using a form auto-filling feature. In either case, in order to correctly reset itself your form-associated component will need the previously selected value, but other state may also be necessary. For instance, the form value to be submitted for a date picker component would be a specific date, but in order to correctly restore the component's visual state it might also be necessary to know whether the picker should display a week or month view. The [`setFormValue`](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setFormValue) method on `ElementInternals` provides some support for this use-case, allowing you to submit both a _value_ and a _state_, where the _state_ is not added to the form data sent to the server but could be used for storing some client-specific state. For instance, a pseudocode sketch of a date picker component that correctly restores whether the 'week' or 'month' view is active could look like: src/components/fa-date-picker.tsx import { Component, h, State, AttachInternals } from '@stencil/core';@Component({ tag: 'fa-date-picker', formAssociated: true,})export class MyDatePicker { @State() value: string = ""; @State() view: "weeks" | "months" = "weeks"; @AttachInternals() internals: ElementInternals; onInputChange(e) { e.preventDefault(); const date = e.target.value; this.setValue(date); } setValue(date: string) { // second 'state' parameter is used to store both // the input value (`date`) _and_ the current view this.internals.setFormValue(date, `${date}#${this.view}`); } formStateRestoreCallback(state, _mode) { const [date, view] = state.split("#"); this.view = view; this.setValue(date); } render() { return
Mock Date Picker, mode: {this.view} this.onInputChange(e)}>
}} Note that the `formStateRestoreCallback` also receives a second argument, `mode`, which can be either `"restore"` or `"autocomplete"`, indicating the reason for the form restoration. For more on form restoration, including a complete example, check out [this great blog post on the subject](https://web.dev/articles/more-capable-form-controls#restoring-form-state) . Resources[​](https://stenciljs.com/docs/v4.33/form-associated#resources "Direct link to Resources") ---------------------------------------------------------------------------------------------------- * [WHATWG specification for form-associated custom elements](https://html.spec.whatwg.org/dev/custom-elements.html#form-associated-custom-elements) * [ElementInternals and Form-Associated Custom Elements](https://webkit.org/blog/13711/elementinternals-and-form-associated-custom-elements/) from the WebKit blog * [Web.dev post detailing how form-associated lifecycle callbacks work](https://web.dev/articles/more-capable-form-controls#lifecycle_callbacks) Footnotes[​](https://stenciljs.com/docs/v4.33/form-associated#footnote-label "Direct link to Footnotes") --------------------------------------------------------------------------------------------------------- 1. See [https://caniuse.com/?search=attachInternals](https://caniuse.com/?search=attachInternals) for up-to-date adoption estimates. [↩](https://stenciljs.com/docs/v4.33/form-associated#user-content-fnref-1) Contents -------- * [Creating a Form-Associated Component](https://stenciljs.com/docs/v4.33/form-associated#creating-a-form-associated-component) * [Lifecycle Callbacks](https://stenciljs.com/docs/v4.33/form-associated#lifecycle-callbacks) * [`formAssociatedCallback`](https://stenciljs.com/docs/v4.33/form-associated#formassociatedcallback) * [`formDisabledCallback`](https://stenciljs.com/docs/v4.33/form-associated#formdisabledcallback) * [`formResetCallback`](https://stenciljs.com/docs/v4.33/form-associated#formresetcallback) * [`formStateRestoreCallback`](https://stenciljs.com/docs/v4.33/form-associated#formstaterestorecallback) * [Resources](https://stenciljs.com/docs/v4.33/form-associated#resources) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/components/form-associated.md) --- # Extras Config | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/config-extras#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/config-extras) ** (v4.35). Version: v4.34 On this page The `extras` config contains options to enable new/experimental features in Stencil, add & remove runtime for DOM features that require manipulations to polyfills, etc. For example, not all DOM APIs are fully polyfilled when using the Slot polyfill. Most of these are opt-in, since not all users require the additional runtime. ### appendChildSlotFix[​](https://stenciljs.com/docs/v4.34/config-extras#appendchildslotfix "Direct link to appendChildSlotFix") By default, the slot polyfill does not update `appendChild()` so that it appends new child nodes into the correct child slot like how shadow dom works. This is an opt-in polyfill for those who need it. ### cloneNodeFix[​](https://stenciljs.com/docs/v4.34/config-extras#clonenodefix "Direct link to cloneNodeFix") By default, the runtime does not polyfill `cloneNode()` when cloning a component that uses the slot polyfill. This is an opt-in polyfill for those who need it. ### enableImportInjection[​](https://stenciljs.com/docs/v4.34/config-extras#enableimportinjection "Direct link to enableImportInjection") In some cases, it can be difficult to lazily load Stencil components in a separate project that uses a bundler such as [Vite](https://vitejs.dev/) . Enabling this flag will allow downstream projects that consume a Stencil library and use a bundler such as Vite to lazily load the Stencil library's components. In order for this flag to work: 1. The Stencil library must expose lazy loadable components, such as those created with the [`dist` output target](https://stenciljs.com/docs/v4.34/distribution) 2. The Stencil library must be recompiled with this flag set to `true` This flag works by creating dynamic import statements for every lazily loadable component in a Stencil project. Users of this flag should note that they may see an increase in their bundle size. Defaults to `false`. ### experimentalImportInjection[​](https://stenciljs.com/docs/v4.34/config-extras#experimentalimportinjection "Direct link to experimentalImportInjection") caution This flag has been deprecated in favor of [`enableImportInjection`](https://stenciljs.com/docs/v4.34/config-extras#enableimportinjection) , which provides the same functionality. `experimentalImportInjection` will be removed in a future major version of Stencil. In some cases, it can be difficult to lazily load Stencil components in a separate project that uses a bundler such as [Vite](https://vitejs.dev/) . This is an experimental flag that, when set to `true`, will allow downstream projects that consume a Stencil library and use a bundler such as Vite to lazily load the Stencil library's components. In order for this flag to work: 1. The Stencil library must expose lazy loadable components, such as those created with the [`dist` output target](https://stenciljs.com/docs/v4.34/distribution) 2. The Stencil library must be recompiled with this flag set to `true` This flag works by creating dynamic import statements for every lazily loadable component in a Stencil project. Users of this flag should note that they may see an increase in their bundle size. Defaults to `false`. ### experimentalScopedSlotChanges[​](https://stenciljs.com/docs/v4.34/config-extras#experimentalscopedslotchanges "Direct link to experimentalScopedSlotChanges") This option updates runtime behavior for Stencil's support of slots in **scoped** components to match more closely with the native Shadow DOM behaviors. When set to `true`, the following behaviors will be applied: * Stencil will hide projected nodes that do not have a destination `slot` ([#2778](https://github.com/ionic-team/stencil/issues/2877) ) (since v4.10.0) * The `textContent` getter will return the text content of all nodes located in a slot (since v4.10.0) * The `textContent` setter will overwrite all nodes located in a slot (since v4.10.0) Defaults to `false`. note These behaviors only apply to components using scoped encapsulation! ### experimentalSlotFixes[​](https://stenciljs.com/docs/v4.34/config-extras#experimentalslotfixes "Direct link to experimentalSlotFixes") This option enables all current and future slot-related fixes. When enabled it will enable the following options, overriding their values if they are specified separately: * [`slotChildNodesFix`](https://stenciljs.com/docs/v4.34/config-extras#slotchildnodesfix) * [`scopedSlotTextContentFix`](https://stenciljs.com/docs/v4.34/config-extras#scopedslottextcontentfix) . * [`appendChildSlotFix`](https://stenciljs.com/docs/v4.34/config-extras#appendchildslotfix) * [`cloneNodeFix`](https://stenciljs.com/docs/v4.34/config-extras#clonenodefix) Slot-related fixes to the runtime will be added over the course of Stencil v4, with the intent of making these the default behavior in Stencil v5. When set to `true` fixes for the following issues will be applied: * Elements rendered outside of slot when shadow not enabled [(#2641)](https://github.com/ionic-team/stencil/issues/2641) (since v4.2.0) * A slot gets the attribute hidden when it shouldn't [(#4523)](https://github.com/ionic-team/stencil/issues/4523) (since v4.7.0) * Nested slots mis-ordered when not using Shadow DOM [(#2997)](https://github.com/ionic-team/stencil/issues/2997) (since v4.7.0) * Inconsistent behavior: slot-fb breaks styling of default slot content in component with 'shadow: false' [(#2937)](https://github.com/ionic-team/stencil/issues/2937) (since v4.7.2) * Slot content went missing within dynamic component [(#4284)](https://github.com/ionic-team/stencil/issues/4284) (since v4.8.2) * Slot element loses its parent reference and disappears when its parent is rendered conditionally [(#3913)](https://github.com/ionic-team/stencil/issues/3913) (since v4.8.2) * Failed to execute 'removeChild' on 'Node' [(#3278)](https://github.com/ionic-team/stencil/issues/3278) (since v4.9.0) * React fails to manage children in Stencil slot [(#2259)](https://github.com/ionic-team/stencil/issues/2259) (since v4.9.0) * Slot name is not updated when it is bind to a prop [(#2982)](https://github.com/ionic-team/stencil/issues/2982) (since 4.12.1) * Conditionally rendered slots not working [(#5335)](https://github.com/ionic-team/stencil/issues/5335) (since 4.13.0) note New fixes enabled by this experimental flag are not subject to Stencil's [semantic versioning policy](https://stenciljs.com/docs/v4.34/versioning) . ### lifecycleDOMEvents[​](https://stenciljs.com/docs/v4.34/config-extras#lifecycledomevents "Direct link to lifecycleDOMEvents") Dispatches component lifecycle events. By default these events are not dispatched, but by enabling this to `true` these events can be listened for on `window`. Mainly used for testing. | Event Name | Description | | --- | --- | | `stencil_componentWillLoad` | Dispatched for each component's `componentWillLoad`. | | `stencil_componentWillUpdate` | Dispatched for each component's `componentWillUpdate`. | | `stencil_componentWillRender` | Dispatched for each component's `componentWillRender`. | | `stencil_componentDidLoad` | Dispatched for each component's `componentDidLoad`. | | `stencil_componentDidUpdate` | Dispatched for each component's `componentDidUpdate`. | | `stencil_componentDidRender` | Dispatched for each component's `componentDidRender`. | ### scopedSlotTextContentFix[​](https://stenciljs.com/docs/v4.34/config-extras#scopedslottextcontentfix "Direct link to scopedSlotTextContentFix") An experimental flag that when set to `true`, aligns the behavior of invoking the `textContent` getter/setter on a scoped component to act more like a component that uses the shadow DOM. Specifically, invoking `textContent` on a component will adhere to the return values described in [MDN's article on textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#description) . Defaults to `false`. ### scriptDataOpts[​](https://stenciljs.com/docs/v4.34/config-extras#scriptdataopts "Direct link to scriptDataOpts") caution This option has been deprecated and will be removed in the next major Stencil release. It is possible to assign data to the actual ` Alternatively, if you wanted to take advantage of ES Modules, you could include the components using an import statement. Passing object props from a non-JSX element[​](https://stenciljs.com/docs/v4.33/javascript#passing-object-props-from-a-non-jsx-element "Direct link to Passing object props from a non-JSX element") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Setting the prop manually[​](https://stenciljs.com/docs/v4.33/javascript#setting-the-prop-manually "Direct link to Setting the prop manually") import { Prop } from '@stencil/core';export class TodoList { @Prop() myObject: object; @Prop() myArray: Array;} ### Watching props changes[​](https://stenciljs.com/docs/v4.33/javascript#watching-props-changes "Direct link to Watching props changes") import { Prop, State, Watch } from '@stencil/core';export class TodoList { @Prop() myObject: string; @Prop() myArray: string; @State() myInnerObject: object; @State() myInnerArray: Array; componentWillLoad() { this.parseMyObjectProp(this.myObject); this.parseMyArrayProp(this.myArray); } @Watch('myObject') parseMyObjectProp(newValue: string) { if (newValue) this.myInnerObject = JSON.parse(newValue); } @Watch('myArray') parseMyArrayProp(newValue: string) { if (newValue) this.myInnerArray = JSON.parse(newValue); }} Contents -------- * [Passing object props from a non-JSX element](https://stenciljs.com/docs/v4.33/javascript#passing-object-props-from-a-non-jsx-element) * [Setting the prop manually](https://stenciljs.com/docs/v4.33/javascript#setting-the-prop-manually) * [Watching props changes](https://stenciljs.com/docs/v4.33/javascript#watching-props-changes) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/framework-integration/javascript.md) --- # Events | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/events#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/events) ** (v4.35). Version: v4.34 On this page There is **NOT** such a thing as _stencil events_, instead, Stencil encourages the use of [DOM events](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events) . However, Stencil does provide an API to specify the events a component can emit, and the events a component listens to. It does so with the `Event()` and `Listen()` decorators. Event Decorator[​](https://stenciljs.com/docs/v4.34/events#event-decorator "Direct link to Event Decorator") ------------------------------------------------------------------------------------------------------------- Components can emit data and events using the Event Emitter decorator. To dispatch [Custom DOM events](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events) for other components to handle, use the `@Event()` decorator. import { Event, EventEmitter } from '@stencil/core';...export class TodoList { @Event() todoCompleted: EventEmitter; todoCompletedHandler(todo: Todo) { this.todoCompleted.emit(todo); }} The code above will dispatch a custom DOM event called `todoCompleted`. The `Event(opts: EventOptions)` decorator optionally accepts an options object to shape the behavior of dispatched events. The options and defaults are described below. export interface EventOptions { /** * A string custom event name to override the default. */ eventName?: string; /** * A Boolean indicating whether the event bubbles up through the DOM or not. */ bubbles?: boolean; /** * A Boolean indicating whether the event is cancelable. */ cancelable?: boolean; /** * A Boolean value indicating whether or not the event can bubble across the boundary between the shadow DOM and the regular DOM. */ composed?: boolean;} Example: import { Event, EventEmitter } from '@stencil/core';...export class TodoList { // Event called 'todoCompleted' that is "composed", "cancellable" and it will bubble up! @Event({ eventName: 'todoCompleted', composed: true, cancelable: true, bubbles: true, }) todoCompleted: EventEmitter; todoCompletedHandler(todo: Todo) { const event = this.todoCompleted.emit(todo); if(!event.defaultPrevented) { // if not prevented, do some default handling code } }} note In the case where the Stencil `Event` type conflicts with the native web `Event` type, there are two possible solutions: 1. Import aliasing: import { Event as StencilEvent, EventEmitter } from '@stencil/core';@StencilEvent() myEvent: EventEmitter<{value: string, ev: Event}>; 2. Namespace the native web `Event` type with `globalThis`: @Event() myEvent: EventEmitter<{value: string, ev: globalThis.Event}>; Listen Decorator[​](https://stenciljs.com/docs/v4.34/events#listen-decorator "Direct link to Listen Decorator") ---------------------------------------------------------------------------------------------------------------- The `Listen()` decorator is for listening to DOM events, including the ones dispatched from `@Events`. The event listeners are automatically added and removed when the component gets added or removed from the DOM. In the example below, assume that a child component, `TodoList`, emits a `todoCompleted` event using the `EventEmitter`. import { Listen } from '@stencil/core';...export class TodoApp { @Listen('todoCompleted') todoCompletedHandler(event: CustomEvent) { console.log('Received the custom todoCompleted event: ', event.detail); }} ### Listen's options[​](https://stenciljs.com/docs/v4.34/events#listens-options "Direct link to Listen's options") The `@Listen(eventName, opts?: ListenOptions)` includes a second optional argument that can be used to configure how the DOM event listener is attached. export interface ListenOptions { target?: 'body' | 'document' | 'window'; capture?: boolean; passive?: boolean;} The available options are `target`, `capture` and `passive`: #### target[​](https://stenciljs.com/docs/v4.34/events#target "Direct link to target") Handlers can also be registered for an event other than the host itself. The `target` option can be used to change where the event listener is attached, this is useful for listening to application-wide events. In the example below, we're going to listen for the scroll event, emitted from `window`: @Listen('scroll', { target: 'window' }) handleScroll(ev) { console.log('the body was scrolled', ev); } #### passive[​](https://stenciljs.com/docs/v4.34/events#passive "Direct link to passive") By default, Stencil uses several heuristics to determine if it must attach a `passive` event listener or not. The `passive` option can be used to change the default behavior. Please check out [https://developers.google.com/web/updates/2016/06/passive-event-listeners](https://developers.google.com/web/updates/2016/06/passive-event-listeners) for further information. #### capture[​](https://stenciljs.com/docs/v4.34/events#capture "Direct link to capture") Event listener attached with `@Listen` does not "capture" by default. When a event listener is set to "capture", it means the event will be dispatched during the "capture phase". Check out [https://www.quirksmode.org/js/events\_order.html](https://www.quirksmode.org/js/events_order.html) for further information. @Listen('click', { capture: true }) handleClick(ev) { console.log('click'); } Keyboard events[​](https://stenciljs.com/docs/v4.34/events#keyboard-events "Direct link to Keyboard events") ------------------------------------------------------------------------------------------------------------- For keyboard events, you can use the standard `keydown` event in `@Listen()` and use `event.keyCode` or `event.which` to get the key code, or `event.key` for the string representation of the key. @Listen('keydown')handleKeyDown(ev: KeyboardEvent){ if (ev.key === 'ArrowDown'){ console.log('down arrow pressed') }} More info on event key strings can be found in the [w3c spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values) . Using events in JSX[​](https://stenciljs.com/docs/v4.34/events#using-events-in-jsx "Direct link to Using events in JSX") ------------------------------------------------------------------------------------------------------------------------- Within a stencil compiled application or component you can also bind listeners to events directly in JSX. This works very similar to normal DOM events such as `onClick`. Let's use our TodoList component from above: import { Event, EventEmitter } from '@stencil/core';...export class TodoList { @Event() todoCompleted: EventEmitter; todoCompletedHandler(todo: Todo) { this.todoCompleted.emit(todo); }} We can now listen to this event directly on the component in our JSX using the following syntax: this.someMethod(ev)} /> This property is generated automatically and is prefixed with "on". For example, if the event emitted is called `todoDeleted` the property will be called `onTodoDeleted`: this.someOtherMethod(ev)} /> Listening to events from a non-JSX element[​](https://stenciljs.com/docs/v4.34/events#listening-to-events-from-a-non-jsx-element "Direct link to Listening to events from a non-JSX element") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Contents -------- * [Event Decorator](https://stenciljs.com/docs/v4.34/events#event-decorator) * [Listen Decorator](https://stenciljs.com/docs/v4.34/events#listen-decorator) * [Listen's options](https://stenciljs.com/docs/v4.34/events#listens-options) * [Keyboard events](https://stenciljs.com/docs/v4.34/events#keyboard-events) * [Using events in JSX](https://stenciljs.com/docs/v4.34/events#using-events-in-jsx) * [Listening to events from a non-JSX element](https://stenciljs.com/docs/v4.34/events#listening-to-events-from-a-non-jsx-element) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.34/components/events.md) --- # Store | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/stencil-store#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/stencil-store) ** (v4.35). Version: v4.33 On this page [Store](https://github.com/ionic-team/stencil-store) is a lightweight shared state library by the stencil core team. It implements a simple key/value map that efficiently re-renders components when necessary. * Lightweight * Zero dependencies * Simple API, like a reactive Map * Best performance Installation[​](https://stenciljs.com/docs/v4.33/stencil-store#installation "Direct link to Installation") ----------------------------------------------------------------------------------------------------------- * npm * Yarn * pnpm npm install @stencil/store --save-dev yarn add @stencil/store --dev pnpm add @stencil/store --save-dev Example[​](https://stenciljs.com/docs/v4.33/stencil-store#example "Direct link to Example") -------------------------------------------------------------------------------------------- **store.ts:** import { createStore } from "@stencil/store";const { state, onChange } = createStore({ clicks: 0, seconds: 0, squaredClicks: 0});onChange('clicks', value => { state.squaredClicks = value ** 2;});export default state; **component.tsx:** import { Component, h } from '@stencil/core';import state from '../store';@Component({ tag: 'app-profile',})export class AppProfile { componentWillLoad() { setInterval(() => state.seconds++, 1000); } render() { return (

Seconds: {state.seconds}
Squared Clicks: {state.squaredClicks}

); }}const MyGlobalCounter = () => { return ( );}; API[​](https://stenciljs.com/docs/v4.33/stencil-store#api "Direct link to API") -------------------------------------------------------------------------------- ### `createStore(initialState)`[​](https://stenciljs.com/docs/v4.33/stencil-store#createstoretinitialstate "Direct link to createstoretinitialstate") Create a new store with the given initial state. The type is inferred from `initialState`, or can be passed as the generic type `T`. Returns a `store` object with the following properties. ### `store.state`[​](https://stenciljs.com/docs/v4.33/stencil-store#storestate "Direct link to storestate") The state object is proxied, I.E. you can directly get and set properties and Store will automatically take care of component re-rendering when the state object is changed. ### `store.on(event, listener)`[​](https://stenciljs.com/docs/v4.33/stencil-store#storeonevent-listener "Direct link to storeonevent-listener") Add a listener to the store for a certain action. ### `store.onChange(propName, listener)`[​](https://stenciljs.com/docs/v4.33/stencil-store#storeonchangepropname-listener "Direct link to storeonchangepropname-listener") Add a listener that is called when a specific property changes. ### `store.get(propName)`[​](https://stenciljs.com/docs/v4.33/stencil-store#storegetpropname "Direct link to storegetpropname") Get a property's value from the store. ### `store.set(propName, value)`[​](https://stenciljs.com/docs/v4.33/stencil-store#storesetpropname-value "Direct link to storesetpropname-value") Set a property's value in the store. ### `store.reset()`[​](https://stenciljs.com/docs/v4.33/stencil-store#storereset "Direct link to storereset") Reset the store to its initial state. ### `store.use(...subscriptions)`[​](https://stenciljs.com/docs/v4.33/stencil-store#storeusesubscriptions "Direct link to storeusesubscriptions") Use the given subscriptions in the store. A subscription is an object that defines one or more of the properties `get`, `set` or `reset`. Testing[​](https://stenciljs.com/docs/v4.33/stencil-store#testing "Direct link to Testing") -------------------------------------------------------------------------------------------- Like any global state library, state should be reset between each spec test. Use the `dispose()` API in the `beforeEach` hook. import store from '../store';beforeEach(() => { store.dispose();}); Contents -------- * [Installation](https://stenciljs.com/docs/v4.33/stencil-store#installation) * [Example](https://stenciljs.com/docs/v4.33/stencil-store#example) * [API](https://stenciljs.com/docs/v4.33/stencil-store#api) * [`createStore(initialState)`](https://stenciljs.com/docs/v4.33/stencil-store#createstoretinitialstate) * [`store.state`](https://stenciljs.com/docs/v4.33/stencil-store#storestate) * [`store.on(event, listener)`](https://stenciljs.com/docs/v4.33/stencil-store#storeonevent-listener) * [`store.onChange(propName, listener)`](https://stenciljs.com/docs/v4.33/stencil-store#storeonchangepropname-listener) * [`store.get(propName)`](https://stenciljs.com/docs/v4.33/stencil-store#storegetpropname) * [`store.set(propName, value)`](https://stenciljs.com/docs/v4.33/stencil-store#storesetpropname-value) * [`store.reset()`](https://stenciljs.com/docs/v4.33/stencil-store#storereset) * [`store.use(...subscriptions)`](https://stenciljs.com/docs/v4.33/stencil-store#storeusesubscriptions) * [Testing](https://stenciljs.com/docs/v4.33/stencil-store#testing) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/guides/store.md) --- # Distributing Web Components Built with Stencil | Stencil [Skip to main content](https://stenciljs.com/docs/distribution#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page The `dist` type is to generate the component(s) as a reusable library that can be self-lazy loading, such as [Ionic](https://www.npmjs.com/package/@ionic/core) . When creating a distribution, the project's `package.json` will also have to be updated. However, the generated bundle is tree-shakable, ensuring that only imported components will end up in the build. outputTargets: [ { type: 'dist' }] Config[​](https://stenciljs.com/docs/distribution#config "Direct link to Config") ---------------------------------------------------------------------------------- ### collectionDir[​](https://stenciljs.com/docs/distribution#collectiondir "Direct link to collectionDir") The `collectionDir` config specifies the output directory within the [distribution directory](https://stenciljs.com/docs/distribution#dir) where the transpiled output of Stencil components will be written. This option defaults to `collection` when omitted from a Stencil configuration file. ### dir[​](https://stenciljs.com/docs/distribution#dir "Direct link to dir") The `dir` config specifies the public distribution directory. This directory is commonly the `dist` directory found within [npm packages](https://docs.npmjs.com/getting-started/packages) . This directory is built and rebuilt directly from the source files. Additionally, since this is a build target, all files will be deleted and rebuilt after each build, so it's best to always copy source files into this directory. It's recommended that this directory not be committed to a repository. This option defaults to `dist` when omitted from a Stencil configuration file. ### empty[​](https://stenciljs.com/docs/distribution#empty "Direct link to empty") By default, before each build the `dir` directory will be emptied of all files. To prevent this directory from being emptied, change this value to `false`. This flag defaults to `true` when omitted from a Stencil configuration file. ### isPrimaryPackageOutputTarget[​](https://stenciljs.com/docs/distribution#isprimarypackageoutputtarget "Direct link to isPrimaryPackageOutputTarget") _default: `false`_ If `true`, this output target will be used to validate `package.json` fields for your project's distribution. See the overview of [primary package output target validation](https://stenciljs.com/docs/output-targets#primary-package-output-target-validation) for more information. ### transformAliasedImportPathsInCollection[​](https://stenciljs.com/docs/distribution#transformaliasedimportpathsincollection "Direct link to transformAliasedImportPathsInCollection") _default: `true`_ This option will allow [path aliases](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping) defined in a project's `tsconfig.json` to be transformed into relative paths in the code output under the [collectionDir](https://stenciljs.com/docs/distribution#collectiondir) subdirectory for this output target. This does not affect imports for external packages. An example of path transformation could look something like: // Source codeimport * as utils from '@utils';// Output codeimport * as utils from '../path/to/utils'; tip If using the `dist-collection` output target directly, the same result can be achieved using the [`transformAliasedImportPaths`](https://stenciljs.com/docs/distribution#transformaliasedimportpathsincollection) flag on the target's config. ### esmLoaderPath[​](https://stenciljs.com/docs/distribution#esmloaderpath "Direct link to esmLoaderPath") _default: `/dist/loader`_ Provide a custom path for the ESM loader directory, containing files you can import in an initiation script within your application to register all your components for lazy loading. Read more about the loader directory in the [section below](https://stenciljs.com/docs/distribution#loader) . If you don't use a custom [exports](https://nodejs.org/api/packages.html#exports) map, users would have to import the loader script via: import { defineCustomElements } from 'stencil-library/dist/loader' By setting `esmLoaderPath` to e.g. `../loader` you can shorten or rename the import path to: import { defineCustomElements } from 'stencil-library/loader' Publishing[​](https://stenciljs.com/docs/distribution#publishing "Direct link to Publishing") ---------------------------------------------------------------------------------------------- Next you can publish your library to [Node Package Manager (NPM)](https://www.npmjs.com/) . For more information about setting up the `package.json` file, and publishing, see: [Publishing A Component Library](https://stenciljs.com/docs/publishing) . Loader[​](https://stenciljs.com/docs/distribution#loader "Direct link to Loader") ---------------------------------------------------------------------------------- The `dist` output target generates a loader directory that exports `setNonce`, `applyPolyfills` and `defineCustomElements` helper functions when imported within an ESM context. This allows you to register all components of your library to be used in your project in an application setup script, e.g.: import { applyPolyfills, defineCustomElements, setNonce } from 'stencil-library/loader';// Will set the `nonce` attribute for all scripts/style tags// i.e. will run styleTag.setAttribute('nonce', 'r4nd0m')// Obviously, you should use the nonce generated by your serversetNonce('r4nd0m');applyPolyfills().then(() => { defineCustomElements();}); This is an alternative approach to e.g. loading the components directly through a script tag as mentioned below. Read more about `setNonce` and when to set it in our guide on [Content Security Policy Nonces](https://stenciljs.com/docs/csp-nonce) . Distribution Options[​](https://stenciljs.com/docs/distribution#distribution-options "Direct link to Distribution Options") ---------------------------------------------------------------------------------------------------------------------------- Each output target's form of bundling and distribution has its own pros and cons. Luckily you can just worry about writing good source code for your component. Stencil will handle generating the various bundles and consumers of your library can decide how to apply your components to their external projects. Below are a few of the options. ### Script tag[​](https://stenciljs.com/docs/distribution#script-tag "Direct link to Script tag") * Use a script tag linked to a CDN copy of your published NPM module, for example: ``. * The initial script itself is extremely tiny and does not represent the entire library. It's only a small registry. * You can use any or all components within your library anywhere within that webpage. * It doesn't matter if the actual component was written within the HTML or created with vanilla JavaScript, jQuery, React, etc. * Only the components used on that page will be requested and lazy-loaded. ### Importing the `dist` library using a bundler[​](https://stenciljs.com/docs/distribution#importing-the-dist-library-using-a-bundler "Direct link to importing-the-dist-library-using-a-bundler") * Run `npm install my-name --save` * Add an `import` within the root component: `import my-component`; * Stencil will automatically setup the lazy-loading capabilities for the Stencil library. * Then you can use the element anywhere in your template, JSX, HTML etc. ### Importing the `dist` library into another Stencil app[​](https://stenciljs.com/docs/distribution#importing-the-dist-library-into-another-stencil-app "Direct link to importing-the-dist-library-into-another-stencil-app") * Run `npm install my-name --save` * Add an `import` within the root component: `import my-component`; * Stencil will automatically setup the lazy-loading capabilities for the Stencil library. * Then you can use the element anywhere in your template, JSX, HTML etc. Contents -------- * [Config](https://stenciljs.com/docs/distribution#config) * [collectionDir](https://stenciljs.com/docs/distribution#collectiondir) * [dir](https://stenciljs.com/docs/distribution#dir) * [empty](https://stenciljs.com/docs/distribution#empty) * [isPrimaryPackageOutputTarget](https://stenciljs.com/docs/distribution#isprimarypackageoutputtarget) * [transformAliasedImportPathsInCollection](https://stenciljs.com/docs/distribution#transformaliasedimportpathsincollection) * [esmLoaderPath](https://stenciljs.com/docs/distribution#esmloaderpath) * [Publishing](https://stenciljs.com/docs/distribution#publishing) * [Loader](https://stenciljs.com/docs/distribution#loader) * [Distribution Options](https://stenciljs.com/docs/distribution#distribution-options) * [Script tag](https://stenciljs.com/docs/distribution#script-tag) * [Importing the `dist` library using a bundler](https://stenciljs.com/docs/distribution#importing-the-dist-library-using-a-bundler) * [Importing the `dist` library into another Stencil app](https://stenciljs.com/docs/distribution#importing-the-dist-library-into-another-stencil-app) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/output-targets/dist.md) --- # Internal state | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/state#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/state) ** (v4.35). Version: v4.34 On this page 'State' is a general term that refers to the values and objects that are stored on a class or an instance of a class for use now or in the future. Like a regular TypeScript class, a Stencil component may have one or more internal class members for holding value(s) that make up the component's state. Stencil allows developers to optionally mark class members holding some part of the class's state with the `@State()` decorator to trigger a rerender when the state changes. The State Decorator (`@State`)[​](https://stenciljs.com/docs/v4.34/state#the-state-decorator-state "Direct link to the-state-decorator-state") ----------------------------------------------------------------------------------------------------------------------------------------------- Stencil provides a decorator to trigger a rerender when certain class members change. A component's class members that should trigger a rerender must be decorated using Stencil's `@State()` decorator, like so: // First, we import State from '@stencil/core'import { Component, State, h } from '@stencil/core';@Component({ tag: 'current-time',})export class CurrentTime { // Second, we decorate a class member with @State() // When `currentTime` changes, a rerender will be // triggered @State() currentTime: number = Date.now(); render() { // Within the component's class, its members are // accessed via `this`. This allows us to render // the value stored in `currentTime` const time = new Date(this.currentTime).toLocaleTimeString(); return ( {time} ); }} In the example above, `@State()` is placed before (decorates) the `currentTime` class member, which is a number. This marks `currentTime` so that any time its value changes, the component rerenders. However, the example above doesn't demonstrate the real power of using `@State`. `@State` members are meant to only be updated within a class, which the example above never does after the initial assignment of `currentTime`. This means that our `current-time` component will never rerender! We fix that in the example below to update `current-time` every 1000 milliseconds (1 second): import { Component, State, h } from '@stencil/core';@Component({ tag: 'current-time',})export class CurrentTime { timer: number; // `currentTime` is decorated with `@State()`, // as we need to trigger a rerender when its // value changes to show the latest time @State() currentTime: number = Date.now(); connectedCallback() { this.timer = window.setInterval(() => { // the assignment to `this.currentTime` // will trigger a re-render this.currentTime = Date.now(); }, 1000); } disconnectedCallback() { window.clearInterval(this.timer); } render() { const time = new Date(this.currentTime).toLocaleTimeString(); return ( {time} ); }} The example above makes use of the [connectedCallback() lifecycle method](https://stenciljs.com/docs/v4.34/component-lifecycle#connectedcallback) to set `currentTime` to the value of `Date.now()` every 1000 milliseconds (or, every one second). Because the value of `currentTime` changes every second, Stencil calls the `render` function on `current-time`, which pretty-prints the current time. The example above also makes use of the [disconnectedCallback() lifecycle method](https://stenciljs.com/docs/v4.34/component-lifecycle#disconnectedcallback) to properly clean up the timer that was created using `setInterval` in `connectedCallback()`. This isn't necessary for using `@State`, but is a general good practice when using `setInterval`. When to Use `@State()`?[​](https://stenciljs.com/docs/v4.34/state#when-to-use-state "Direct link to when-to-use-state") ------------------------------------------------------------------------------------------------------------------------ `@State()` should be used for all class members that should trigger a rerender when they change. However, not all internal state might need to be decorated with `@State()`. If you know for sure that the value will either not change or that it does not need to trigger a re-rendering, `@State()` is not necessary. It is considered a 'best practice' to only use `@State()` when absolutely necessary. Revisiting our `current-time` component: import { Component, State, h } from '@stencil/core';@Component({ tag: 'current-time',})export class CurrentTime { // `timer` is not decorated with `@State()`, as // we do not wish to trigger a rerender when its // value changes timer: number; // `currentTime` is decorated with `@State()`, // as we need to trigger a rerender when its // value changes to show the latest time @State() currentTime: number = Date.now(); connectedCallback() { // the assignment to `this.timer` will not // trigger a re-render this.timer = window.setInterval(() => { // the assignment to `this.currentTime` // will trigger a re-render this.currentTime = Date.now(); }, 1000); } disconnectedCallback() { window.clearInterval(this.timer); } render() { const time = new Date(this.currentTime).toLocaleTimeString(); return ( {time} ); }} Examples[​](https://stenciljs.com/docs/v4.34/state#examples "Direct link to Examples") --------------------------------------------------------------------------------------- ### Using `@State()` with `@Listen()`[​](https://stenciljs.com/docs/v4.34/state#using-state-with-listen "Direct link to using-state-with-listen") This example makes use of `@State` and [`@Listen`](https://stenciljs.com/docs/v4.34/events#listen-decorator) decorators. We define a class member called `isOpen` and decorate it with `@State()`. With the use of `@Listen()`, we respond to click events toggling the value of `isOpen`. import { Component, Listen, State, h } from '@stencil/core';@Component({ tag: 'my-toggle-button'})export class MyToggleButton { // `isOpen` is decorated with `@State()`, // changes to it will trigger a rerender @State() isOpen: boolean = true; @Listen('click', { capture: true }) handleClick() { // whenever a click event occurs on // the component, update `isOpen`, // triggering the rerender this.isOpen = !this.isOpen; } render() { return ; }} ### Complex Types[​](https://stenciljs.com/docs/v4.34/state#complex-types "Direct link to Complex Types") For more advanced use cases, `@State()` can be used with a complex type. In the example below, we print a list of `Item` entries. Although we start with zero `Item`s initially, we use the same pattern as we did before to add a new `Item` to `ItemList`'s `items` array once every 2000 milliseconds (2 seconds). Every time a new entry is added to `items`, a rerender occurs: import { Component, State, h } from '@stencil/core';// a user defined, complex type describing an 'Item'type Item = { id: number; description: string,}@Component({ tag: 'item-list',})export class ItemList { // `timer` is not decorated with `@State()`, as // we do not wish to trigger a rerender when its // value changes timer: number; // `items` will trigger a rerender if // the value assigned to the variable changes @State() items: Item[] = []; connectedCallback() { // the assignment to `this.timer` will not // trigger a re-render this.timer = window.setInterval(() => { const newTodo: Item = { description: "Item", id: this.items.length + 1 }; // the assignment to `this.items` will // trigger a re-render. the assignment // using '=' is important here, as we // need that to make sure the rerender // occurs this.items = [...this.items, newTodo]; }, 2000); } disconnectedCallback() { window.clearInterval(this.timer); } render() { return (

To-Do List

    {this.items.map((todo) =>
  • {todo.description} #{todo.id}
  • )}
); }} It's important to note that it's the reassignment of `this.items` that is causing the rerender in `connectedCallback()`: this.items = [...this.items, newTodo]; Mutating the existing reference to `this.items` like in the examples below will not cause a rerender, as Stencil will not know that the contents of the array has changed: // updating `items` either of these ways will not// cause a rerenderthis.items.push(newTodo);this.items[this.items.length - 1] = newTodo; Similar to the examples above, this code sample makes use of the [connectedCallback() lifecycle method](https://stenciljs.com/docs/v4.34/component-lifecycle#connectedcallback) to create a new `Item` and add it to `items` every 2000 milliseconds (every two seconds). The example above also makes use of the [disconnectedCallback() lifecycle method](https://stenciljs.com/docs/v4.34/component-lifecycle#disconnectedcallback) to properly clean up the timer that was created using `setInterval` in `connectedCallback()`. Contents -------- * [The State Decorator (`@State`)](https://stenciljs.com/docs/v4.34/state#the-state-decorator-state) * [When to Use `@State()`?](https://stenciljs.com/docs/v4.34/state#when-to-use-state) * [Examples](https://stenciljs.com/docs/v4.34/state#examples) * [Using `@State()` with `@Listen()`](https://stenciljs.com/docs/v4.34/state#using-state-with-listen) * [Complex Types](https://stenciljs.com/docs/v4.34/state#complex-types) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.34/components/state.md) --- # Server Side Rendering | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/server-side-rendering#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/server-side-rendering) ** (v4.35). Version: v4.33 On this page Stencil provides server-side rendering (SSR) support for React and Vue Output Targets. If you're using frameworks like [Vite](https://vite.dev/) , [Remix](https://remix.run/) , [Next.js](https://nextjs.org/) or [Nuxt](https://nuxt.com/) , Stencil automatically enhances these frameworks to render components on the server using a [Declarative Shadow DOM](https://web.dev/articles/declarative-shadow-dom) or in [scoped mode](https://stenciljs.com/docs/styling#scoped-css) . The first step to enable server side rendering is to generate a hydrate module of your components. Hydrate Module[​](https://stenciljs.com/docs/v4.33/server-side-rendering#hydrate-module "Direct link to Hydrate Module") ------------------------------------------------------------------------------------------------------------------------- The Hydrate Module is a standalone bundle of all your components that uses a JavaScript implementation of various HTML and DOM standards to render Stencil components in a Node.js environment. To create this bundle you have to add `dist-hydrate-script` to your Stencil configuration: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'dist-hydrate-script', dir: './hydrate', }, // ... ]}; This will create the Hydrate Module which you can export separately via: package.json { "name": "component-library", ... "exports": { ... "./hydrate": { "types": "./hydrate/index.d.ts", "import": "./hydrate/index.mjs", "require": "./hydrate/index.js", "default": "./hydrate/index.js" }, ... }, ...} Two SSR Approaches[​](https://stenciljs.com/docs/v4.33/server-side-rendering#two-ssr-approaches "Direct link to Two SSR Approaches") ------------------------------------------------------------------------------------------------------------------------------------- Stencil provides two distinct strategies for server-side rendering, each designed to solve different challenges and use cases. These approaches emerged from the complex nature of rendering Web Components on the server, where traditional browser APIs don't exist. ### Strategy 1: The Compiler Approach (Universal SSR)[​](https://stenciljs.com/docs/v4.33/server-side-rendering#strategy-1-the-compiler-approach-universal-ssr "Direct link to Strategy 1: The Compiler Approach (Universal SSR)") The compiler-based approach, implemented in the `@stencil/ssr` package, works as a build-time plugin that intercepts your code and performs AST (Abstract Syntax Tree) transformations. It transforms components at compile time. #### How It Works[​](https://stenciljs.com/docs/v4.33/server-side-rendering#how-it-works "Direct link to How It Works") 1. **Build-time interception**: The plugin (Vite or Webpack) receives your JSX code after transformation 2. **AST analysis**: Parses JavaScript into an Abstract Syntax Tree to identify Stencil components 3. **Prop analysis**: Analyzes the props being passed to each component 4. **Pre-rendering**: Calls Stencil's hydrate module to render the component server-side 5. **Code replacement**: Replaces the original component with a wrapper containing pre-rendered HTML #### When to Use Compiler-Based SSR[​](https://stenciljs.com/docs/v4.33/server-side-rendering#when-to-use-compiler-based-ssr "Direct link to When to Use Compiler-Based SSR") ✅ **Multiple framework support**: Need to support Vite, Remix, Next.js, and other meta-frameworks ✅ **Performance critical applications**: Where response speed is paramount ✅ **Predictable props**: Components with static or build-time determinable data ✅ **"Set it and forget it" solutions**: Want minimal runtime complexity #### Advantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#advantages "Direct link to Advantages") * **Universal compatibility**: Works with any React meta-framework * **Zero runtime overhead**: No server processing during requests * **Handles deep nesting**: Excellent at rendering complex component compositions * **Clean separation**: Clear distinction between build-time and runtime concerns * **Consistent performance**: Predictable response times #### Disadvantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#disadvantages "Direct link to Disadvantages") * **Static props only**: Cannot resolve dynamic props at compile time (e.g., `prop={calculateValue()}`) * **Build-time configuration required**: Needs plugin setup * **Hydration mismatches**: Still prone to occasional client/server differences ### Strategy 2: The Runtime Approach (Next.js Server Components)[​](https://stenciljs.com/docs/v4.33/server-side-rendering#strategy-2-the-runtime-approach-nextjs-server-components "Direct link to Strategy 2: The Runtime Approach (Next.js Server Components)") The runtime approach leverages Next.js Server Components to perform real-time SSR. When the server encounters a Stencil component, it renders it on-demand during the request cycle. #### How It Works[​](https://stenciljs.com/docs/v4.33/server-side-rendering#how-it-works-1 "Direct link to How It Works") 1. **Component interception**: Next.js hits a Stencil component during server rendering 2. **Prop serialization**: Uses `serializeProperty` to handle complex objects, Maps, Sets, and even `Infinity` 3. **Children transformation**: Attempts to transform React children into strings using `react-dom/server` 4. **Async rendering**: Calls Stencil's `renderToString` (Promise-based) on the server 5. **React node recreation**: Parses resulting HTML back into React nodes using `html-react-parser` #### When to Use Runtime-Based SSR[​](https://stenciljs.com/docs/v4.33/server-side-rendering#when-to-use-runtime-based-ssr "Direct link to When to Use Runtime-Based SSR") ✅ **Next.js commitment**: When you're fully invested in the Next.js ecosystem ✅ **Dynamic values**: Props that are highly dynamic or computed at runtime ✅ **Light DOM access**: Need to include children in server rendering #### Advantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#advantages-1 "Direct link to Advantages") * **Full prop access**: All props available with resolved values at runtime * **Light DOM inclusion**: Can include children during serialization * **Dynamic value support**: Handles runtime-computed values perfectly * **True isomorphic rendering**: Complete server-client parity * **Complex object handling**: Built-in serialization for advanced data types #### Disadvantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#disadvantages-1 "Direct link to Disadvantages") * **Next.js only**: Requires Server Components support * **Dual component management**: Must maintain both client and server wrappers * **Performance overhead**: Runtime serialization adds latency * **Additional Setup**: Requires importing components from a separate export path, e.g. `my-react-components/next` ### Choosing Your Strategy[​](https://stenciljs.com/docs/v4.33/server-side-rendering#choosing-your-strategy "Direct link to Choosing Your Strategy") Here's the battle-tested decision tree from real-world implementation: #### Use the Compiler Approach when:[​](https://stenciljs.com/docs/v4.33/server-side-rendering#use-the-compiler-approach-when "Direct link to Use the Compiler Approach when:") * You need to support multiple frameworks beyond Next.js * Performance is your top priority * Your components have predictable, static props * You want a "set it and forget it" solution * You're building a content-focused site (marketing, docs, blogs) #### Use the Runtime Approach when:[​](https://stenciljs.com/docs/v4.33/server-side-rendering#use-the-runtime-approach-when "Direct link to Use the Runtime Approach when:") * You're committed to Next.js and Server Components * You need full Light DOM access for complex compositions * Your props are highly dynamic or computed at runtime * You're okay with additional complexity for more rendering power * You're building highly interactive, data-driven applications Enable SSR for StencilJS[​](https://stenciljs.com/docs/v4.33/server-side-rendering#enable-ssr-for-stenciljs "Direct link to Enable SSR for StencilJS") ------------------------------------------------------------------------------------------------------------------------------------------------------- For serializing Stencil components on the server, Stencil uses a package called `@stencil/ssr` which you can install via: npm install --save-dev @stencil/ssr It exports compiler plugins for Vite based projects, e.g. Remix or Webpack based ones like Next.js. The plugin requires the following options: #### `module`[​](https://stenciljs.com/docs/v4.33/server-side-rendering#module "Direct link to module") The import of the package that exports all your Stencil React components. It helps the package to understand which components can be server side rendered. #### `from`[​](https://stenciljs.com/docs/v4.33/server-side-rendering#from "Direct link to from") The name of the package that exports all your Stencil React components. Stencil will look up all imports from that package and transforms the statement to use a server side rendered version of the component. #### `hydrateModule`[​](https://stenciljs.com/docs/v4.33/server-side-rendering#hydratemodule "Direct link to hydratemodule") Your generated hydrate module that gives the package the primitives to serialize a given Stencil component. #### `serializeShadowRoot`[​](https://stenciljs.com/docs/v4.33/server-side-rendering#serializeshadowroot "Direct link to serializeshadowroot") **optional** **default: **declarative-shadow-dom**** Configurations on how the components should be rendered on the server, e.g. as Declarative Shadow DOM, as scoped components or as a mixture of both. ### Vite[​](https://stenciljs.com/docs/v4.33/server-side-rendering#vite "Direct link to Vite") If your project is based on the Vite compiler, this includes frameworks like [Remix](https://remix.run/) that are rely on Vite under the hood, you can use the `@stencil/ssr` package to enable SSR support for Stencil components by adding the plugin to the configuration: vite.config.ts import { defineConfig } from 'vite';import { stencilSSR } from '@stencil/ssr';import react from '@vitejs/plugin-react';// https://vite.dev/config/export default defineConfig({ plugins: [ react(), stencilSSR({ module: import('component-library-react'), from: 'component-library-react', hydrateModule: import('component-library/hydrate'), serializeShadowRoot: { 'scoped': ['my-counter'], default: 'declarative-shadow-dom', }, }), ],}) or in case of a Remix project: vite.config.ts import { vitePlugin as remix } from "@remix-run/dev";import { defineConfig } from "vite";import { stencilSSR } from "@stencil/ssr";declare module "@remix-run/node" { interface Future { v3_singleFetch: true; }}export default defineConfig({ plugins: [ remix(), stencilSSR({ module: import('component-library-react'), from: 'component-library-react', hydrateModule: import('component-library/hydrate'), serializeShadowRoot: { 'scoped': ['my-counter'], default: 'declarative-shadow-dom', }, }), ],}); ### Next.js[​](https://stenciljs.com/docs/v4.33/server-side-rendering#nextjs "Direct link to Next.js") When using Stencil with Next.js, you can server-side render (SSR) components in two ways: **at runtime** or **at compile time**. Each approach has its trade-offs, and the best choice depends on your component architecture. * If your components rely heavily on **slots**, the **compiler-based** SSR approach is generally more reliable. * If your components use **dynamically computed attributes**, the **runtime-based** SSR approach is more flexible. #### Runtime-Based SSR[​](https://stenciljs.com/docs/v4.33/server-side-rendering#runtime-based-ssr "Direct link to Runtime-Based SSR") In this method, Stencil serializes the component to a **Declarative Shadow DOM** during runtime, as Next.js renders the component on the server. Since Next.js supports asynchronous server components, this allows Stencil to perform serialization as part of the render process. To enable runtime SSR, set the `hydrateModule` option in your React output target: import { Config } from '@stencil/core';import { reactOutputTarget } from '@stencil/react-output-target';export const config: Config = { namespace: 'component-library', outputTargets: [ reactOutputTarget({ /** * tell Stencil where to generate the `components.ts` and `components.server.ts` files */ outDir: '../component-library-react/src', /** * give Stencil the import name of the hydrate module */ hydrateModule: 'component-library/hydrate', /** * tell the server component where it would import the client version of the components */ clientModule: 'component-library-react', serializeShadowRoot: { /* options */ }, }), ],}; This will generate: * `components.ts` — for use on the client * `components.server.ts` — for server-side rendering If you distribute your React wrapper as a separate package, consider exposing the server entry point via a custom export path in your `package.json`: { "name": "component-library-react", "version": "0.0.0", "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "node": "./dist/components.server.js" }, "./next": { "types": "./dist/components.server.d.ts", "import": "./dist/components.server.js" } }} Now you can use the server-optimized components in your Next.js app: /src/app/page.tsx import { MyComponent } from 'component-library-react/next';export default function Home() { return ( <> ... );} ##### ✅ Advantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#-advantages "Direct link to ✅ Advantages") * All component props are available with their **resolved values** at runtime. * Props can be **computed dynamically** or retrieved from functions: const value = getValueFromAPI();return ; ##### ⚠️ Disadvantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#%EF%B8%8F-disadvantages "Direct link to ⚠️ Disadvantages") * **Nested Stencil components** may fail to render correctly on the server. * Components using slots may confuse Next.js's `BAILOUT_TO_CLIENT_SIDE_RENDERING` template tags as entries #### Compiler-Based SSR[​](https://stenciljs.com/docs/v4.33/server-side-rendering#compiler-based-ssr "Direct link to Compiler-Based SSR") With this approach, the `@stencil/ssr` package pre-processes your application during the build step to wrap and serialize Stencil components for server-side rendering. To enable it, wrap your Next.js configuration using the `stencilSSR()` helper: next.config.js import stencilSSR from '@stencil/ssr/next';/** @type {import('next').NextConfig} */const nextConfig = { // your base config};export default stencilSSR({ module: import('component-library-react'), from: 'component-library-react', hydrateModule: import('component-library/hydrate'), serializeShadowRoot: { scoped: ['my-counter'], default: 'declarative-shadow-dom', },})(nextConfig); > 📌 **Note:** The integration import path is `@stencil/ssr/next`. ##### ✅ Advantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#-advantages-1 "Direct link to ✅ Advantages") * More **reliable SSR** for Stencil components rendered in the **light DOM**. * Avoids hydration mismatch issues commonly seen with client-heavy components. ##### ⚠️ Disadvantages[​](https://stenciljs.com/docs/v4.33/server-side-rendering#%EF%B8%8F-disadvantages-1 "Direct link to ⚠️ Disadvantages") * Since components are pre-rendered at **build time**, **runtime values** (e.g. function calls or dynamic props) are not available: // ✅ Static objects are fineconst staticProp = { key: 'value' };// ❌ Dynamic values will not be resolvedconst runtimeValue = computeAtRuntime();return ; * Components using **slots** may render incorrectly due to internal Next.js behavior, such as injected ` * * * ``` */ **Scoped Example:** const results = await hydrate.renderToString( ``, { fullDocument: true, serializeShadowRoot: `scoped`, prettyHtml: true, });console.log(results.html);/** * outputs: * ```html * * * * * * *
* * Hello, World! I'm Stencil 'Don't call me a framework' JS *
*
* * ``` */ ##### `fullDocument`[​](https://stenciljs.com/docs/hydrate-app#fulldocument "Direct link to fulldocument") **Type:** `boolean` **Default:** `true` If set to `true`, Stencil will serialize a complete HTML document for a server to respond. If set to `false` it will only render the components within the given template. Contents -------- * [How to Use the Hydrate App](https://stenciljs.com/docs/hydrate-app#how-to-use-the-hydrate-app) * [hydrateDocument](https://stenciljs.com/docs/hydrate-app#hydratedocument) * [renderToString](https://stenciljs.com/docs/hydrate-app#rendertostring) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/guides/hydrate-app.md) --- # Plugin Config | Stencil [Skip to main content](https://stenciljs.com/docs/plugins#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page Stencil plugins[​](https://stenciljs.com/docs/plugins#stencil-plugins "Direct link to Stencil plugins") -------------------------------------------------------------------------------------------------------- By default, Stencil does not come with `Sass` or `PostCSS` support. However, either can be added using the `plugins` array. import { Config } from '@stencil/core';import { sass } from '@stencil/sass';export const config: Config = { plugins: [ sass() ]}; Rollup plugins[​](https://stenciljs.com/docs/plugins#rollup-plugins "Direct link to Rollup plugins") ----------------------------------------------------------------------------------------------------- The `rollupPlugins` config can be used to add your own [Rollup](https://rollupjs.org/) plugins. Under the hood, stencil ships with some built-in plugins including `node-resolve` and `commonjs`, since the execution order of rollup plugins is important, stencil provides an API to inject custom plugin **before node-resolve** and after **commonjs transform**: export const config = { rollupPlugins: { before: [ // Plugins injected before rollupNodeResolve() resolvePlugin() ], after: [ // Plugins injected after commonjs() nodePolyfills() ] }} ### Related Plugins[​](https://stenciljs.com/docs/plugins#related-plugins "Direct link to Related Plugins") * [@stencil/sass](https://www.npmjs.com/package/@stencil/sass) * [@stencil-community/postcss](https://www.npmjs.com/package/@stencil-community/postcss) * [@stencil-community/less](https://www.npmjs.com/package/@stencil-community/less) * (Deprecated) [@stencil/stylus](https://www.npmjs.com/package/@stencil/stylus) Node Polyfills[​](https://stenciljs.com/docs/plugins#node-polyfills "Direct link to Node Polyfills") ----------------------------------------------------------------------------------------------------- See the [Node Polyfills in Module bundling](https://stenciljs.com/docs/module-bundling#node-polyfills) for other examples. Contents -------- * [Stencil plugins](https://stenciljs.com/docs/plugins#stencil-plugins) * [Rollup plugins](https://stenciljs.com/docs/plugins#rollup-plugins) * [Related Plugins](https://stenciljs.com/docs/plugins#related-plugins) * [Node Polyfills](https://stenciljs.com/docs/plugins#node-polyfills) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/config/plugins.md) --- # Hydrate App | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/hydrate-app#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/hydrate-app) ** (v4.35). Version: v4.34 On this page The hydrate app is a Stencil output target which generates a module that can be used on a NodeJS server to hydrate HTML and implement server side rendering (SSR). This functionality is used internally by the Stencil compiler for prerendering, as well as for the Angular Universal SSR for the Ionic framework. However, like Stencil components, the hydrate app itself is not restricted to one framework. _Note that Stencil does **NOT** use Puppeteer for SSR or prerendering._ How to Use the Hydrate App[​](https://stenciljs.com/docs/v4.34/hydrate-app#how-to-use-the-hydrate-app "Direct link to How to Use the Hydrate App") --------------------------------------------------------------------------------------------------------------------------------------------------- Server side rendering (SSR) can be accomplished in a similar way to prerendering. Instead of using the `--prerender` CLI flag, you can an output target of type `'dist-hydrate-script'` to your `stencil.config.ts`, like so: outputTargets: [ { type: 'dist-hydrate-script', },]; This will generate a `hydrate` app in your root project directory that can be imported and used by your Node server. After publishing your component library, you can import the hydrate app into your server's code like this: import { createWindowFromHtml, hydrateDocument, renderToString, streamToString } from 'yourpackage/hydrate'; The hydrate app module exports 3 functions, `hydrateDocument`, `renderToString` and `streamToString`. `hydrateDocument` takes a [document](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument) as its input while `renderToString` as well as `streamToString` takes a raw HTML string. While `hydrateDocument` and `renderToString` return a Promise which wraps a result object, `streamToString` returns a [`Readable`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) stream that can be passed into a server response. ### hydrateDocument[​](https://stenciljs.com/docs/v4.34/hydrate-app#hydratedocument "Direct link to hydrateDocument") You can use `hydrateDocument` as a part of your server's response logic before serving the web page. `hydrateDocument` takes two arguments, a [document](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDocument) and a config object. The function returns a promise with the hydrated results, with the hydrated HTML under the `html` property. _Example taken from Ionic Angular server_ import { hydrateDocument, createWindowFromHtml } from 'yourpackage/hydrate';export function hydrateComponents(template: string) { const win = createWindowFromHtml(template, Math.random().toString()) return hydrateDocument(win.document) .then((hydrateResults) => { // execute logic based on results console.log(hydrateResults.html); return hydrateResults; });} You can call the `hydrateComponents` function from your Node.js server, e.g.: import Koa from 'koa';const app = new Koa();app.use(async (ctx) => { const res = await hydrateComponents(` Document `) ctx.body = res}) Please note that Stencil injects scoped component styles immediately after `` tags with a `rel="preconnect"` attribute, but before your custom styles. This setup allows you to define custom styles for your components effectively. #### hydrateDocument Options[​](https://stenciljs.com/docs/v4.34/hydrate-app#hydratedocument-options "Direct link to hydrateDocument Options") * `canonicalUrl` - string * `constrainTimeouts` - boolean * `clientHydrateAnnotations` - boolean * `cookie` - string * `direction` - string * `language` - string * `maxHydrateCount` - number * `referrer` - string * `removeScripts` - boolean * `removeUnusedStyles` - boolean * `resourcesUrl` - string * `timeout` - number * `title` - string * `url` - string * `userAgent` - string ### renderToString[​](https://stenciljs.com/docs/v4.34/hydrate-app#rendertostring "Direct link to renderToString") The hydrate app also has a `renderToString` function that takes an HTML string and returns a promise of `HydrateResults`. The optional second parameter is a config object that can alter the output of the markup. Like `hydrateDocument`, the hydrated HTML can be found under the `html` property. _Example taken from Ionic Core_ const results = await hydrate.renderToString( ``, { fullDocument: false, serializeShadowRoot: 'declarative-shadow-dom', prettyHtml: true, });console.log(results.html);/** * outputs: * ```html * * * * * ``` */ #### renderToString Options[​](https://stenciljs.com/docs/v4.34/hydrate-app#rendertostring-options "Direct link to renderToString Options") ##### `approximateLineWidth`[​](https://stenciljs.com/docs/v4.34/hydrate-app#approximatelinewidth "Direct link to approximatelinewidth") **Type:** `number` Determines when line breaks are being set when serializing the component. ##### `prettyHtml`[​](https://stenciljs.com/docs/v4.34/hydrate-app#prettyhtml "Direct link to prettyhtml") **Default:** `false` **Type:** `boolean` If set to `true` it prettifies the serialized HTML code, intends elements and escapes text nodes. ##### `removeAttributeQuotes`[​](https://stenciljs.com/docs/v4.34/hydrate-app#removeattributequotes "Direct link to removeattributequotes") **Type:** `boolean` **Default:** `false` If set to `true` it removes attribute quotes when possible, e.g. replaces `someAttribute="foo"` to `someAttribute=foo`. ##### `removeEmptyAttributes`[​](https://stenciljs.com/docs/v4.34/hydrate-app#removeemptyattributes "Direct link to removeemptyattributes") **Type:** `boolean` **Default:** `true` If set to `true` it removes attribute that don't have values, e.g. remove `class=""`. ##### `removeHtmlComments`[​](https://stenciljs.com/docs/v4.34/hydrate-app#removehtmlcomments "Direct link to removehtmlcomments") **Type:** `boolean` **Default:** `false` If set to `true` it removes any abundant HTML comments. Stencil still requires to insert hydration comments to be able to reconcile the component. ##### `beforeHydrate`[​](https://stenciljs.com/docs/v4.34/hydrate-app#beforehydrate "Direct link to beforehydrate") **Type:** `(document: Document, url: URL) => | Promise` Allows to modify the document and all its containing components to be modified before the hydration process starts. This allows e.g. to assign properties to the components dynamically: await renderToString(response.body, { beforeHydrate: (doc: Document) => { doc.querySelector(`my-component`).someComplexThing = new Map(...) },}) ##### `afterHydrate`[​](https://stenciljs.com/docs/v4.34/hydrate-app#afterhydrate "Direct link to afterhydrate") **Type:** `(document: Document, url: URL, results: PrerenderUrlResults) => | Promise` Allows to modify the document and all its containing components after the component was rendered in the virtual DOM and before the serialization process starts. ##### `serializeShadowRoot`[​](https://stenciljs.com/docs/v4.34/hydrate-app#serializeshadowroot "Direct link to serializeshadowroot") **Default:** `'declarative-shadow-dom'` **Type:** 'declarative-shadow-dom' | 'scoped' | { 'declarative-shadow-dom'?: string[]; scoped?: string[]; default: 'declarative-shadow-dom' | 'scoped';} | false; Configure how Stencil serializes a component's shadow-root: * `declarative-shadow-dom` - all `shadow: true` components will be rendered with a [Declarative Shadow DOM](https://developer.chrome.com/docs/css-ui/declarative-shadow-dom) . * `scoped` - all `shadow: true` components will be rendered with Stencil's custom scoped behavior; a light-dom tree and single ` *
* * Hello, World! I'm Stencil 'Don't call me a framework' JS *
* * * * ``` */ **Scoped Example:** const results = await hydrate.renderToString( ``, { fullDocument: true, serializeShadowRoot: `scoped`, prettyHtml: true, });console.log(results.html);/** * outputs: * ```html * * * * * * *
* * Hello, World! I'm Stencil 'Don't call me a framework' JS *
*
* * ``` */ ##### `fullDocument`[​](https://stenciljs.com/docs/v4.34/hydrate-app#fulldocument "Direct link to fulldocument") **Type:** `boolean` **Default:** `true` If set to `true`, Stencil will serialize a complete HTML document for a server to respond. If set to `false` it will only render the components within the given template. Contents -------- * [How to Use the Hydrate App](https://stenciljs.com/docs/v4.34/hydrate-app#how-to-use-the-hydrate-app) * [hydrateDocument](https://stenciljs.com/docs/v4.34/hydrate-app#hydratedocument) * [renderToString](https://stenciljs.com/docs/v4.34/hydrate-app#rendertostring) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.34/guides/hydrate-app.md) --- # Storybook Integration | Stencil [Skip to main content](https://stenciljs.com/docs/storybook#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page [Storybook](https://storybook.js.org/) is a powerful tool for developing, testing, and documenting UI components in isolation. It's open-source, widely adopted, and integrates seamlessly with modern frontend frameworks—including Stencil (v2.30.0 and above). With the latest Stencil version, you can now build and preview your components directly in Storybook. Getting Started[​](https://stenciljs.com/docs/storybook#getting-started "Direct link to Getting Started") ---------------------------------------------------------------------------------------------------------- > 🔧 **Note:** Native support for Stencil in the Storybook CLI is currently in progress ([see pull request](https://github.com/storybookjs/storybook/pull/31205) > ). > > In the meantime, follow this manual setup guide for Storybook Version 8, then optionally run the following command to migrate to Storybook Version 9: > > npx storybook@latest upgrade ### Install Dependencies[​](https://stenciljs.com/docs/storybook#install-dependencies "Direct link to Install Dependencies") Add the necessary dev dependencies to your project: npm install --save-dev storybook@8 @storybook/addon-essentials@8 @storybook/addon-links@8 @storybook/addon-interactions@8 @stencil/core@latest @stencil/storybook-plugin ### Configure Storybook[​](https://stenciljs.com/docs/storybook#configure-storybook "Direct link to Configure Storybook") Create a `.storybook/main.ts` file with the following configuration: const config = { stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"], addons: [ "@storybook/addon-links", "@storybook/addon-essentials", "@storybook/addon-interactions", ], framework: { name: "@stencil/storybook-plugin" },};export default config; By default, the Stencil Storybook plugin registers the component specified via the `component` property in your story. However, if your component depends on other custom elements from your Stencil library, you'll want to ensure those are available too. To do this, you can embed the [Stencil Loader](https://stenciljs.com/docs/next/distribution#loader) in the Storybook preview script to **lazily register all components** globally: // .storybook/preview.tsximport { defineCustomElements } from '../loader/index.js';/** * Registers all custom elements in the Storybook preview. * This is useful if your components rely on other nested Stencil components. */defineCustomElements(); ### Adding Global Styles[​](https://stenciljs.com/docs/storybook#adding-global-styles "Direct link to Adding Global Styles") If your components rely on global stylesheets (e.g., a design system or component library), you can include them using a `preview-head.html` file. This file will be injected into the `` of the Storybook preview iframe: This ensures all your components render correctly with the required styles in place. ### Add a Script[​](https://stenciljs.com/docs/storybook#add-a-script "Direct link to Add a Script") In your `package.json`, add the following Storybook script: "scripts": { "storybook": "storybook dev -p 6006 --no-open"} Creating Your First Story[​](https://stenciljs.com/docs/storybook#creating-your-first-story "Direct link to Creating Your First Story") ---------------------------------------------------------------------------------------------------------------------------------------- It's recommended to place your story file next to your component for better co-location and discoverability. For example: src/components/my-component/my-component.stories.tsx If you prefer a different structure, that's perfectly fine—just make sure your `stories` pattern in `.storybook/main.ts` includes the correct paths. Here’s an example story for a `MyComponent`: import type { Meta, StoryObj } from '@stencil/storybook-plugin';import { h } from '@stencil/core';import { MyComponent } from './my-component';const meta: Meta = { title: 'MyComponent', component: MyComponent, parameters: { layout: 'centered', }, argTypes: { first: { control: 'text' }, last: { control: 'text' }, middle: { control: 'text' }, }, args: { first: 'John', last: 'Doe', middle: 'Michael' },};export default meta;type Story = StoryObj;export const Primary: Story = { args: { first: 'John', last: 'Doe', middle: 'Michael', }, render: (props) => ,};/** * Storybook story without custom render function */export const Secondary: Story = { args: { first: 'Jane', last: 'Smith', middle: 'Marie', },}; Running Storybook[​](https://stenciljs.com/docs/storybook#running-storybook "Direct link to Running Storybook") ---------------------------------------------------------------------------------------------------------------- To launch Storybook, first make sure your Stencil project is built, then simply run: npm run storybook Then open [http://localhost:6006](http://localhost:6006/) in your browser to view your Stencil component in action 🎉 Learn More[​](https://stenciljs.com/docs/storybook#learn-more "Direct link to Learn More") ------------------------------------------------------------------------------------------- For additional features and customization options, visit the [official Storybook documentation](https://storybook.js.org/docs) . Contents -------- * [Getting Started](https://stenciljs.com/docs/storybook#getting-started) * [Install Dependencies](https://stenciljs.com/docs/storybook#install-dependencies) * [Configure Storybook](https://stenciljs.com/docs/storybook#configure-storybook) * [Adding Global Styles](https://stenciljs.com/docs/storybook#adding-global-styles) * [Add a Script](https://stenciljs.com/docs/storybook#add-a-script) * [Creating Your First Story](https://stenciljs.com/docs/storybook#creating-your-first-story) * [Running Storybook](https://stenciljs.com/docs/storybook#running-storybook) * [Learn More](https://stenciljs.com/docs/storybook#learn-more) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/guides/storybook.md) --- # Functional Components | Stencil [Skip to main content](https://stenciljs.com/docs/v4.34/functional-components#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.34**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/functional-components) ** (v4.35). Version: v4.34 On this page Functional components are quite different to normal Stencil web components because they are a part of Stencil's JSX compiler. A functional component is basically a function that takes an object of props and turns it into JSX. const Hello = props =>

Hello, {props.name}!

; When the JSX transpiler encounters such a component, it will take its attributes, pass them into the function as the `props` object, and replace the component with the JSX that is returned by the function. Functional components also accept a second argument `children`. const Hello = (props, children) => [

Hello, {props.name}

, children]; The JSX transpiler passes all child elements of the component as an array into the function's `children` argument.

I'm a child element.

Stencil provides a `FunctionalComponent` generic type that allows to specify an interface for the component's properties. // Hello.tsximport { FunctionalComponent, h } from '@stencil/core';interface HelloProps { name: string;}export const Hello: FunctionalComponent = ({ name }) => (

Hello, {name}!

); Working with children[​](https://stenciljs.com/docs/v4.34/functional-components#working-with-children "Direct link to Working with children") ---------------------------------------------------------------------------------------------------------------------------------------------- The second argument of a functional component receives the passed children, but in order to work with them, `FunctionalComponent` provides a utils object that exposes a `map()` method to transform the children, and a `forEach()` method to read them. Reading the `children` array is not recommended since the stencil compiler can rename the vNode properties in prod mode. export interface FunctionalUtilities { forEach: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => void) => void; map: (children: VNode[], cb: (vnode: ChildNode, index: number, array: ChildNode[]) => ChildNode) => VNode[];}export interface ChildNode { vtag?: string | number | Function; vkey?: string | number; vtext?: string; vchildren?: VNode[]; vattrs?: any; vname?: string;} **Example:** export const AddClass: FunctionalComponent = (_, children, utils) => ( utils.map(children, child => ({ ...child, vattrs: { ...child.vattrs, class: `${child.vattrs.class} add-class` } } ))); note When using a functional component in JSX, its name must start with a capital letter. Therefore it makes sense to export it as such. Disclaimer[​](https://stenciljs.com/docs/v4.34/functional-components#disclaimer "Direct link to Disclaimer") ------------------------------------------------------------------------------------------------------------- There are a few major differences between functional components and class components. Since functional components are just syntactic sugar within JSX, they... * aren't compiled into web components, * don't create a DOM node, * don't have a Shadow DOM or scoped styles, * don't have lifecycle hooks, * are stateless. When deciding whether to use functional components, one concept to keep in mind is that often the UI of your application can be a function of its state, i. e., given the same state, it always renders the same UI. If a component has to hold state, deal with events, etc, it should probably be a class component. If a component's purpose is to simply encapsulate some markup so it can be reused across your app, it can probably be a functional component (especially if you're using a component library and thus don't need to style it). caution Stencil does not support re-exporting a functional component from a "barrel file" and dynamically rendering it in another component. This is a [known limitation](https://github.com/ionic-team/stencil/issues/5246) within Stencil. Instead, either use class components and remove the import or import the functional component directly. Contents -------- * [Working with children](https://stenciljs.com/docs/v4.34/functional-components#working-with-children) * [Disclaimer](https://stenciljs.com/docs/v4.34/functional-components#disclaimer) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.34/components/functional-components.md) --- # Stencil Output Targets | Stencil [Skip to main content](https://stenciljs.com/docs/output-targets#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page One of the more powerful features of the compiler is its ability to generate various builds depending on _"how"_ the components are going to be used. Stencil is able to take an app's source and compile it to numerous targets, such as a webapp to be deployed on an http server, as a third-party component lazy-loaded library to be distributed on [npm](https://www.npmjs.com/) , or a vanilla custom elements bundle. By default, Stencil apps have an output target type of `www`, which is best suited for a webapp. Output Target Types:[​](https://stenciljs.com/docs/output-targets#output-target-types "Direct link to Output Target Types:") ----------------------------------------------------------------------------------------------------------------------------- * [`dist`: Distribution](https://stenciljs.com/docs/distribution) * [`www`: Website](https://stenciljs.com/docs/www) * [`dist-custom-elements`: Custom Elements](https://stenciljs.com/docs/custom-elements) Example:[​](https://stenciljs.com/docs/output-targets#example "Direct link to Example:") ----------------------------------------------------------------------------------------- import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'dist' }, { type: 'www' } ]}; Primary Package Output Target Validation[​](https://stenciljs.com/docs/output-targets#primary-package-output-target-validation "Direct link to Primary Package Output Target Validation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ If `validatePrimaryPackageOutputTarget: true` is set in your project's [Stencil config](https://stenciljs.com/docs/config#validateprimarypackageoutputtarget) Stencil will attempt to validate certain fields in your `package.json` that correspond with the generated distribution code. Because Stencil can output many different formats from a single project, it can only validate that the `package.json` has field values that align with one of the specified output targets in your project's config. So, Stencil allows you to designate which output target should be used for this validation and thus which will be the default distribution when bundling your project. This behavior only affects a small subset of output targets so a flag exists on the following targets that are eligible for this level of validation: `dist`, `dist-types`, `dist-collection`, and `dist-custom-elements`. For any of these output targets, you can configure the target to be validated as follows: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { ..., outputTargets: [ { type: 'dist', // This flag is what tells Stencil to use this target for validation isPrimaryPackageOutputTarget: true, ... }, ... ], // If this is not set, Stencil will not validate any targets validatePrimaryPackageOutputTarget: true,}; note Stencil can only validate one of these output targets for your build. If multiple output targets are marked for validation, Stencil will use the first designated target in the array and ignore all others. Contents -------- * [Output Target Types:](https://stenciljs.com/docs/output-targets#output-target-types) * [Example:](https://stenciljs.com/docs/output-targets#example) * [Primary Package Output Target Validation](https://stenciljs.com/docs/output-targets#primary-package-output-target-validation) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/output-targets/01-overview.md) --- # Upgrading to Stencil v4.0.0 | Stencil [Skip to main content](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page Getting Started[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#getting-started "Direct link to Getting Started") --------------------------------------------------------------------------------------------------------------------------------------- We recommend that you only upgrade to Stencil v4 from Stencil v3. If you're a few versions behind, we recommend upgrading one major version at a time (from v1 to v2, then v2 to v3, finally v3 to v4). This will minimize the number of breaking changes you have to deal with at the same time. For breaking changes introduced in previous major versions of the library, see: * [Stencil v3 Breaking Changes](https://github.com/ionic-team/stencil/blob/main/BREAKING_CHANGES.md#stencil-v300) * [Stencil v2 Breaking Changes](https://github.com/ionic-team/stencil/blob/main/BREAKING_CHANGES.md#stencil-two) * [Stencil v1 Breaking Changes](https://github.com/ionic-team/stencil/blob/main/BREAKING_CHANGES.md#stencil-one) For projects that are on Stencil v3, install the latest version of Stencil v4: `npm install @stencil/core@4` Updating Your Code[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#updating-your-code "Direct link to Updating Your Code") ------------------------------------------------------------------------------------------------------------------------------------------------ ### New Configuration Defaults[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#new-configuration-defaults "Direct link to New Configuration Defaults") Starting with Stencil v4.0.0, the default configuration values have changed for a few configuration options. The following sections lay out the configuration options that have changed, their new default values, and ways to opt-out of the new behavior (if applicable). #### `transformAliasedImportPaths`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#transformaliasedimportpaths "Direct link to transformaliasedimportpaths") TypeScript projects have the ability to specify a path aliases via the [`paths` configuration in their `tsconfig.json`](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping) like so: tsconfig.json { "compilerOptions": { "baseUrl": ".", "paths": { "@utils": ["src/utils/index.ts"] } }} In the example above, `"@utils"` would be mapped to the string `"src/utils/index.ts"` when TypeScript performs type resolution. The TypeScript compiler does not however, transform these paths from their keys to their values as a part of its output. Instead, it relies on a bundler/loader to do the transformation. The ability to transform path aliases was introduced in [Stencil v3.1.0](https://github.com/ionic-team/stencil/releases/tag/v3.1.0) as an opt-in feature. Previously, users had to explicitly enable this functionality in their `stencil.config.ts` file with `transformAliasedImportPaths`: stencil.config.ts - enabling 'transformAliasedImportPaths' in Stencil v3.1.0 import { Config } from '@stencil/core';export const config: Config = { transformAliasedImportPaths: true, // ...}; Starting with Stencil v4.0.0, this feature is enabled by default. Projects that had previously enabled this functionality that are migrating from Stencil v3.1.0+ may safely remove the flag from their Stencil configuration file(s). For users that run into issues with this new default, we encourage you to file a [new issue on the Stencil GitHub repo](https://github.com/ionic-team/stencil/issues/new?assignees=&labels=&projects=&template=bug_report.yml&title=bug%3A+) . As a workaround, this flag can be set to `false` to disable the default functionality. stencil.config.ts - disabling 'transformAliasedImportPaths' in Stencil v4.0.0 import { Config } from '@stencil/core';export const config: Config = { transformAliasedImportPaths: false, // ...}; For more information on this flag, please see the [configuration documentation](https://stenciljs.com/docs/config#transformaliasedimportpaths) #### `transformAliasedImportPathsInCollection`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#transformaliasedimportpathsincollection "Direct link to transformaliasedimportpathsincollection") Introduced in [Stencil v2.18.0](https://github.com/ionic-team/stencil/releases/tag/v2.18.0) , `transformAliasedImportPathsInCollection` is a configuration flag on the [`dist` output target](https://stenciljs.com/docs/distribution#transformaliasedimportpathsincollection) . `transformAliasedImportPathsInCollection` transforms import paths, similar to [`transformAliasedImportPaths`](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#transformaliasedimportpaths) . This flag however, only enables the functionality of `transformAliasedImportPaths` for collection output targets. Starting with Stencil v4.0.0, this flag is enabled by default. Projects that had previously enabled this functionality that are migrating from Stencil v2.18.0+ may safely remove the flag from their Stencil configuration file(s). For users that run into issues with this new default, we encourage you to file a [new issue on the Stencil GitHub repo](https://github.com/ionic-team/stencil/issues/new?assignees=&labels=&projects=&template=bug_report.yml&title=bug%3A+) . As a workaround, this flag can be set to `false` to disable the default functionality. stencil.config.ts - disabling 'transformAliasedImportPathsInCollection' in Stencil v4.0.0 import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'dist', transformAliasedImportPathsInCollection: false, }, // ... ] // ...}; For more information on this flag, please see the [`dist` output target's documentation](https://stenciljs.com/docs/distribution#transformaliasedimportpathsincollection) . ### In Browser Compilation Support Removed[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#in-browser-compilation-support-removed "Direct link to In Browser Compilation Support Removed") Prior to Stencil v4.0.0, components could be compiled from TSX to JS in the browser. This feature was seldom used, and has been removed from Stencil. At this time, there is no replacement functionality. For additional details, please see the [request-for-comment](https://github.com/ionic-team/stencil/discussions/4134) on the Stencil GitHub Discussions page. ### Legacy Context and Connect APIs Removed[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#legacy-context-and-connect-apis-removed "Direct link to Legacy Context and Connect APIs Removed") Previously, Stencil supported `context` and `connect` as options within the `@Prop` decorator. Both of these APIs were deprecated in Stencil v1 and are now removed. @Prop({ context: 'config' }) config: Config;@Prop({ connect: 'ion-menu-controller' }) lazyMenuCtrl: Lazy; To migrate away from usages of `context`, please see [the original deprecation announcement](https://github.com/ionic-team/stencil/blob/main/BREAKING_CHANGES.md#propcontext) . To migrate away from usages of `connect`, please see [the original deprecation announcement](https://github.com/ionic-team/stencil/blob/main/BREAKING_CHANGES.md#propconnect) . ### Legacy Browser Support Removed[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#legacy-browser-support-removed "Direct link to Legacy Browser Support Removed") In Stencil v3.0.0, we announced [the deprecation of IE 11, pre-Chromium Edge, and Safari 10 support](https://github.com/ionic-team/stencil/blob/1a8ff39073a88d1372beaa98434dbe2247f68a85/BREAKING_CHANGES.md?plain=1#L78) . In Stencil v4.0.0, support for these browsers has been dropped (for a full list of supported browsers, please see our [Browser Support policy](https://stenciljs.com/docs/support-policy#browser-support) ). By dropping these browsers, a few configuration options are no longer valid in a Stencil configuration file: #### `__deprecated__cssVarsShim`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#__deprecated__cssvarsshim "Direct link to __deprecated__cssvarsshim") The `extras.__deprecated__cssVarsShim` option caused Stencil to include a polyfill for [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) . This field should be removed from a project's Stencil configuration file (`stencil.config.ts`). #### `__deprecated__dynamicImportShim`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#__deprecated__dynamicimportshim "Direct link to __deprecated__dynamicimportshim") The `extras.__deprecated__dynamicImportShim` option caused Stencil to include a polyfill for the [dynamic `import()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) for use at runtime. This field should be removed from a project's Stencil configuration file (`stencil.config.ts`). #### `__deprecated__safari10`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#__deprecated__safari10 "Direct link to __deprecated__safari10") The `extras.__deprecated__safari10` option would patch ES module support for Safari 10. This field should be removed from a project's Stencil configuration file (`stencil.config.ts`). #### `__deprecated__shadowDomShim`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#__deprecated__shadowdomshim "Direct link to __deprecated__shadowdomshim") The `extras.__deprecated__shadowDomShim` option would check whether a shim for [shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) was needed in the current browser, and include one if so. This field should be removed from a project's Stencil configuration file (`stencil.config.ts`). ### Legacy Cache Stats Config Flag Removed[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#legacy-cache-stats-config-flag-removed "Direct link to Legacy Cache Stats Config Flag Removed") The `enableCacheStats` flag was used in legacy behavior for caching, but has not been used for some time. This flag has been removed from Stencil's API and should be removed from a project's Stencil configuration file (`stencil.config.ts`). ### Drop Node 14 Support[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#drop-node-14-support "Direct link to Drop Node 14 Support") Stencil no longer supports Node 14. Please upgrade local development machines, continuous integration pipelines, etc. to use Node v16 or higher. For the full list of supported runtimes, please see [our Support Policy](https://stenciljs.com/docs/support-policy#javascript-runtime) . Information Included in `docs-json` Expanded[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#information-included-in-docs-json-expanded "Direct link to information-included-in-docs-json-expanded") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- For Stencil v4 the information included in the output of the `docs-json` output target was expanded to include more information about the types of properties and methods on Stencil components. For more context on this change, see the [documentation for the new `supplementalPublicTypes`](https://stenciljs.com/docs/docs-json#supplementalpublictypes) option for the JSON documentation output target. ### `JsonDocsEvent`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#jsondocsevent "Direct link to jsondocsevent") The JSON-formatted documentation for an `@Event` now includes a field called `complexType` which includes more information about the types referenced in the type declarations for that property. Here's an example of what this looks like for the [ionBreakpointDidChange event](https://github.com/ionic-team/ionic-framework/blob/1f0c8049a339e3a77c468ddba243041d08ead0be/core/src/components/modal/modal.tsx#L289-L292) on the `Modal` component in Ionic Framework: { "complexType": { "original": "ModalBreakpointChangeEventDetail", "resolved": "ModalBreakpointChangeEventDetail", "references": { "ModalBreakpointChangeEventDetail": { "location": "import", "path": "./modal-interface", "id": "src/components/modal/modal.tsx::ModalBreakpointChangeEventDetail" } } }} ### `JsonDocsMethod`[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#jsondocsmethod "Direct link to jsondocsmethod") The JSON-formatted documentation for a `@Method` now includes a field called `complexType` which includes more information about the types referenced in the type declarations for that property. Here's an example of what this looks like for the [open method](https://github.com/ionic-team/ionic-framework/blob/1f0c8049a339e3a77c468ddba243041d08ead0be/core/src/components/select/select.tsx#L261-L313) on the `Select` component in Ionic Framework: { "complexType": { "signature": "(event?: UIEvent) => Promise", "parameters": [ { "tags": [ { "name": "param", "text": "event The user interface event that called the open." } ], "text": "The user interface event that called the open." } ], "references": { "Promise": { "location": "global", "id": "global::Promise" }, "UIEvent": { "location": "global", "id": "global::UIEvent" }, "HTMLElement": { "location": "global", "id": "global::HTMLElement" } }, "return": "Promise" }} Additional Packages[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#additional-packages "Direct link to Additional Packages") --------------------------------------------------------------------------------------------------------------------------------------------------- To ensure the proper functioning of other `@stencil/` packages, it is advisable for projects utilizing any of the packages mentioned below to upgrade to the minimum package version specified. | Package | Minimum Package Version | GitHub | Documentation | | --- | --- | --- | --- | | `@stencil/angular-output-target` | [0.7.1](https://github.com/ionic-team/stencil-ds-output-targets/releases/tag/%40stencil%2Fangular-output-target%400.7.1) | [GitHub](https://github.com/ionic-team/stencil-ds-output-targets) | [Stencil Doc Site](https://stenciljs.com/docs/angular) | | `@stencil/sass` | [3.0.4](https://github.com/ionic-team/stencil-sass/releases/tag/v3.0.4) | [GitHub](https://github.com/ionic-team/stencil-sass) | [GitHub README](https://github.com/ionic-team/stencil-sass) | | `@stencil/store` | [2.0.8](https://github.com/ionic-team/stencil-store/releases/tag/v2.0.8) | [GitHub](https://github.com/ionic-team/stencil-store) | [Stencil Doc Site](https://stenciljs.com/docs/stencil-store) | | `@stencil/react-output-target` | [0.5.1](https://github.com/ionic-team/stencil-ds-output-targets/releases/tag/%40stencil%2Freact-output-target%400.5.1) | [GitHub](https://github.com/ionic-team/stencil-ds-output-targets) | [Stencil Doc Site](https://stenciljs.com/docs/react) | | `@stencil/vue-output-target` | [0.8.6](https://github.com/ionic-team/stencil-ds-output-targets/releases/tag/%40stencil%2Fvue-output-target%400.8.6) | [GitHub](https://github.com/ionic-team/stencil-ds-output-targets) | [Stencil Doc Site](https://stenciljs.com/docs/vue) | Need Help Upgrading?[​](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#need-help-upgrading "Direct link to Need Help Upgrading?") ----------------------------------------------------------------------------------------------------------------------------------------------------- Be sure to look at the Stencil [v4.0.0 Breaking Changes Guide](https://github.com/ionic-team/stencil/blob/main/BREAKING_CHANGES.md#stencil-v400) . If you need help upgrading, please post a thread on the [Stencil Discord](https://chat.stenciljs.com/) . Contents -------- * [Getting Started](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#getting-started) * [Updating Your Code](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#updating-your-code) * [New Configuration Defaults](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#new-configuration-defaults) * [In Browser Compilation Support Removed](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#in-browser-compilation-support-removed) * [Legacy Context and Connect APIs Removed](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#legacy-context-and-connect-apis-removed) * [Legacy Browser Support Removed](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#legacy-browser-support-removed) * [Legacy Cache Stats Config Flag Removed](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#legacy-cache-stats-config-flag-removed) * [Drop Node 14 Support](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#drop-node-14-support) * [Information Included in `docs-json` Expanded](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#information-included-in-docs-json-expanded) * [`JsonDocsEvent`](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#jsondocsevent) * [`JsonDocsMethod`](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#jsondocsmethod) * [Additional Packages](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#additional-packages) * [Need Help Upgrading?](https://stenciljs.com/docs/introduction/upgrading-to-stencil-four#need-help-upgrading) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.35/introduction/upgrading-to-stencil-four.md) --- # WebdriverIO Overview | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/testing/webdriverio/overview#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/testing/webdriverio/overview) ** (v4.35). Version: v4.33 On this page WebdriverIO is a progressive automation framework built to automate modern web and mobile applications. It simplifies the interaction with your project and provides a set of plugins that help you create a scalable, robust and stable test suite. Testing with WebdriverIO has the following advantages: * **Cross Browser Support**: WebdriverIO is designed to support all platforms, either on desktop or mobile. You can run tests on actual browser your users are using, including covering different versions of them. * **Real User Interaction**: Interaction with elements in WebdriverIO through the WebDriver protocol is much closer to native user-triggered interactions than what can be achieved with emulated DOM environments (such as JSDom or Stencil's own Mock-Doc). * **Web Platform Support**: Running tests in actual browsers allows you to tap into the latest Web Platform features for testing your components, often not available when using virtual DOM environments. * **Real Environments**: Run your tests in an environment that your users are using and not somewhere that re-implements web standards with polyfills like JSDOM. Set Up[​](https://stenciljs.com/docs/v4.33/testing/webdriverio/overview#set-up "Direct link to Set Up") -------------------------------------------------------------------------------------------------------- To get started with WebdriverIO, all you need to do is to run their project starter: * npm * Yarn * pnpm npm init wdio@latest . yarn create wdio@latest . pnpm create wdio@latest . This will initiate WebdriverIO's configuration wizard that walks you through the setup. Make sure you select the following options when walking through it: * **What type of testing would you like to do?** Select either: * `Component or Unit Testing - in the browser` if you are interested adding unit tests for your components * `E2E Testing - of Web or Mobile Applications` if you like to test your whole applicationYou can always add either of them later on * **Which framework do you use for building components?**: if you select _Component or Unit Testing_ make sure to select `StencilJS` as preset so WebdriverIO knows how to compile your components properly The following questions can be answered as desired. Once setup the wizard has created a `wdio.conf.ts` file and a `wdio` script to run your tests. CJS vs. ESM WebdriverIO's generated config and test files use ESM syntax for imports. If you generated a project via the [`create-stencil`](https://www.npmjs.com/package/create-stencil) starter package your project is likely setup for CommonJS. To avoid any incompatibility issues, we recommend to rename your `wdio.conf.ts` to `wdio.conf.mts` and update the `wdio` script in your `package.json`. Type Clashes It's possible that you run into TypeScript issues as WebdriverIO uses Mocha for component testing and Stencil Jest. Both register the same globals, e.g. `it` which causes type clashes. To fix these we recommend to add the following to your `tsconfig.json`: "types": ["jest"] This will ensure that Jest types will be preferred. You should be able to run your first test on the auto-generated test file via: * npm * Yarn * pnpm npm run wdio yarn wdio pnpm run wdio More information on setting up WebdriverIO can be found in their [documentation](https://webdriver.io/docs/component-testing/stencil) . Integration with Stencil[​](https://stenciljs.com/docs/v4.33/testing/webdriverio/overview#integration-with-stencil "Direct link to Integration with Stencil") -------------------------------------------------------------------------------------------------------------------------------------------------------------- If you have been using Stencil's test runner for unit or end-to-end tests to can continue to do so. For basic implementation details that don't require any web platform features, running tests through the Stencil test runner might still be the faster choice, since no browser needs to be spawned. However you can also migrate over to only one single framework one test at a time. We recommend to create a new NPM script for running both, Stencil and WebdriverIO tests, starting with Stencil tests first as they are likely to run faster. In your `package.json` this can be structured like so: package.json { "scripts:": { "test.e2e": "stencil test && wdio run wdio.conf.ts" }} Make sure that each test runner picks up their respective tests by defining the `testRegex` property in your Stencil config, e.g.: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { // ... testing: { testRegex: '(/__tests__/.*|\\.?(spec))\\.(ts|js)$', },}; This will make Stencil pick up all files ending with `.spec.ts` or `.spec.js` while WebdriverIO picks up tests ending with `.test.ts`. Contents -------- * [Set Up](https://stenciljs.com/docs/v4.33/testing/webdriverio/overview#set-up) * [Integration with Stencil](https://stenciljs.com/docs/v4.33/testing/webdriverio/overview#integration-with-stencil) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/testing/webdriverio/01-overview.md) --- # Vitest | Stencil [Skip to main content](https://stenciljs.com/docs/v4.33/testing/vitest#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Stencil **v4.33**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://stenciljs.com/docs/testing/vitest) ** (v4.35). Version: v4.33 On this page [Vitest](https://vitest.dev/) is a popular and modern test framework for unit testing. You can use Vitest to test Stencil components in the browser using its [browser mode feature](https://vitest.dev/guide/browser.html) . caution Vitest browser mode is an experimental feature and in early development. As such, it may not yet be fully optimized, and there may be some bugs or issues that have not yet been ironed out. Set Up[​](https://stenciljs.com/docs/v4.33/testing/vitest#set-up "Direct link to Set Up") ------------------------------------------------------------------------------------------ To get started with Vitest, all you need to install it via: * npm * Yarn * pnpm npm install vitest @vitest/browser unplugin-stencil webdriverio yarn add vitest @vitest/browser unplugin-stencil webdriverio pnpm add vitest @vitest/browser unplugin-stencil webdriverio This command installs: * `vitest`: the core test framework * `@vitest/browser`: enables testing in browser environments * `unplugin-stencil`: integrates Stencil's compiler with Vitest for seamless testing * `webdriverio`: facilitates browser management for tests Next, we create a Vitest configuration as following: vitest.config.ts import stencil from 'unplugin-stencil/vite'import { defineConfig } from 'vitest/config'export default defineConfig({ test: { browser: { enabled: true, headless: true, name: 'chrome' }, }, plugins: [stencil()]}) This configuration enables tests to run in a headless Chrome browser. Writing Tests[​](https://stenciljs.com/docs/v4.33/testing/vitest#writing-tests "Direct link to Writing Tests") --------------------------------------------------------------------------------------------------------------- Once you've setup Vitest you can start write your first test. In order to render a Stencil component into the browser, all you need to do is import the component and initiate an instance of the component on the page: src/components/my-component/my-component.test.ts import { expect, test } from 'vitest'import '../src/components/my-component/my-component.js'test('should render component correctly', async () => { const cmp = document.createElement('my-component') cmp.setAttribute('first', 'Stencil') cmp.setAttribute('last', `'Don't call me a framework' JS`) document.body.appendChild(cmp) await new Promise((resolve) => requestIdleCallback(resolve)) expect(cmp.shadowRoot?.querySelector('div')?.innerText) .toBe(`Hello, World! I'm Stencil 'Don't call me a framework' JS`)}) Lastly, let's add a Vitest script to our `package.json`: { "scripts": { "test": "vitest --run" },} Execute the tests using: * npm * Yarn * pnpm npm test yarn test pnpm test Expected output: ❯ npm test> [email protected] test> vitest --runThe CJS build of Vite's Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details. RUN v1.5.0 /private/tmp/vitest Browser runner started at http://localhost:5173/[19:39.9] build, vitest, prod mode, started ...[19:39.9] transpile started ...[19:40.0] transpile finished in 72 ms[19:40.0] generate custom elements + source maps started ...[19:40.1] generate custom elements + source maps finished in 137 ms[19:40.1] build finished in 227 ms ✓ src/components/my-component/my-component.test.ts (1) ✓ should render component correctly Test Files 1 passed (1) Tests 1 passed (1) Start at 14:19:36 Duration 3.19s (transform 0ms, setup 0ms, collect 721ms, tests 22ms, environment 0ms, prepare 0ms) ### Use JSX[​](https://stenciljs.com/docs/v4.33/testing/vitest#use-jsx "Direct link to Use JSX") The example above creates the Stencil instance using basic DOM primitives. If you prefer to use JSX also for rendering Stencil components in your test, just create a `jsx.ts` utility file with the following content: src/utils/jsx.ts export const createElement = (tag, props, ...children) => { if (typeof tag === 'function') { return tag(props, ...children) } const element = document.createElement(tag) Object.entries(props || {}).forEach(([name, value]) => { if (name.startsWith('on') && name.toLowerCase() in window) { element.addEventListener(name.toLowerCase().substr(2), value) } else { element.setAttribute(name, value.toString()) } }) children.forEach((child) => { appendChild(element, child) }) return element}export const appendChild = (parent, child) => { if (Array.isArray(child)) { child.forEach((nestedChild) => appendChild(parent, nestedChild)) } else { parent.appendChild(child.nodeType ? child : document.createTextNode(child)) }}export const createFragment = (_, ...children) => { return children} Now update your test, import the `createElement` method and tell the JSX engine to use that method for rendering the JSX snippet. Our test should look as follows: src/components/my-component/my-component.test.tsx /** @jsx createElement */import { expect, test } from 'vitest'import { createElement } from '../../utils/jsx'import './my-component.js'test('should render the component with jsx', async () => { const cmp = document.body.appendChild(cmp) await new Promise((resolve) => requestIdleCallback(resolve)) expect(cmp.shadowRoot?.querySelector('div')?.innerText) .toBe(`Hello, World! I'm Stencil 'Don't call me a framework' JS`)}) **Note:** the `/** @jsx createElement */` at the top of the file tells JSX which rendering function it should use to parse the JSX snippet. Limitations[​](https://stenciljs.com/docs/v4.33/testing/vitest#limitations "Direct link to Limitations") --------------------------------------------------------------------------------------------------------- Be aware of the following limitations, when using Vitest as test framework for testing Stencil components: * **Mocking not yet supported**: you can't mock any files or dependencies when running with the Stencil browser feature * **No auto-waits**: in order to ensure that the component is rendered, you have to manually wait via, e.g. calling `await new Promise((resolve) => requestIdleCallback(resolve))` Contents -------- * [Set Up](https://stenciljs.com/docs/v4.33/testing/vitest#set-up) * [Writing Tests](https://stenciljs.com/docs/v4.33/testing/vitest#writing-tests) * [Use JSX](https://stenciljs.com/docs/v4.33/testing/vitest#use-jsx) * [Limitations](https://stenciljs.com/docs/v4.33/testing/vitest#limitations) * * * [Edit this page](https://github.com/ionic-team/stencil-site/tree/main/versioned_docs/version-v4.33/testing/03-vitest.md) --- # Server Side Rendering | Stencil [Skip to main content](https://stenciljs.com/docs/server-side-rendering#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v4.35 On this page Stencil provides server-side rendering (SSR) support for React and Vue Output Targets. If you're using frameworks like [Vite](https://vite.dev/) , [Remix](https://remix.run/) , [Next.js](https://nextjs.org/) or [Nuxt](https://nuxt.com/) , Stencil automatically enhances these frameworks to render components on the server using a [Declarative Shadow DOM](https://web.dev/articles/declarative-shadow-dom) or in [scoped mode](https://stenciljs.com/docs/styling#scoped-css) . The first step to enable server side rendering is to generate a hydrate module of your components. Hydrate Module[​](https://stenciljs.com/docs/server-side-rendering#hydrate-module "Direct link to Hydrate Module") ------------------------------------------------------------------------------------------------------------------- The Hydrate Module is a standalone bundle of all your components that uses a JavaScript implementation of various HTML and DOM standards to render Stencil components in a Node.js environment. To create this bundle you have to add `dist-hydrate-script` to your Stencil configuration: stencil.config.ts import { Config } from '@stencil/core';export const config: Config = { outputTargets: [ { type: 'dist-hydrate-script', dir: './hydrate', }, // ... ]}; This will create the Hydrate Module which you can export separately via: package.json { "name": "component-library", ... "exports": { ... "./hydrate": { "types": "./hydrate/index.d.ts", "import": "./hydrate/index.mjs", "require": "./hydrate/index.js", "default": "./hydrate/index.js" }, ... }, ...} Two SSR Approaches[​](https://stenciljs.com/docs/server-side-rendering#two-ssr-approaches "Direct link to Two SSR Approaches") ------------------------------------------------------------------------------------------------------------------------------- Stencil provides two distinct strategies for server-side rendering, each designed to solve different challenges and use cases. These approaches emerged from the complex nature of rendering Web Components on the server, where traditional browser APIs don't exist. ### Strategy 1: The Compiler Approach (Universal SSR)[​](https://stenciljs.com/docs/server-side-rendering#strategy-1-the-compiler-approach-universal-ssr "Direct link to Strategy 1: The Compiler Approach (Universal SSR)") The compiler-based approach, implemented in the `@stencil/ssr` package, works as a build-time plugin that intercepts your code and performs AST (Abstract Syntax Tree) transformations. It transforms components at compile time. #### How It Works[​](https://stenciljs.com/docs/server-side-rendering#how-it-works "Direct link to How It Works") 1. **Build-time interception**: The plugin (Vite or Webpack) receives your JSX code after transformation 2. **AST analysis**: Parses JavaScript into an Abstract Syntax Tree to identify Stencil components 3. **Prop analysis**: Analyzes the props being passed to each component 4. **Pre-rendering**: Calls Stencil's hydrate module to render the component server-side 5. **Code replacement**: Replaces the original component with a wrapper containing pre-rendered HTML #### When to Use Compiler-Based SSR[​](https://stenciljs.com/docs/server-side-rendering#when-to-use-compiler-based-ssr "Direct link to When to Use Compiler-Based SSR") ✅ **Multiple framework support**: Need to support Vite, Remix, Next.js, and other meta-frameworks ✅ **Performance critical applications**: Where response speed is paramount ✅ **Predictable props**: Components with static or build-time determinable data ✅ **"Set it and forget it" solutions**: Want minimal runtime complexity #### Advantages[​](https://stenciljs.com/docs/server-side-rendering#advantages "Direct link to Advantages") * **Universal compatibility**: Works with any React meta-framework * **Zero runtime overhead**: No server processing during requests * **Handles deep nesting**: Excellent at rendering complex component compositions * **Clean separation**: Clear distinction between build-time and runtime concerns * **Consistent performance**: Predictable response times #### Disadvantages[​](https://stenciljs.com/docs/server-side-rendering#disadvantages "Direct link to Disadvantages") * **Static props only**: Cannot resolve dynamic props at compile time (e.g., `prop={calculateValue()}`) * **Build-time configuration required**: Needs plugin setup * **Hydration mismatches**: Still prone to occasional client/server differences ### Strategy 2: The Runtime Approach (Next.js Server Components)[​](https://stenciljs.com/docs/server-side-rendering#strategy-2-the-runtime-approach-nextjs-server-components "Direct link to Strategy 2: The Runtime Approach (Next.js Server Components)") The runtime approach leverages Next.js Server Components to perform real-time SSR. When the server encounters a Stencil component, it renders it on-demand during the request cycle. #### How It Works[​](https://stenciljs.com/docs/server-side-rendering#how-it-works-1 "Direct link to How It Works") 1. **Component interception**: Next.js hits a Stencil component during server rendering 2. **Prop serialization**: Uses `serializeProperty` to handle complex objects, Maps, Sets, and even `Infinity` 3. **Children transformation**: Attempts to transform React children into strings using `react-dom/server` 4. **Async rendering**: Calls Stencil's `renderToString` (Promise-based) on the server 5. **React node recreation**: Parses resulting HTML back into React nodes using `html-react-parser` #### When to Use Runtime-Based SSR[​](https://stenciljs.com/docs/server-side-rendering#when-to-use-runtime-based-ssr "Direct link to When to Use Runtime-Based SSR") ✅ **Next.js commitment**: When you're fully invested in the Next.js ecosystem ✅ **Dynamic values**: Props that are highly dynamic or computed at runtime ✅ **Light DOM access**: Need to include children in server rendering #### Advantages[​](https://stenciljs.com/docs/server-side-rendering#advantages-1 "Direct link to Advantages") * **Full prop access**: All props available with resolved values at runtime * **Light DOM inclusion**: Can include children during serialization * **Dynamic value support**: Handles runtime-computed values perfectly * **True isomorphic rendering**: Complete server-client parity * **Complex object handling**: Built-in serialization for advanced data types #### Disadvantages[​](https://stenciljs.com/docs/server-side-rendering#disadvantages-1 "Direct link to Disadvantages") * **Next.js only**: Requires Server Components support * **Dual component management**: Must maintain both client and server wrappers * **Performance overhead**: Runtime serialization adds latency * **Additional Setup**: Requires importing components from a separate export path, e.g. `my-react-components/next` ### Choosing Your Strategy[​](https://stenciljs.com/docs/server-side-rendering#choosing-your-strategy "Direct link to Choosing Your Strategy") Here's the battle-tested decision tree from real-world implementation: #### Use the Compiler Approach when:[​](https://stenciljs.com/docs/server-side-rendering#use-the-compiler-approach-when "Direct link to Use the Compiler Approach when:") * You need to support multiple frameworks beyond Next.js * Performance is your top priority * Your components have predictable, static props * You want a "set it and forget it" solution * You're building a content-focused site (marketing, docs, blogs) #### Use the Runtime Approach when:[​](https://stenciljs.com/docs/server-side-rendering#use-the-runtime-approach-when "Direct link to Use the Runtime Approach when:") * You're committed to Next.js and Server Components * You need full Light DOM access for complex compositions * Your props are highly dynamic or computed at runtime * You're okay with additional complexity for more rendering power * You're building highly interactive, data-driven applications Enable SSR for StencilJS[​](https://stenciljs.com/docs/server-side-rendering#enable-ssr-for-stenciljs "Direct link to Enable SSR for StencilJS") ------------------------------------------------------------------------------------------------------------------------------------------------- For serializing Stencil components on the server, Stencil uses a package called `@stencil/ssr` which you can install via: npm install --save-dev @stencil/ssr It exports compiler plugins for Vite based projects, e.g. Remix or Webpack based ones like Next.js. The plugin requires the following options: #### `module`[​](https://stenciljs.com/docs/server-side-rendering#module "Direct link to module") The import of the package that exports all your Stencil React components. It helps the package to understand which components can be server side rendered. #### `from`[​](https://stenciljs.com/docs/server-side-rendering#from "Direct link to from") The name of the package that exports all your Stencil React components. Stencil will look up all imports from that package and transforms the statement to use a server side rendered version of the component. #### `hydrateModule`[​](https://stenciljs.com/docs/server-side-rendering#hydratemodule "Direct link to hydratemodule") Your generated hydrate module that gives the package the primitives to serialize a given Stencil component. #### `serializeShadowRoot`[​](https://stenciljs.com/docs/server-side-rendering#serializeshadowroot "Direct link to serializeshadowroot") **optional** **default: **declarative-shadow-dom**** Configurations on how the components should be rendered on the server, e.g. as Declarative Shadow DOM, as scoped components or as a mixture of both. ### Vite[​](https://stenciljs.com/docs/server-side-rendering#vite "Direct link to Vite") If your project is based on the Vite compiler, this includes frameworks like [Remix](https://remix.run/) that are rely on Vite under the hood, you can use the `@stencil/ssr` package to enable SSR support for Stencil components by adding the plugin to the configuration: vite.config.ts import { defineConfig } from 'vite';import { stencilSSR } from '@stencil/ssr';import react from '@vitejs/plugin-react';// https://vite.dev/config/export default defineConfig({ plugins: [ react(), stencilSSR({ module: import('component-library-react'), from: 'component-library-react', hydrateModule: import('component-library/hydrate'), serializeShadowRoot: { 'scoped': ['my-counter'], default: 'declarative-shadow-dom', }, }), ],}) or in case of a Remix project: vite.config.ts import { vitePlugin as remix } from "@remix-run/dev";import { defineConfig } from "vite";import { stencilSSR } from "@stencil/ssr";declare module "@remix-run/node" { interface Future { v3_singleFetch: true; }}export default defineConfig({ plugins: [ remix(), stencilSSR({ module: import('component-library-react'), from: 'component-library-react', hydrateModule: import('component-library/hydrate'), serializeShadowRoot: { 'scoped': ['my-counter'], default: 'declarative-shadow-dom', }, }), ],}); ### Next.js[​](https://stenciljs.com/docs/server-side-rendering#nextjs "Direct link to Next.js") When using Stencil with Next.js, you can server-side render (SSR) components in two ways: **at runtime** or **at compile time**. Each approach has its trade-offs, and the best choice depends on your component architecture. * If your components rely heavily on **slots**, the **compiler-based** SSR approach is generally more reliable. * If your components use **dynamically computed attributes**, the **runtime-based** SSR approach is more flexible. #### Runtime-Based SSR[​](https://stenciljs.com/docs/server-side-rendering#runtime-based-ssr "Direct link to Runtime-Based SSR") In this method, Stencil serializes the component to a **Declarative Shadow DOM** during runtime, as Next.js renders the component on the server. Since Next.js supports asynchronous server components, this allows Stencil to perform serialization as part of the render process. To enable runtime SSR, set the `hydrateModule` option in your React output target: import { Config } from '@stencil/core';import { reactOutputTarget } from '@stencil/react-output-target';export const config: Config = { namespace: 'component-library', outputTargets: [ reactOutputTarget({ /** * tell Stencil where to generate the `components.ts` and `components.server.ts` files */ outDir: '../component-library-react/src', /** * give Stencil the import name of the hydrate module */ hydrateModule: 'component-library/hydrate', /** * tell the server component where it would import the client version of the components */ clientModule: 'component-library-react', serializeShadowRoot: { /* options */ }, }), ],}; This will generate: * `components.ts` — for use on the client * `components.server.ts` — for server-side rendering If you distribute your React wrapper as a separate package, consider exposing the server entry point via a custom export path in your `package.json`: { "name": "component-library-react", "version": "0.0.0", "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "node": "./dist/components.server.js" }, "./next": { "types": "./dist/components.server.d.ts", "import": "./dist/components.server.js" } }} Now you can use the server-optimized components in your Next.js app: /src/app/page.tsx import { MyComponent } from 'component-library-react/next';export default function Home() { return ( <> ... );} ##### ✅ Advantages[​](https://stenciljs.com/docs/server-side-rendering#-advantages "Direct link to ✅ Advantages") * All component props are available with their **resolved values** at runtime. * Props can be **computed dynamically** or retrieved from functions: const value = getValueFromAPI();return ; ##### ⚠️ Disadvantages[​](https://stenciljs.com/docs/server-side-rendering#%EF%B8%8F-disadvantages "Direct link to ⚠️ Disadvantages") * **Nested Stencil components** may fail to render correctly on the server. * Components using slots may confuse Next.js's `BAILOUT_TO_CLIENT_SIDE_RENDERING` template tags as entries #### Compiler-Based SSR[​](https://stenciljs.com/docs/server-side-rendering#compiler-based-ssr "Direct link to Compiler-Based SSR") With this approach, the `@stencil/ssr` package pre-processes your application during the build step to wrap and serialize Stencil components for server-side rendering. To enable it, wrap your Next.js configuration using the `stencilSSR()` helper: next.config.js import stencilSSR from '@stencil/ssr/next';/** @type {import('next').NextConfig} */const nextConfig = { // your base config};export default stencilSSR({ module: import('component-library-react'), from: 'component-library-react', hydrateModule: import('component-library/hydrate'), serializeShadowRoot: { scoped: ['my-counter'], default: 'declarative-shadow-dom', },})(nextConfig); > 📌 **Note:** The integration import path is `@stencil/ssr/next`. ##### ✅ Advantages[​](https://stenciljs.com/docs/server-side-rendering#-advantages-1 "Direct link to ✅ Advantages") * More **reliable SSR** for Stencil components rendered in the **light DOM**. * Avoids hydration mismatch issues commonly seen with client-heavy components. ##### ⚠️ Disadvantages[​](https://stenciljs.com/docs/server-side-rendering#%EF%B8%8F-disadvantages-1 "Direct link to ⚠️ Disadvantages") * Since components are pre-rendered at **build time**, **runtime values** (e.g. function calls or dynamic props) are not available: // ✅ Static objects are fineconst staticProp = { key: 'value' };// ❌ Dynamic values will not be resolvedconst runtimeValue = computeAtRuntime();return ; * Components using **slots** may render incorrectly due to internal Next.js behavior, such as injected `