Skip to main content
Version: v5 (Preview)

Stencil Config

Most projects need little or no configuration. Stencil's defaults cover the common case: a project with no stencil.config.ts at all builds as a component library, with the loader-bundle output. Keep the config as small as you can. Every property below is optional.

Example stencil.config.ts:

import { Config } from '@stencil/core';

export const config: Config = {
namespace: 'MyApp',
srcDir: 'src'
};

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​

default: '.stencil'

The directory where sub-directories will be created for caching when enableCache is set true.

A Stencil config like the following:

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

export const config: Config = {
...,
enableCache: true,
cacheDir: '.cache',
}

Will result in the following file structure:

stencil-project-root
└── .cache
└── .build <-- Where build related file caching is written

collections​

default: []

npm packages whose collection output this project should compile in alongside its own components.

stencil.config.ts
export const config: Config = {
collections: ['@my-org/design-system'],
};

Without this option, a collection is only picked up from a side-effect import (import '@my-org/design-system';) somewhere in your source.

devServer​

Please see the Dev-Server docs.

docs​

Please see the docs config.

enableCache​

default: true

Stencil will cache build results in order to speed up rebuilds. To disable this feature, set enableCache to false.

enableCache: true

excludeComponents​

default: []

An array of component tag names to exclude from production builds. Useful to remove test, demo or experimental components from final output.

Supports glob patterns for matching multiple components:

  • ['demo-*'] - Excludes all components starting with "demo-"
  • ['*-test', '*-demo'] - Excludes components ending with "-test" or "-demo"
  • ['my-component'] - Excludes a specific component

Components matching these patterns will be completely excluded from all output targets when not using the --dev flag.

compat​

Please see the Compat docs.

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, Env, Host } from '@stencil/core';

@Component({
tag: 'api-component',
})
export class APIComponent {
async connectedCallback () {
const res = await fetch(Env.API_BASE_URL)
// ...
}
}

generateExportMaps​

default: false

Set to true to have production builds write an exports map into your package.json, with an entry for each thing your library publishes:

EntryPoints atGenerated when
.The loader-bundle entry, or standalone's if there's no loader-bundleeither is configured
./loaderThe lazy loaderloader-bundle
./standaloneThe standalone output's indexstandalone
./<tag>One entry per component, for example ./my-buttonstandalone
./componentsThe type definitions for every componenttypes
./ssrThe server-side rendering modulessr
./assets/*Component assets and global stylesheetsassets or global-style
generateExportMaps: true

Once a package has an exports map, consumers can only import the paths it lists, so my-library/dist/... imports stop resolving. Add any extra entries you need to package.json yourself. Stencil keeps entries it didn't generate, and removes the entry of a component that no longer exists.

globalScript​

The global script config option takes a file path as a string. If it isn't set, Stencil uses src/global.ts or src/global.js when one exists.

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​

default: undefined

A top-level path to a global stylesheet, predating the global-style output target. Setting globalStyle auto-generates a global-style output target for you, so it still works, but new projects should configure global-style directly instead - it supports more than one global stylesheet, a custom output filename, and control over shadow-root injection, none of which globalStyle alone gives you.

globalStyle: 'src/global/app.css'

hydratedFlag​

When using the loader-bundle output target, 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), 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​

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​

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​

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​

default: 'hidden'

This is the value which should be set for the property specified by property on all components before hydration.

initialValue: string

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​

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​

default: true in production

When true, the browser CSS file will be minified.

minifyJs​

default: true in production

When true, the browser JS files will be minified. Stencil uses Terser under-the-hood for file minification.

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​

Please see the Output Target docs.

plugins​

Please see the Plugin docs.

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.
*/

signalBacking​

default: false

Stores each component's @Prop() and @State() values in signals. Components need no changes. Other code can then subscribe to a component's props, and @Effect() methods track the component's own members.

signalBacking: true

sourceMap​

default: 'dev'

  • Set to true to always generate source maps,
  • Set to false to never generate source maps
  • Set to 'dev' to only generate source maps during development (--dev) builds.
sourceMap: true | false | 'dev'

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​

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​

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 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 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.

taskQueue: 'async'

transformAliasedImportPaths​

default: true

This sets whether or not Stencil should transform path aliases 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;

rolldownConfig​

default: {}

Passes custom configuration down to Rolldown itself, which replaced Rollup as Stencil's bundler in v5 (renamed from rollupConfig — run stencil migrate --dry-run to preview updating an existing config automatically). The config shape is flatter than the old Rollup-era rollupConfig — there's no more inputOptions/outputOptions nesting:

  • treeshake: boolean
  • external: a string, RegExp, array of either, or a function (source, importer, isResolved) => boolean | null | undefined

The old inputOptions.context, inputOptions.moduleContext, and outputOptions.globals options have no rolldownConfig equivalent.

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 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"]
}
}