10. Script Block - ES Modules
We have seen that if you are not careful, it can be very easy to overwrite classes and functions. Is there really no way to solve this? Yes! The solution lies in ES Modules. Unfortunately, WEM widgets were built before ES Modules became widely adopted. However, while it may not be perfect, using the building blocks that WEM provides can get you close enough if you know what you are doing. ES Modules is a feature in JavaScript that helps encapsulate code, making it possible to use imports and exports to manage sections of code. Let’s see how this can help us fix naming collisions once and for all!
Let’s imagine we have two separate JavaScript modules, each containing a function with the same name.
Normally, we would encounter a problem if we embedded these files using scriptreference
. The first issue is naming collisions, and the second is that the export
keyword is reserved for use in a module. To use both functions, we need to import them. There are two ways to do this: one is with <script type="module">
, and the other is with the import()
function. Unfortunately, while using the <script>
tag is the easiest method, we cannot use it due to the way the WEM runtime handles loading dynamic scripts. Therefore, we are limited to using import()
. The challenge with this approach is that it is an asynchronous function. In theory, the widget could be unloaded from the page by the time this function resolves, so we need to account for that as well.
We import our JavaScript module dynamically using the import()
function. When the script is loaded, the .then()
function is called, with the first argument being the loaded module. We use destructuring syntax { setHelloText }
to extract our function from the module.
Since calling import()
is asynchronous, there is a possibility that the widget may have already been removed by the time this function finishes loading the module. Therefore, we perform a simple check with if (enEl.parentNode)
, which verifies that the parentNode
is not null
. This ensures that the element is still attached to the DOM and that the widget has not been removed.
Note Widget Using ES Modules
If we update our Note widget to use ES modules, we can revert to using class Note
instead of class WemAcademyNote
, without worrying about another widget using the same class name. Our updated initialization code now looks like this:
Once again, due to the asynchronous nature of the import()
function, we need to handle some race conditions. In the startupscript
, within the then()
code block, we check if (window[symbol] !== "loading")
. If this condition is true, we know that unloadscript
has been called before the module has finished loading. This is because, at the end of unloadscript
, we delete window[symbol]
, which sets its value to undefined
. A similar check in the unloadscript
is if (note !== "loading")
. If this condition is true, we know that the module has been loaded before unloadscript
was called, and the value of window[symbol]
has been set to a new Note()
, allowing us to safely call note.dispose()
.
Last updated
Was this helpful?