How should you write a good component and how do you integrate it with many view engines such as React, Angular and Vue?

Nowadays it is pretty common to have multiple applications written in different frameworks and libraries — that is the case with Trio, we have React and Angular applications as well as Vue. We understand how hard it is to maintain consistency between components, libraries, and even useful functions across apps. It’s even harder task to do this with different view engines like a React App or an Angular App, right?

In this blog post, I’m going to show you some case studies on a few JavaScript components and how they can be integrated with different view engines.

p.s. for a better readability experience I’m using the word ‘view engine’ to represent ‘UI frameworks and libraries’.

First of all, what exactly is “Vanilla JavaScript”?

We call Vanilla JavaScript or just VanillaJS to refer to when plain language like JavaScript code is used without any additional libraries like jQuery or React, for example. Developers often joke, as a reminder, that sometimes we just don’t need to use extra libraries to do things.

p.s. to make it even funnier there’s a website for that… check it out.

So… why should I write a VanillaJS component instead of just writing one for each different view engine?

There are scenarios where you and your teammates should build the exact features across different view engines. If you encounter these scenarios, consider using these three distinct approaches:

1) To write different render packages for each view engine

This approach is all about you writing different packages even if they’re similar or even the same.

That’s when we have to stop and think… if we’re looking for easy maintainability, this is absolutely not the right path because you’ll have to deal with different packages with duplicated lines of code.


To follow this approach you need to create different JavaScript packages for every view engine even if they have similar lines of code.

e.g. Let’s pretend that you have to write a Video Player component for React, Vue, and Angular. You’ll end up maintaining three packages… one for each different view engine.

Real World Sample

In order to better demonstrate this approach, we have a couple of JavaScript packages with distinct API usage and features each, but both of them have the same goal, which is to provide a Video Player component:

Video React demo


Vue Video demo


Take a look at this React package’s file and also take a look at these lines of the Vue’s version… that’s what I meant when I said that you’d probably end up with duplicated lines of code. Both of them implemented a Full Screen feature.

2) To write a Core VanillaJS package + different render packages for each view engine

I know that, at first, this approach seems weird but it’s interesting especially if you have some lines of code beyond rendering (e.g. helpers functions).

If you do have some logic to share between the view engines, that’s a better approach than the first one when we think about maintainability, because even if you have to maintain a core package and one package per view engine, it is valuable since you wouldn’t have duplicated lines of code which makes it easier for changes affect all view engines at once.


In order to implement this approach, make sure to follow these steps:

  • Write a Core package which contains shared code between the view engines;
  • Write a render package for each of the different view engine and make use of the Core package when needed.

When using this approach, just make sure to strictly follow a versioning flow (e.g. semantic versioning) to avoid breaking code without awareness.

Releases versions of video-react JavaScript package

Real World Sample

There’s a great JavaScript package called DevExtreme Reactive that aims to build Data Tables with amazing features.

DevExtreme React Grid demos

It has several packages that depend on and compose each other.

DevExtreme Reactive packages

This is an excellent sample because this component currently supports two different view engines (React and Vue) and it also has a really nice sub-packages organization. They compose each other… I love this repo. 😌

3) To write a render VanillaJS package and integrate it with different view engines through wrapper packages

This approach aims to have a view engine agnostic core. In other words: it has its own render logic and works without any view engine dependency.

It could be a good catch if your component doesn’t have too much rendering complexity because you’d have to write it on your own without the help of view engines.

By using this approach, you’ll likely have:

  • Core package which is responsible for the Vanilla rendering;
  • Wrapper packages for each different view engine that use the Core package in order to render the component.

Real World Sample

We got a really nice sample about this approach: Final Form.

Final Form core repository

Like its description says: it’s a “Framework agnostic” component because it handles rendering logic just by itself. I really like this project because it handles the logic of when the form should be rendered but not DOM mutations… it’s up to you.

Final Form usage instructions

Final Form has a really great API documentation 😍. All public methods are very well described.

Final Form API documentation

Another amazing thing is that they’ve got the same samples:

Final Form Samples

And to prove that they don’t actually handle DOM mutations… they got a VanillaJS sample:

Final Form VanillaJS implementation 😍❤️

Adding to that, Final Form currently supports React & Vue, it’s an amazing project that follows this last approach.