Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is mixing bundled modules and JavaScript Modules possible

Inspired by preact's "no build tools route", I recently created a project with no build or bundling process. Conceptually, it looks like this (pseudo code following).

I have a dependency on react-button which uses e.g. microbundle to resolve the preact import through the node_modules folder.

// dependency 1: "preact-button" npm package (uses bundler)
import { h, Component, render } from 'preact';

const button = h('button', null, 'Click');
export default Button;

Then, there's my app which requires preact-button as a dependency. It's just a .html file for now.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title>SO App</title>
    <script type="module">
      import { h, Component, render } from 'https://unpkg.com/preact?module';
      import Button from "https://fantasycdn.com/preact-button?module"
    </script>
  </head>
  <body>
  </body>
</html>

However, my app is not using any bundler and hence imports preact-button's code. If I had a bundler, this wouldn't be a problem, as the import ... from "preact" would be resolved through the bundler. But now, taking advantage of the type="module" syntax, this global module name cannot be imported anymore. Instead, an error is thrown:

react-button.js:
Uncaught TypeError: Error resolving module specifier “preact”. Relative module specifiers must start with “./”, “../” or “/”.

As the author of preact-button, what I want though is that my module:

  • can be used with a bundler (as shown above)
  • can be used within a JavaScript module by somehow resolving it's dependencies (dynamically?)

Since preact advertises this approach on their website, I took a quick look into their build process. They have a simple advantage, which is that they don't have to deal with any kind of dependencies (e.g. peer or regular), as they simply don't have any.

But is it possible to mix bundled modules and JavaScript modules without any heavy build process? Is there maybe even a commonly agreed upon approach?

like image 705
Tim Daubenschütz Avatar asked Jul 16 '20 12:07

Tim Daubenschütz


People also ask

Are there modules in JavaScript?

A module in JavaScript is just a file containing related code. In JavaScript, we use the import and export keywords to share and receive functionalities respectively across different modules. The export keyword is used to make a variable, function, class or object accessible to other modules.

Is every JavaScript file a module?

With CommonJS, each JavaScript file stores modules in its own unique module context (just like wrapping it in a closure). In this scope, we use the module. exports object to expose modules, and require to import them.

How many ways we can import a module in JS?

There are two types of module imports: Named Imports. Default Imports.

When were JavaScript modules added?

Until 2015, the JavaScript language had no built-in module system. Yet people had been building large systems in JavaScript for more than a decade, and they needed modules. So they designed their own module systems on top of the language.


1 Answers

Notice that UNPKG claims:

?module

Expands all “bare” import specifiers in JavaScript modules to unpkg URLs. This feature is very experimental

This means that your build would be transformed and cached courtesy of UNPKG into:

import { h, Component, render } from 'https://unpkg.com/preact@^10.4.6?module';

const button = h('button', null, 'Click');
export default Button;

As a confirmation of this claim, I checked how ?module handles one of my bundled libraries on UNPKG, and it transforms:

import { Parser, Grammar } from 'nearley';
import moo from 'moo';

into:

import { Parser, Grammar } from "https://unpkg.com/nearley@^2.19.1?module";
import moo from "https://unpkg.com/moo@^0.5.1?module";

Assuming that your preact-button module is published on npm, the current usage of bare import specifiers in your code should not be an issue.

like image 137
Patrick Roberts Avatar answered Nov 10 '22 03:11

Patrick Roberts