Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

If you don't find JavaScript modules confusing, you should. I work on a module loader [1] and I find it quite confusing. To clarify we have 3 things:

1. import and export syntax, this is defined in ES2015. It's just syntax, it doesn't explain how modules should be loaded.

2. The Loader spec (http://whatwg.github.io/loader/) which defines a full loader including hooks to do just about anything you can possibly need. This allows you to do really crazy things like define modules dynamically and import then dynamically (which the static import/export syntax doesn't allow). We use this extensively in StealJS (or at least an older version of it) and it's pretty powerful.

3. import type=module is what this article is referring to. It defines a tag that allows you to import modules in the browser. You can't use a regular script tag, modules are different; they are strict mode by default for example.

If you read the GitHub issue there was some discussion of whether import type=module should use the Loader spec. It probably should. But the Loader spec isn't done so... reading the spec and seeing things like the module map [2] it sounds like import type=script defines a miniature sized loader.

I don't blame them for doing this, Loader has taken too long and people are clamoring for something. The Loader spec has a weird history; it was close to being done in ES2015 but when it was ejected it sit for a long time without much work. Then around last summer it was heavily worked on and got pretty far. But now as it sits, no commits like the last 2 and a half months [3]

At this point I wouldn't be surprised to see Loader go away. It's probably too controversially and too big to ever get done. I imagine the web will just have the import type=module loader and Node will do it's own this. This is going to make writing portable JavaScript as annoying going forward as it's always been.

[1] http://stealjs.com/

[2] https://html.spec.whatwg.org/multipage/webappapis.html#modul...

[3] https://github.com/whatwg/loader/commits



One detail that's often lost in the discussion (that you might have been hinting at) is that without a loader modules can only be referred to by URL. Node-style name resolution won't work at all.

This means that modules will either still have to be compiled with something like browserify that resolves modules names into URLs ahead of time (a solution I don't particularly like), or modules will just have to use URLs to import other modules, leading to a convention of assuming that modules are all siblings so that you import like this:

    import * as jquery from '../jquery/jquery.js';
Despite the extra verbosity, I prefer this since it requires that modules are flat and de-duplicated and doesn't require any resolution step at all.


Modules are not flat in reality though, any non-trivial sized app likely has multiple versions of the same module being used. I don't see any reason to think that's going to change in the future, extreme modularity is the norm in JavaScript these days.


It may be the norm right now (since npm came around), but that's no reason to excuse it for what it is: a mess. A mess we should be able to do without.

If we can have an official module-implementation which somehow forces developers to get a grip on their dependencies (which is the exact opposite of what "modern" js developers are doing), that can only be a good thing.

The cowboy days must surely soon be over?


Every language and platform ever has had serious problems with multiple library versions. Anyone who has used an OS without a package manager knows this. I won't claim that npm doesn't also have problems, but at least its problems are different. Humanity can survive the existence of more than one paradigm for dealing with versioned libraries.


> any non-trivial sized app likely has multiple versions of the same module being used

Which I think is a very bad idea in general, but especially when shipping bytes to the browser.

IMO, one of the key responsibilities of package managers is to find a single solution to the version constraints in a dependency graph, and allow the user to resolve conflicts. Just in general, multiple incompatible versions of a library in an application is asking for hard-to-find bugs if those versions ever interact. With web apps though, it's just too easy to create unnecessarily bloated script bundles without even knowing it.


I'm not sure how a user can possibly resolve conflicts when 2 libraries are using 2 incompatible versions of some other library. Those need the versions they depend on.

You might not want multiple versions of Angular in your script bundle but multiple versions of small modules like an "extend" doesn't matter much.

But whether it's good or bad isn't really relevant, if you think that people are going to throw out the npm workflow because it doesn't fit into script type=module's semantics I think you're going to be disappointed. More likely they'll just not use script type=module (except perhaps after bundled).


Often times packages have far to narrow version constraints (usually from unnecessarily raising the lower bound), and/or a technically breaking change in a dependency doesn't actually break the depender. In these cases the user can override the version, test, and move on.

In more severe cases, like lodash 3->4, it is tough, but a user can try to downgrade the direct dependencies at the root of the paths that lead to the newer version.

The best antidote is for packages to maintain compatibility through consecutive major versions with decent deprecation rules, and for packages to update and test their dependencies upper bounds regularly.


You can also do

   import * as jquery from '/js/jquery/jquery.js';
or maybe better, set up your server-side rewrite rules so that instead of that you do

   import * as jquery from '/js/jquery';


I'm not sure how a reusable module that depends on jquery could make these assumptions about where the server-wide JS directory is.

../package-name/ works with multiple apps on the same server, and mounted in other places than root. It's working quite well for us with HTML imports.


I'd rather have each module have its own dependencies as subdirectories, sort of like node_modules. Everyone resolves paths from cwd.

If someone wants to share the same jquery across subdirs, I'm sure http redirects could be configured. Or alternately some sort of corporate versioning convention that developers can expect to have with absolute paths. Certainly better than ../jquery.


Every Angular or React component or every lodash dependent carrying along it's own copy of the modules sounds entirely unworkable.


>> This allows you to do really crazy things like define modules dynamically

In python there's a library called "sh" and it has a novelty interface:

    from sh import ls, pwd, my_unique_command
    print ls('/dir')
    ...
I wondered (not enough to check right enough) if something similar could be done in JS. Although due to the async nature of such a call, it might not end up looking so familiar with JS in practice i guess.


https://github.com/shelljs/shelljs Edit: \/ ahh, yes you're right!


I think if I'm grokking correctly that you can import "anything" from sh, without it having to be explicitly in the package.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: