External modules without bundling in typescript
Last week I finished the Preact-cli template and this week I begun on a project to make use of that template. I've decided to make a new website for spelmakare.se as practice before doing an actual new project using the template.
Background for today's problem
I wanted to be able to use external modules (such as dsteem) without the need to actually bundle the whole module with my own scripts. I've made attempts at this in the past and always had issues getting it to work consistently.
When creating the production script you can define modules you do not want included, and then those modules can be added externally with <script> tags in the html. The benefit is that you get a smaller script file for your site and that the module can be loaded from a distributed network, like cdnjs. The last bit is beneficial in particular, because if you have visited one site with a lib that another site also uses, in many cases your browser can use the cached file you already have from the first site.
This whole excluding thing is what has caused me issues in the past. Possibly because of my limited knowledge, but the result none the less the same... a day spent solving a technical issue like this, instead of swiftly making an actual project. If I got one module working, then the next has had some sort of failure and so forth.
Today I decided to get this solved.
Today's solution
After doing some research I cooked up this solution that fits my needs. It is easy to use, gives you full Intellisense when writing code and seems to be consistent in functionality.
I'm using dsteem as an example.
$npm install dsteem
We will not actually use dsteem in the code, we only install it to get the declarations. There are other ways to do this, but this is quick, simple and has no impact except increasing the file size of our node_modules folder a bit.
First we create a helper function to use when loading external scripts. You give the script tag an unique ID and the url to the script file. An event listener is configured and a callback will trigger as soon as the script file has finished loading.
/**
* Load external script files to avoid bundling.
*
* @param scriptID string for tag ID.
* @param scriptSrc url to script file.
* @param callBack callback function to be triggered when script file loaded.
*/
export function extScriptLoader(scriptID: string, scriptSrc: string, callBack: any) {
// Append script if none exists.
if (document.body.querySelector("#" + scriptID) === null) {
// Callback when script loaded.
let finishedLoading = () => {
callBack();
document.getElementById(scriptID).removeEventListener("load", finishedLoading);
}
let script = document.createElement("script");
script.id = scriptID;
script.src = scriptSrc;
document.body.appendChild(script);
document.getElementById(scriptID).addEventListener("load", finishedLoading);
}
// Callback directly as script already exists.
else {
callBack();
}
}
In the script file where we will use dsteem. First we declare dsteem (making use of what we installed earlier) to get Intellisense working, and then use the helper to load the script
declare const dsteem: typeof import("dsteem");
extScriptLoader("steemScript", 'https://unpkg.com/dsteem@^0.10.1/dist/dsteem.js', () => {
this.createClient();
});
createClient is only a test function I've done to check so this works, it looks like this:
async createClient() {
this.client = new dsteem.Client("https://api.steemit.com");
const accounts = await this.client.database.getAccounts(["smjn"]);
accounts.forEach(account => {
document.getElementById("newsItem").innerHTML = account.name;
});
}
Visiting the page it will check for the unique script ID, if none found, it will append the script tag to the body and the script file gets downloaded. When done it calls back and that triggers the fetching of my Steem account and when ready it updates the "newsItem" to contain the name of my account.
Thanks for reading!
Hi @smjn!
Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your UA account score is currently 1.824 which ranks you at #28640 across all Steem accounts.
Your rank has dropped 154 places in the last three days (old rank 28486).
In our last Algorithmic Curation Round, consisting of 299 contributions, your post is ranked at #288.
Evaluation of your UA score:
Feel free to join our @steem-ua Discord server
Congratulations @smjn! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :
Click here to view your Board of Honor
If you no longer want to receive notifications, reply to this comment with the word
STOP
Do not miss the last post from @steemitboard:
Congratulations @smjn! You received a personal award!
Click here to view your Board of Honor