I am pretty new to JavaScript and just playing around with web components. Now it’s not clear to me about importing different web components and how to do it a correct way, if there is a correct way. Maybe you could take a look on a way how I do it until now and tell me some advantages and drawbacks according to it, it would be great. If you think I am doing it wrong I would appreciate if you could show me the way and explain why is it better.
1st method (feeling wrong):
class WorkPanel extends HTMLElement {
//stuff in here
}
window.customElements.define('work-panel', WorkPanel)
and
class Sidebar extends HTMLElement {
//stuff in here
}
window.customElements.define('side-bar', Sidebar)
index.html
<body>
<side-nav></side-nav>
<work-panel></work-panel>
<script type="module" src="javascripts/workPanel.js"></script>
<script type="module" src="javascripts/sideNav.js"></script>
</body>
2nd method
it differs from the first one as I have an index.js where I have the content and it’t the module itself containing the web components.
import './javascripts/sideNav.js'
import './javascripts/workPanel.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
div.content {
display: block;
}
div.sidebar {}
div.workpanel {}
</style>
<side-nav class="sidebar"></side-nav>
<work-panel class="workpanel"><work-panel/>
`;
class SiteContent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open"})
this.shadowRoot.appendChild(template.content.cloneNode(true))
}
}
window.customElements.define('site-content', SiteContent)
index.html
<body>
<site-content></site-content>
<script type="module" src="index.js"></script>
</body>
Is it better to have multiple modules loading each component or one module loading all components. How could it affect the performance or potentially the architecture later?
Thanks in advance
2
Answers
Preamble
You should not worry about performance unless you notice significant underperformance. Even then, don’t optimize every detail but only the aspects that matter, identified by measuring, analyzing and benchmarking.
Both ways ensure the execution order of your scripts.
Index
<script>
elementA single script that imports others has to be (partially?) downloaded before downloads of the others can start.
This could result in theoretically slower loading times, but practically it shouldn’t affect loading times significantly, if at all.
A benefit of a distinct script per page is arguably better organization: All of a page’s code is contained in a single "entry point" JS-only file. Any small code may be included as well, instead of having to link yet another small script.
Keeping a more lightweight HTML due to "deferred linking" may result in earlier page rendering.
Individual
<script>
elementsLinking all resources explicitly provides the browser with all relevant URLs during initial scan/parse of the HTML. This may result in faster loading times.
Also, individual linking makes for robust imports of independent scripts: If a script that imports others fails to download, then those imports won’t happen.
Linking all resources in the
<head>
section provides an overview of all dependencies with a quick glance at the HTML, which may be preferable.Theoretically, many small scripts from the same origin may be downloaded slower than one large script, because many individual request have to be sent. This means: If possible, you should bundle as many scripts as possible.
However, a single large script tailored to each page individually is also not beneficial: Resources can be cached, but if those aren’t ever re-used than caching them is pointless.
Note: Scripts with
type=module
are deferred, so linking them late instead of early only prevents the browser to preload the resource. You should always link resources early (i.e. in<head>
), and maybe even use<link rel=preload>
for large resources.The is no better way; there is only your way, depending on your requirements
Note:
<template>
can be great, but are not required, your code can be condensed:Dependencies
If you have dependenies, where Component B can only work when Component A is loaded;
use:
customElements.whenDefined
https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/whenDefined