# Dynamic import build time template only components

**URL:** <https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283>\
**Category:** Ember CLI\
**Created:** [October 13, 2020, 3:59pm UTC](https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283 "2020-10-13T15:59:47Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![betocantu93](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/betocantu93/32/16586_2.png) [@betocantu93](https://discuss.emberjs.com/u/betocantu93)\
**Post date:** [October 13, 2020, 3:59pm UTC](https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283/1 "2020-10-13T15:59:47Z")

</div>

Hello, I’m building a new hbs strategy for ember-svg-jar and wonder if it would be possible to dynamic import template only components?

[Hbs strategy](https://github.com/ivanvotti/ember-svg-jar/pull/166)

The idea is to create a component which dynamic import template only components created at build time

```nohighlight
export default class SvgComponent extends GlimmerComponent {
  constructor() {
    super(...arguments);
    this.loadSvg(this.args.name);
  }

  loadSvg(name){
    if(!CACHE.has(name)) {
        return import(name).then(comp => CACHE.set(name))
    }
  }
}

```

```nohighlight
{{#unless this.isLoading}}
 {{component this.args.name}}
{{/unless}}

```

Would something like is viable with ember-auto-import?

---

<div class="post-metadata">

**Author:** ![ef4](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/ef4/32/13470_2.png) [@ef4](https://discuss.emberjs.com/u/ef4)\
**Post date:** [October 14, 2020, 9:10pm UTC](https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283/2 "2020-10-14T21:10:30Z")

</div>

As long as we’re talking about octane-style co-located templates, being template-only doesn’t really affect this question. Template-only components still preprocess into javascript modules that, from the outside, look indistinguishable from components that have separate JS and HBS.

Today ember-auto-import can only import things from NPM packages that are _not_ ember addons. The reason is that ember-addons have their own idiosyncratic way of getting modules into the build, and trying to auto-import them would be redundant with that. In contrast, embroider _does_ do the thing you want here, which is why it’s designed around the v2 addon format that is designed to be analyzable.

Under embroider, the thing you show would basically work in terms of loading components the first time they’re needed. There’s no need for your own `CACHE`, because ES modules guarantee only-once evaluation – calling `import()`a second time doesn’t load or run the code twice. After loading a component, to make it invocable in a template you’d still need to call `define` (see [Load Ember-addons on demand from main application - #4 by ef4](https://discuss.emberjs.com/t/load-ember-addons-on-demand-from-main-application/17576/4)), at least until Ember lets us directly invoke component classes (which I expect is coming soon).

But I don’t think you should always use dynamic `import()` for every SVG. That adds asynchrony and potentially more network requests when it isn’t truly wanted. If you just compile all SVGs to template-only components, there’s really no step two. People could invoke the components directly, and Embroider would include only the ones that are used, and they will split correctly into multiple bundles if people are splitting up their apps, etc.

A lot of the work svg-jar needs to do today is only needed because of the lack of such a general-purpose, pull-based build system. Once we have that, svg-jar can be much simpler. I think ideally it would only need to be a preprocessor that rewrites SVG files to HBS files, adding `...attributes` like in your linked issue.

---

<div class="post-metadata">

**Author:** ![betocantu93](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/betocantu93/32/16586_2.png) [@betocantu93](https://discuss.emberjs.com/u/betocantu93)\
**Post date:** [October 15, 2020, 6:28am UTC](https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283/3 "2020-10-15T06:28:29Z")

</div>

Thanks for the detailed answer @ef4 and your continuos work, looking forward for the upcoming features…

> People could invoke the components directly, and Embroider would include only the ones that are used, and they will split correctly into multiple bundles if people are splitting up their apps, etc.

I totally agree and I’m glad that embroider with splitting would practically solve most of the scenarios… as long as the usage is statically analyzable, i.e. `<Svg::MyCar />` or using AST at build time `<Svg @name="my-car" />`

But what if we need to support a dynamic scenario?

AFAIK, unused components will be “trimmed” or tree shacked, so in that case I think a dynamic import is the only way? (unless of course you bundle everything) i.e.

`<Svg @name={{this.model.picture}} />`

`{{component this.args.name}}`

> But I don’t think you should always use dynamic `import()` for every SVG

I agree, static usage would be encouraged for splitting, but for this use case I want to kind of “mimic” the DX around the default `<img src="my-car.svg" />` behaviour

Thanks again

---

<div class="post-metadata">

**Author:** ![melsumner](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/melsumner/32/16411_2.png) [@melsumner](https://discuss.emberjs.com/u/melsumner)\
**Post date:** [August 9, 2021, 8:39pm UTC](https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283/4 "2021-08-09T20:39:34Z")

</div>

@ef4 coming back around to this thread for some extra clarification.

Let’s say someone is working on an icon component as part of a UI addon for their whole company to use. I don’t think I’d expect anyone to design a template-only component that just puts `...attributes` on the svg in the hbs; they’d likely want to deliver something that gives better guidance/guard rails. Especially if a lot of folks will be using the UI addon.

In the end, the icon component will probably need to provide a few things that are customizable- if an SVG is used, then things like `fill`, `height` and `width` (and the dimensions would feed `viewBox` values) are things you might want to allow a developer to indicate when they use the component. Also, they would probably want to generate a unique `id` for each (something that should be dynamically generated).

Is there a template-only answer to something like this? Thanks in advance for clarifying!

---

<div class="post-metadata">

**Author:** ![ef4](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/ef4/32/13470_2.png) [@ef4](https://discuss.emberjs.com/u/ef4)\
**Post date:** [August 9, 2021, 10:38pm UTC](https://discuss.emberjs.com/t/dynamic-import-build-time-template-only-components/18283/5 "2021-08-09T22:38:00Z")

</div>

The original post was asking how to dynamically load template-only components. My reply was that there’s nothing special about template-only components when it comes to how you’d load them. Under embroider, you can dynamically load any component. And since the above was written, we released ember-auto-import 2.0 which lets you dynamically import components out of v2 addons even without switching your app to embroider.

Your question is about how much can be done with template-only components.

Firstly, there’s no pressure to use template-only components. They’re appropriate sometimes but not all times, and JS-backed Glimmer components are a first-class part of Octane-edition Ember.

Second, I think we should be precise about what we mean by template-only. One meaning is “a component with no javascript” and another is “a component with no backing class”. Traditionally in ember those collapsed into one concept, because if you want to have any Javascript you need to create a backing class. But that is not true for proposed formats like GJS, where you can make locally-scoped helpers, modifiers, and components and then invoke them from the template, all without ever making a `class extends Component {}`.

As an illustrative example, imagine you want to both offer a default `fill` _and_ assert that any developer-provided fill satisfies a11y contrast requirements within your design system. I can see doing that with a template-only component like this:

```nohighlight
import { fillFor } from '@bigco/theme-system';

<template>
  <svg fill={{fillFor "icon" @fill}}>Your Icon Here</svg>
</template>

```

I’m using the proposed GJS format as implemented in [GitHub - ember-template-imports/ember-template-imports: Template import support in Ember!](https://github.com/ember-template-imports/ember-template-imports).

The use of the ES import makes it clearer where your theme rules are coming from. `fillFor` would be implemented as a helper. And even though this is a “template-only component”, if you needed a little Javascript to glue things together or adjust them, you could have some, even though your component is still just a template with no JS class:

```nohighlight
import Theme from '@bigco/theme-system';

function fillFor(userFill) {
  return Theme.find("new-mobile").fillFor("icon", userFill);
}

<template>
  <svg fill={{ (fillFor @fill) }}>Your Icon Here</svg>
</template>

```

In this second example, I’m assuming [Default Helper Manager by NullVoxPopuli · Pull Request #756 · emberjs/rfcs · GitHub](https://github.com/emberjs/rfcs/pull/756) which eliminates the need to wrap our `funciton fillFor` in Ember’s `helper()` utility.
