Using Data URLs to Load Dependencies in Deno

Using Data URLs to Load Dependencies in Deno

Recently Deno released 1.7.0 which had support for data URLs. I think this is a pretty cool way to dynamically create modules on the fly when paired with import(). This could be used to dynamically load all the dependencies we want to use in our file at once.

Data URLs

Data URLs are basically URLs but with data encoded in some form so that instead of a link to data, it holds the data inside itself. Data URLs first need to start with data:. We then need to append the MIME type of the file we are loading, in this case application/typescript but we could also do application/javascript. After we append the format for encoding the file, in this tutorial we will be using base64 and you also append a , followed by the actual encoding of the file.

An Example

Imagine we have this file:

export const add = (a: number, b: number) => a + b;

and we want to import it from a data URL. Then we would first get the boilerplate.

const { add } = await import("data:application/typescript;base64,");

Then we need to append the base64 encoding. For this it is

ZXhwb3J0IGNvbnN0IGFkZCA9IChhOiBudW1iZXIsIGI6IG51bWJlcikgPT4gYSArIGI7

So the final code is:

const { add } = await import("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGFkZCA9IChhOiBudW1iZXIsIGI6IG51bWJlcikgPT4gYSArIGI7");

and it will correctly export the add function.

Loading Dependencies

Now that we know how to use them, let’s create a helper function to load dependencies. Let’s first create the type definition.

interface Dependency {
 url: string;
 name: string;
}
function loadDependencies(deps: Dependency[]) {
}

We want to create a variable for the data URL to import and a variable for the source code of the import. We also want to loop over the deps array.

function loadDependencies(deps: Dependency[]) {
 let code = "";
 let dataURL = "data:application/typescript;base64,";
 deps.forEach({ url, name} => {

 });
}

Now let’s append exports to code for each dependency.

function loadDependencies(deps: Dependency[]) {
 let code = "";
 let dataURL = "data:application/typescript;base64,";
 deps.forEach(({ url, name }) => {
  code += `export * as ${name} from "${url}"`;
 });
}

Now let’s encode that. We also have to add a dependency to the standard library.

import { encode } from "https://deno.land/std@0.84.0/encoding/base64.ts";

Now let’s do the finishing parts.

function loadDependencies(deps: Dependency[]) {
 let code = "";
 let dataURL = "data:application/typescript;base64,";
 deps.forEach(({ url, name }) => {
  code += `export * as ${name} from "${url}"`;
 });
 dataURL += encode(code);
 return import(dataURL);
}

And 🎉you can import dependencies with it!

const deps = await loadDependencies([{ name: "aleph", url: "https://deno.land/x/aleph/mod.ts" }]);

If you liked this article I suggest you check out other articles of mine on my blog.