DEV Community

The Vanilla Javascript Component Pattern

megazear7 on July 29, 2018

I started delving into web components about a year ago. I really liked the idea of getting a reference to a custom element and then calling methods...
Collapse
 
davidmulder profile image
David Mulder

There are indeed situations where it's sensible not to use libraries or frameworks, but those situations are rare and should only ever be touched upon by experienced senior developers. If I gave the code presented in this blog post to most of my colleagues I can guarantee that within a couple of months it will be completely and utterly unmaintainable. I am not sure I would be able to keep this code clean. This reminds me of the messes we had 10+ years ago.

If anything I think this blog post represents the trap most passionate (and often inexperienced) developers fall in (including me). We hate the overhead of libraries and/or think we can do better. It's good to reinvent the wheel once every while, because it's possible to improve, but we shouldn't reinvent the wheel ever single time we build a car. If the goal is to make private components for a project with a strong data pressure forget about web components and pick any library in the react-style (be careful with your transpilation settings). If you don't care about the amount of data go for a library in the angular-style. And if the component should be used by lots of people go for web components (including huge polyfill), or if the data thing is a huge problem make it a backend rendered component (yes, there is still a place for those).

The only thing you should never do (professionally) is go at it vanilla. There is nothing inheritly better about vanilla. Vanilla is just the set of base libraries decided upon by a small group of people. What's important is to pick the right set of tools. I mean, I get how tempting vanilla is and sometimes it can be the right set of tools if the requirements are extreme enough. Years ago I build a private application that actually performed and looked like native on mobile when that claim was still just an empty promise. The cost was that it was 100% unmaintainable.

Point is, I don't think you are doing anybody a favor with a post like this. It will just put more inexperience developers on the wrong path.

Collapse
 
quanla profile image
Quan Le

I agree that Vanilla component is a wrong and amateur idea, but, my friend, I think you are too fond of using frameworks, and that is much greater threat to your projects and your career.

I have 14+ years of experience and was a heavy framework user once, but now I only have ReactJS and NodeJS in my toolbox. Most frameworks today are created by amateurs that dont know how to solve problems in a simpler way, and promoted/adopted by a huge community of amateurs who know no better but love to make noise.

Don't start with questioning my skills or capabilities, I finishes hundreds of man month effort in days

Collapse
 
puritanic profile image
Darkø Tasevski

I would love to see your comment on reddit :)

Thread Thread
 
quanla profile image
Quan Le

Sorry, but I don't know what you mean, I which reddit post?

Thread Thread
 
puritanic profile image
Darkø Tasevski

r/reactjs, r/programming, r/javascript :) No post in particular but it would be fun to watch as your comment gets downvoted into oblivion.
Do you really think that Facebook's React team and Google's Angular team are made of amateurs? Lol

Thread Thread
 
quanla profile image
Quan Le

Ha ha. That should be fun. I would love to see it too. Pretty sure it will happen. About Angular and React team, I dont think they are amateurs, but still, our definition of amateur are very different

Collapse
 
kepta profile image
Kushan Joshi • Edited

David couldn’t agree with you more.
Code Maintainabilty is the most underrated thing in the world. While doing something like making a fancy vanilla Javascript is cool and will get you some pat on the back, it is not pragmatic and I doubt you would ever use beyond more than a blog post example.

Collapse
 
megazear7 profile image
megazear7 • Edited

I think frameworks work very well in software focused small to medium sized companies that can scope out there technological future very well, and can cultivate teams experienced in the framework that fits their scenario. However, imagine a scenario where you are working on something for a very large non-software focused company. You can't introduce a framework as the scope of the work is too small to make such long lasting decisions. You also want to build something that is still relevant 5 years down the line. You don't know who will be working on it or what there expertise will be. The platform stays relevant forever, frameworks do not. However like I said, frameworks provide an amazing benefit when used in an organizations that, you might say, respects their power.

So I think we might see eye to eye on this, if provided a specific scenario to problem solve for. However the only thing I would really take issue with is maintainability. If certain rules are followed in regards to what code is responsible for what, then this is certainly maintainable. JavaScript by it's nature has always been poor at enforcing separation of concerns, leaving it up to self governance from the developers. Luckily this is changing in updates to the language and web components.

Collapse
 
jmyrons profile image
jmyrons

This is the approach I have used and advocated for for the last 10 years however 'class' was not available until ecmascript 6 so I have learned how to do it using what's available by leveraging the power and nature of first class functions, closures, and the other features available in the Javascript language in the earlier versions of ecmascript. I applaud your approach because I have always written Javascript with the intent to avoid making my code dependent on frameworks and libraries. It would be nice if companies would come to realize this is the better approach to writing frontend code and not insisting on the use of frameworks!

Collapse
 
megazear7 profile image
megazear7

I absolutely agree, especially with the comment about what companies are looking for. I keep in contact with a few recruiters in order to stay in touch with what companies are looking for. I don't know how many times I've had to explain to a interviewer that they need to look for people competent in the JavaScript language, not for people who have committed themselves to a particular framework.

Collapse
 
misterhtmlcss profile image
Roger K.

Now even as a junior developer I can attest to that frustration. It's crazy how focused they are on platform skills when that's just a doc away from doing x or y. I spend so much time trying to develop my JavaScript skills now. I don't even like calling myself a front-end developer because I feel like it had a frivolous connotation, like I can only do HTML, CSS and MAYBE a bit of JS. I'm like no, I love JS and I'm good at it. Anyway great article, but the discussion had been even more enjoyable.

Collapse
 
vitalyt profile image
Vitaly Tomilov

In the same spirit, to create DOM components in pure JavaScript, I implemented a small library just to wrap all my code into DOM components, per se:

github.com/vitaly-t/excellent

You still write everything directly for DOM, but it helps with reusability + lifespan + isolation.

Collapse
 
cashpipeplusplus profile image
cashpipeplusplus

Using innerHTML like this looks like a massive XSS vulnerability waiting to happen. Please don't do components like this. Your users will suffer the consequences when your page contents get hijacked.

Collapse
 
misterhtmlcss profile image
Roger K.

I thought innerHTML was only an issue if you were applying it with user input? I thought if it's my code and my data then I can use innerHTML. Crap! Please give me a link or a little more on this as I'm using it wrong and I thought I was being careful.

Collapse
 
cashpipeplusplus profile image
cashpipeplusplus

Of course, it is possible to use innerHTML without an XSS vulnerability, but it's much easier to reduce your XSS attack surface when you don't use it at all. You have to make that call for your project.

In my professional JS projects, we aren't building an end-user application, and we won't ultimately be in control, so we ban the use of innerHTML project-wide.

As an alternative, you can/should construct individual elements with createElement, and use innerText or createTextNode for the textual parts. For example:

const div1 = document.createElement('div');
div1.appendChild(document.createTextNode('It may be a pain, but this is '));

const em1 = document.createElement('em');
em1.innerText = 'worth';
div1.appendChild(em1);

div1.appendChild(document.createTextNode(' it!'));

document.body.appendChild(div1);

But if you find yourself doing this often... consider doing something else, like using a templating library or something. When we use this pattern at work, we're building a middle-ware library that constructs a DOM hierarchy with UI controls for something the app developer is building. It could have been done as a web component, but we just fill in an app-supplied div instead. There's not much text involved, except for labels and aria attributes, so it's not terribly burdensome. YMMV.

Thread Thread
 
megazear7 profile image
megazear7

I have updated the contents of this blog on the source blog post to more directly address and discuss some of these concerns: alexlockhart.me/2018/07/the-vanill...

I agree, in most cases a trusted template library should be used. The point I wanted to stress in the blog post is that I think that in my opinion template literals should be the preferred method of rendering html from JavaScript, and that libraries can be layered on top of that basic scheme.

Collapse
 
megazear7 profile image
megazear7

Correct you would need to do both JS and HTML encoding for security reasons. Ideally using a template library would also alleviate many conerns as well.

Collapse
 
hamzahamidi profile image
Hamza Hamidi

It's always fun to see a new VanillaJs component approach. You could also use Inheritance to reduce the amount of line in the CTOR, introduce lifecycles. But this could also become quickly unmaintainable.

Collapse
 
tscherrer05 profile image
tscherrer05

Great article !
Small mistake in your second example. It should be :
get title() {
return this.titleValue;
}

Collapse
 
lgraziani2712 profile image
Luciano Graziani

I like this! Thank you.

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
megazear7 profile image
megazear7

Yep, I think as a JavaScript community we've haven't done a good enough job teaching people when to apply patterns and when to integrate frameworks.

Collapse
 
quanla profile image
Quan Le

This post is great if you don't know what Reactive programming or how it can hugely improve your app architecture

Collapse
 
megazear7 profile image
megazear7

I think updating DOM in a reactive way would be a great addition instead of rerendering the whole template each time. How might you suggest integrating reactive programming into the pattern I've described in the post?

Collapse
 
quanla profile image
Quan Le

I am not suggesting, ReactJS has done this very well (updating Dom in a reactive way) and it is 1 of the lib that I have to keep in my toolbox these day

Collapse
 
frankdspeed profile image
Frank Lemanschik

@megazar7 you inspired me to introduce a other usefull pattern what do you think about that? dev.to/frankdspeed/the-html-compon...

Collapse
 
studiospindle profile image
Remi Vledder

Interesting approach. Using MVC to make this setup would perhaps be more scalable. Any thoughts on this @megazear7 ?

Collapse
 
gypsydave5 profile image
David Wickes

Schemes and patterns are always better than frameworks and libraries, as I say all of the time.

Amen.