DEV Community

Cover image for Use URL Imports in Nodejs v16 without experimental hacks!
Ren Hiyama
Ren Hiyama

Posted on • Updated on

Use URL Imports in Nodejs v16 without experimental hacks!

When We first made our own implementation of URL Imports for Ree.js we learnt a simple hack from here that was based using experimental tags.

Since now Nodejs was going to bring that feature natively in future versions, we thought of why shouldn't we pull that feature down, so we could have a cross platform of features being run across different platforms? (ie. Nodejs, Bun & maybe Deno)

But Deno already has them!

Yea sure they got them, but if we were meant to provide cross platform solution for our codes (ie, it could run on different platforms with same UI and same mechanics so its imported the same way across them), we got to create our own!

How do we solve this problem?

Thanks to es-module-lexer we can easily find all the imports in a js code, if we just replace those url imports present in those codes themselves with an absolute file path, we can easily dynamically import them.

So when we are asked to import a package, for example, https://esm.run/preact, we first fetch it with node-fetch package, and then run a loop on the code, to find out the imports urls, crawl them and run the same recursive function on them; and we continue replacing the urls with absolute file paths:

let code = await _fetch(originalUrl).then(res => res.text());
        let [_imports] = await lexer.parse(code)

        _imports = Array.from(new Set(_imports.map(i => i.n)));
        if (_imports.length > 0) {
            await Promise.all(_imports.map(async i => {
                let to = await dl(i, name, local, domain)
                code = code.replaceAll(i, to);
            }));
        }
Enter fullscreen mode Exit fullscreen mode

What's dl ? It's the recursive function I said above!
After those codes, we use fs to save those js files in their respective folder structure.


Shall we test it out?

Download Ree.js (currently we have bundled this url imports feature with Ree.js itself 😅)

npm i reejs
Enter fullscreen mode Exit fullscreen mode

Now add this script in your code:

import Import from "reejs/import.js";
let chalk = await Import("https://esm.sh/chalk?target=node");
console.log(chalk.green("We Did It!"));
Enter fullscreen mode Exit fullscreen mode

We can now see:

We Did It!


If you made this far, great! You can read the full source code of this file at: here
Consider even reading the file that we actually import (server/import.js), it's built on top of our url import "technology" that fixes some stupid stuff like:

  • Instead of chalk having all the properties, you needed to use chalk.default to get them... This issue happens with the way dynamic imports works...
  • Can read imports maps from your project directory's import-maps.json and server.import-maps.json
  • Can import relative files, as well as absolute files, and even the native nodejs modules/npm modules!

Do you love this idea?

Consider commenting if you want this feature to be as a package of its own on npm!

Also don't forget to star Ree.js Repo at https://github.com/rovelstars/reejs

Come and talk to us on Discord: https://dscrdly.com/server
Hit a Like and A Unicorn to show some support, share this post with your fellow friends/devs and maybe you even want to read my other articles? Check them out on my page!

Have an Epik Day!

Top comments (3)

Collapse
 
nicolasdanelon profile image
Nicolás Danelón

dope

Collapse
 
renhiyama profile image
Ren Hiyama

Consider hitting this post a like and a unicorn, and a star on our source code, to show some support! 🥰

Collapse
 
nicolasdanelon profile image
Nicolás Danelón

for sure!