StencilJS 'dist' vs 'dist-custom-elements': Resolving Asset URLs in Subpath Deployments
0 reputation · 08 Jan 2022, 05:57 UTC
0 reputation · 08 Jan 2022, 05:57 UTC
The goal is to ensure that images, fonts, and CSS referenced by components load correctly when a StencilJS application is deployed to a subpath (e.g., /app/) rather than the site root. In development, stencil dev serves components with unminified CSS and absolute URLs, which masks the issue. However, the production build with outputTargets: ['dist', 'dist-custom-elements'] minifies assets and may strip or rewrite relative paths, resulting in 404 errors for assets referenced inside the bundled dist-custom-elements script. The ambiguity lies in how Stencil resolves relative URLs against the script location when the application is served from a non-root path, and whether a configuration option exists to override this behavior.
Key constraints include the need to support static hosting or CDN deployment, the use of relative asset references within component templates, and the lack of explicit documentation for subpath handling in the dist-custom-elements target.
Unresolved questions:
dist-custom-elements target?35275 reputation · 08 Jan 2022, 06:45 UTC
StencilJS does not provide a built-in basePath or publicPath configuration in stencil.config.ts to globally rewrite asset URLs during the build process. When using the dist-custom-elements target, the browser resolves relative asset paths against the current page URL, not the location of the hosted JavaScript bundle. This is why assets load correctly in stencil dev (which uses a dedicated dev server) but fail with 404s when deployed to a subpath like /app/.
In a production build, references to assets in your JSX/TSX templates are treated as static strings. If you use src="./assets/image.png", and your page is hosted at example.com/app/index.html, the browser attempts to fetch the image from example.com/app/assets/image.png. However, if your build artifacts are structured differently or hosted on a CDN, this path will be invalid.
Since Stencil does not perform build-time URL transformations for these targets, you must implement a dynamic path resolution strategy. The most reliable method is to define a global configuration variable that is set at runtime or injected during your CI/CD pipeline.
// src/utils/paths.ts
const ASSET_BASE_PATH = window.location.origin + '/app/build/assets/';
export const getAssetUrl = (path: string) => `${ASSET_BASE_PATH}${path}`;
In your component:
import { getAssetUrl } from '../../utils/paths';
render() {
return <img src={getAssetUrl('logo.png')} />;
}
dist-custom-elements folder. Confirm that asset paths remain exactly as written in your source code; Stencil will not rewrite them automatically.To provide a more tailored build-time transformation (such as a custom Webpack or Rollup plugin), please specify if you are using a custom build pipeline or relying solely on the stencil build command.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.