See how Stencil fits into the entire Ionic Ecosystem ->
Stencil is part of the Ionic Ecosystem ->

Upgrading to Stencil v3.0.0

Getting Started

It's recommended that your projects start their upgrade from Stencil v2. Projects using Stencil v0 or Stencil v1 should upgrade to Stencil v2 before proceeding with this guide. For breaking changes introduced in previous major versions of the library, see:

For projects that are on Stencil v2, install the latest version of Stencil v3:

npm install @stencil/core@3

Updating Your Code

New Configuration Defaults

Starting with Stencil v3.0.0, the default configuration values have changed for a few properties.

SourceMaps

Sourcemaps are generated by default for all builds. Previously, sourcemaps had to be explicitly enabled by setting the sourceMap flag to true. To restore the old behavior, set the sourceMap flag to false in your project's stencil.config.ts:

// stencil.config.ts
import { Config } from '@stencil/core';

export const config: Config = {
  sourceMap: false,
  // ...
};

dist-custom-elements Type Declarations

Type declaration files (.d.ts files) are now generated by default for the dist-custom-elements output target. If your project is using dist-custom-elements and you do not wish to generate type declarations, the old behavior can be achieved by setting generateTypeDeclarations to false in the dist-custom-elements output target in your project's stencil.config.ts:

// stencil.config.ts
import { Config } from '@stencil/core';

export const config: Config = {
  outputTargets: [
    {
      type: 'dist-custom-elements',
      generateTypeDeclarations: false,
      // ...
    },
    // ...
  ],
  // ...
};

Deprecated assetsDir Removed from @Component() decorator

The assetsDir field was deprecated in Stencil v2.0.0, but some backwards compatibility was retained with a warning message. It has been fully removed in Stencil v3.0.0 in favor of assetsDirs. To migrate from existing usages of assetsDir, update the property name and wrap its value in an array:

@Component({
  tag: 'my-component',
- assetsDir: 'assets',
+ assetsDirs: ['assets'],
})

For more information on the assetsDirs field, please see the Stencil Documentation on assetsDirs

Drop Node 12 Support

Stencil no longer supports Node 12. Please upgrade local development machines, continuous integration pipelines, etc. to use Node v14 or higher.

Strongly Typed Inputs

onInput and onInputCapture events have had their interface's updated to accept an argument of InputEvent over Event:

- onInput?: (event: Event) => void;
+ onInput?: (event: InputEvent) => void;
- onInputCapture?: (event: Event) => void;
+ onInputCapture?: (event: InputEvent) => void;

event arguments to either callback should be updated to take this narrower typing into account

Narrowed Typing for autocapitalize Attribute

The autocaptialize attribute has been narrowed from type any to type string. This change brings Stencil into closer alignment with TypeScript's typings for the attribute. No explicit changes are needed, unless a project was passing non-strings to the attribute.

Custom Types for Props and Events are now Exported from components.d.ts

Custom types for props and custom events are now re-exported from a project's components.d.ts file.

For the following Stencil component

import { Component, Event, EventEmitter, Prop, h } from '@stencil/core';

export type NameType = string;
export type Todo = Event;

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true,
})
export class MyComponent {
  @Prop() first: NameType;

  @Event() todoCompleted: EventEmitter<Todo>

  render() {
    return <div>Hello, World! I'm {this.first}</div>;
  }
}

The following data will now be included automatically in components.d.ts:

  import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
  import { NameType, Todo } from "./components/my-component/my-component";
+ export { NameType, Todo } from "./components/my-component/my-component";
  export namespace Components {
      interface MyComponent {
        "first": NameType;
      }
  }
  export interface MyComponentCustomEvent<T> extends CustomEvent<T> {
      detail: T;
      target: HTMLMyComponentElement;
  }
  declare global {
      interface HTMLMyComponentElement extends Components.MyComponent, HTMLStencilElement {
  }

This allows those types to be easily accessed from the root of the type distribution:

import { NameType, Todo } from '@my-lib/types';

When using dist-custom-elements, these types can now be accessed from the custom element output:

import { NameType, Todo } from '@my-custom-elements-output';

This may clash with any manually created types in existing Stencil projects. Projects that manually create type definitions from components.d.ts will either need to:

  • remove the manually created type (if the types generated in components.d.ts suffice)
  • update their type creation logic to account for potential naming collisions with the newly generated types

Composition Event Handlers Renamed

The names of Stencil's composition event handlers have been changed in order to correct a casing issue which prevented handlers from being called when events fired. The changes are as follows:

previous name new name
onCompositionEnd onCompositionend
onCompositionEndCapture onCompositionendCapture
onCompositionStart onCompositionstart
onCompositionStartCapture onCompositionstartCapture
onCompositionUpdate onCompositionupdate
onCompositionUpdateCapture onCompositionupdateCapture

Output Targets

dist-custom-elements Output Target

Add customElementsExportBehavior to Control Export Behavior

customElementsExportBehavior is a new configuration option for the output target. It allows users to configure the export behavior of components that are compiled using the output target. By default, this output target will behave exactly as it did in Stencil v2.0.0. For more information on how to configure it, please see the documentation for the field.

Move autoDefineCustomElements Configuration

autoDefineCustomElements was a configuration option to define a component and its children automatically with the CustomElementRegistry when the component's module is imported. This behavior has been merged into the customElementsExportBehavior configuration field. To continue to use this behavior, replace autoDefineCustomElements in your project's stencil.config.ts with the following:

// stencil.config.ts
import { Config } from '@stencil/core';

export const config: Config = {
  outputTargets: [
    {
      type: 'dist-custom-elements',
-      autoDefineCustomElements: true,
+      customElementsExportBehavior: 'auto-define-custom-elements',
      // ...
    },
    // ...
  ],
  // ...
};

dist-custom-elements-bundle Output Target

The dist-custom-elements-bundle has been removed starting with Stencil v3.0.0, following the RFC process. Users of this output target should migrate to the dist-custom-elements output target.

By default, dist-custom-elements does not automatically define all a project's component's with the CustomElementsRegistry. This allows for better treeshaking and smaller bundle sizes.

For teams that need to migrate quickly to dist-custom-elements, the following configuration should be close to a drop-in replacement for dist-custom-elements-bundle:

// stencil.config.ts
import { Config } from '@stencil/core';

export const config: Config = {
  outputTargets: [
-    {
-      type: 'dist-custom-elements-bundle',
-      // additional configuration
-    },
+    {
+      type: 'dist-custom-elements',
+      customElementsExportBehavior: 'bundle'
+    },
    // ...
  ],
  // ...
};

However, it does not necessarily improve treeshaking/bundle size. For more information on configuring this output target, please see the dist-custom-elements documentation

Legacy Angular Output Target

Prior to the creation of the @stencil/angular-output-target, the 'angular' output target was the original means of connecting a Stencil component to an Angular application. This output target has been removed in favor of @stencil/angular-output-target. Please migrate to @stencil/angular-output-target and remove the 'angular' output target from your stencil.config.ts file. Instructions for doing so can be found in the Angular Framework Integration section of this site.

Stencil APIs

Stencil exposes Node APIs for programmatically invoking the compiler. Most users do not use these APIs directly. Unless your project calls these APIs, no action is required for this section.

Flag Parsing, parseFlags()

Stencil exposes an API for parsing flags that it receives from the command line. Previously, it accepted an optional CompilerSystem argument that was never properly used. The flag has been removed as of Stencil v3.0.0. To migrate, remove the argument from any calls to parseFlags imported from the Stencil CLI package.

import { parseFlags } from '@stencil/core/cli';
- parseFlags(flags, compilerSystem);
+ parseFlags(flags);

Destroy Callback, addDestroy(), removeDestroy()

The Stencil CompilerSystem interface has a pair of methods, addDestroy and removeDestroy that were previously misspelled. If your codebase explicitly calls these methods, they need to be updated. Replace all instances of addDestory with addDestroy and all instances of removeDestory with removeDestroy The functionality of these methods remains the same.

End-to-End Testing

Puppeteer v10+ Required

Versions of Puppeteer prior to Puppeteer version 10 are no longer supported. In newer versions of Puppeteer, the library provides its own types, making @types/puppeteer no longer necessary. Ensure that Puppeteer v10 or higher is installed, and that its typings are not:

$ npm install puppeteer
$ npm uninstall @types/puppeteer

To see which versions of Puppeteer are supported by Stencil, please see our support matrix

Need Help Upgrading?

Be sure to look at the Stencil v3.0.0 Breaking Changes Guide.

If you need help upgrading, please post a thread on the Stencil Forum.

BackNext
Contributors