4

I'm trying to insert an image into a Web Component I'm building with Stencil.

I'm getting 2 errors:

AppLogo is declared but its value is never read.

and

Cannot find module ../assets/logo.svg.

Directories:

- src
-- components
--- app-header
---- assets
----- logo.svg
---- app-header.tsx
---- app-header.scss
---- app-header.spec.ts

Code:

import { Component } from "@stencil/core";
import AppLogo from "../assets/logo.svg";

@Component({
  tag: "app-header",
  styleUrl: "app-header.scss"
})

export class AppHeader {
  render() {
    return (
      <header class="app-header">
        <a href="#" class="app-logo">
          <img src="{AppLogo}" alt="App Name" />
        </a>
      </header>
    );
  }
}

There's not a ton of documentation around this (that I can find). So, any help is appreciated.

Aaron Benjamin
  • 1,291
  • 3
  • 18
  • 27

1 Answers1

14

Quite some things that went wrong here.

import AppLogo from "../assets/logo.svg";

You can't just import a .svg file into Javascript. What do you expect AppLogo to contain when you import it like that? Normally when you import a .js, .jsx or .tsx file that way, somewhere in those files there is an export specified. So you know when you import from that file, you'll get whatever you exported. There is no export in a .svg though.

Your usage is also wrong:

<header class="app-header">
  <a href="#" class="app-logo">
    <img src="{AppLogo}" alt="App Name" />
  </a>
</header>

First of all get rid of the " around {AppLogo}. You want to use the value of {AppLogo}- not use a string containing {AppLogo}.

Now there are two ways to achieve what you want:

The assets way

Somewhere in the root of your project, there's a stencil.config.ts file. In there you can specify copy tasks. You can read here how to do this: https://stenciljs.com/docs/config#copy

After you set that up correctly and your ../assets/ folder is being copied to your build folder, you can just use the image by putting in the path as the src:

<header class="app-header">
  <a href="#" class="app-logo">
    <img src="./assets/logo.svg" alt="App Name" />
  </a>
</header>

The Rollup way

You can also use Rollup to import it. Stencil is using Rollup as its module bundler. The stencil.config.ts is basically a rollup.config-file. You can find a lot of documentation on rollup here: https://rollupjs.org/guide/en#configuration-files

There are some rollup plugins that support importing .svg files:

  • rollup-plugin-svg
  • rollup-plugin-svgo
  • rollup-plugin-svg-to-jsx

If you use any of those, you'll be able to import your .svg files. Depending on which plugin you use AppLogo will contain something different.

For example rollup-plugin-svg-to-jsx will give you a ready-to-use JSX-tag when importing. So after you do

import AppLogo from "../assets/logo.svg";

You'd be able to use it like:

<header class="app-header">
  <a href="#" class="app-logo">
    <AppLogo />
  </a>
</header>
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Schadenn
  • 854
  • 1
  • 9
  • 20
  • Could you give a fuller example of how the Assets Way can be configured/implemented? The official docs unfortunately don't explain how assets such as images are to be handled. – bcody Aug 06 '19 at 14:43
  • @bcody I think the official docs do contain a lot of information about the topic (or is there anything in particular you're having trouble with?): https://stenciljs.com/docs/copy-tasks – Schadenn Aug 09 '19 at 13:41
  • The official docs don't show how that all works when the StencilJS project is built and integrated with some other application. From my current understanding, StencilJS can only copy resource files into the dist directory which end up being packaged into the NPM artifact, but they won't be compiled in any way into the web component's JS module. If the app wants to use the resource files, it will need to reference the "collections" dir in the NPM package and somehow integrate that. – bcody Aug 14 '19 at 14:12
  • @bcody That's correct. If you want to compile assets into the JS module, you'll have to use the other (Rollup) way. – Schadenn Aug 15 '19 at 13:19
  • 1
    The Rollup way doesn't really have to do anything with Stencils build pipeline in particular, that's why you won't find any information in the official docs. Just look for some information on Rollup or search for a Rollup plugin that handles loading of the filetype you want to compile into the JS code. Or maybe even write your own Rollup plugin - depending on what you want to do it might not even be that hard. Documentation on how to get Rollup plugins into Stencils build process are in the official docs however. https://stenciljs.com/docs/plugins – Schadenn Aug 15 '19 at 13:25