DEV Community

v-moe
v-moe

Posted on

Reducing JS code in your Vue bundle

I recently got a typical task for a UI component library.
Creating an atomic video component.

Not hard to achieve, take an embed url for example one of those from Youtube and set it as the src attribute of an iframe.

As a requirement there should be a default width-to-height ratio on the iframe and the possibility to customize it.

The following code examples are simplified.

My first approach is probably what would occur first to every Vue dev put in front of this problem.

<script setup lang="ts">
interface Props {
  url: string
  ratio?: [number, number]
}
withDefaults(defineProps<Props>(), {
  ratio: () => [776, 437],
})
</script>

<template>
  <iframe
    :src="url"
    :style="{ aspectRatio: `${ratio[0]} / ${ratio[1]}` }"
  />
</template>
Enter fullscreen mode Exit fullscreen mode

This exposes a nice API, wehere the customer can customize the ratio like this

<UiVideo url="somewhere" :ratio="[3, 1]"/>
Enter fullscreen mode Exit fullscreen mode

But we have added a prop and silently a computed prop just for a CSS property value.

Not a big deal in an SPA but what if you are building a site where you want your JS to be as small as possible?

Well we could use Astro of course ;-)

But what if not?

A teammate came up with a great idea, it avoids the JS at the price of a tiny little bit of extra CSS!

<script setup lang="ts">
interface Props {
  url: string
}
</script>

<template>
  <iframe :src="url" style="aspect-ratio: var(--video-ratio, 776 / 437)" />
</template>
Enter fullscreen mode Exit fullscreen mode

The extra prop is gone!
Consuming the component and customizing the ratio will now look like

<UiVideo url="somewhere" style="--video-ratio: 3 / 1"/>
Enter fullscreen mode Exit fullscreen mode

You can also create a CSS class and apply that instead of using an inline style of course.

Really convenient! While I think that the first version is still a bit more developer friendly (TS + your IDE will suggest ratio as a prop when you start typing <UiVideo ...) the second does everything you actually need and is even cleaner from some point of view (CSS from style or class, data + logic from props)

In a big SPA where initial page load performance is not an issue, I would still prefer the first version though, maybe I still have to get used to this great pattern that leverages the power of CSS custom props.

Good documentation and a reliable CSS props naming strategy is absolutely necessary to make this scale and not become messy.

Top comments (1)

Collapse
 
kissu profile image
Konstantin BIFERT

CSS is usually the way to go if it's powerful enough, otherwise a good ol' piece of JS does the job well too!