102

Is it possible to import javascript module from external url in ES6?

I tried (using babel-node):

import mymodule from 'http://...mysite.../myscript.js';
// Error: Cannot find module 'http://...mysite.../myscript.js'
ᄂ ᄀ
  • 5,669
  • 6
  • 43
  • 57
madox2
  • 49,493
  • 17
  • 99
  • 99

6 Answers6

50

2018 Update: The module loader spec is now a part of the ES Spec - what you are describing is allowed and possible with <script type="module"> in browsers and with a custom --loader with Node.js as well as with Deno if you're into that.


The module loader spec and the import/export syntax are separate. So this is a property of the module loader (not a part of the ES spec). If you use a module loader that supports plugins like SystemJS.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Browserify plugin: [browserify-cdnjs](https://github.com/dsdenes/browserify-cdnjs) – CodingIntrigue Jan 05 '16 at 08:44
  • 3
    Wait, isn't the `import` syntax the native module loader in ES6? – slebetman Jan 05 '16 at 08:48
  • 1
    @slebetman specifying the syntax for loading modules (i.e. `import` and `export` syntax) and specifying _how_ to load it are two separate tasks - the browser and node.js would use different mechanisms for it for instance - so it can't be a part of the language. In general - interacting with the environment is not a task the spec is interested in. – Benjamin Gruenbaum Jan 05 '16 at 08:51
  • Correct, the underlying mechanism may be different, but the import syntax is supposed to import the module right? Obviously we have no current examples of the syntax working natively but presumably at some point in the future browsers will support it. – slebetman Jan 05 '16 at 08:52
  • @slebetman At some point browsers will have a native module loader, but there is no specification as to how that will load. Maybe it will load external URLs, maybe it won't. No telling until someone writes one – CodingIntrigue Jan 05 '16 at 08:55
  • 1
    @slebetman Chrome and Firefox support it under a flag. The spec is polyfilled by https://github.com/ModuleLoader/es6-module-loader (a subset of systemjs). Files that call `System.register` would likely work - other files will likely not at the moment. There is also `script type='module'` for writing module code inside the browser. This is all mostly guessing. – Benjamin Gruenbaum Jan 05 '16 at 08:57
26

Update in 2022, it seems it works at least in latest Chrome, Firefox and Safari as of now, as long as the server provides a response header of content-type: application/javascript; charset=utf-8 for the js file.

Try these two files with a vanilla web server:

index.html

<!DOCTYPE html>
<html lang="en-US">
<head>
   <meta charset="utf-8">
   <title>Hello World</title>
   <script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>

hello.js

import ip6 from 'https://cdn.jsdelivr.net/gh/elgs/ip6/ip6.js';

const el = document.createElement('h1');
const words = "::1";
const text = document.createTextNode(ip6.normalize(words));
el.appendChild(text);

document.body.appendChild(el);

This is a HUGE deal! Because we can say bye to Webpack now. I am a little too excited now!

  • 1
    This is exciting. Note as of Jan 2022 it doesn't work in a Stackblitz project https://stackblitz.com/edit/js-y9xn5f or on Codesandbox - but works OK in my local dev environment. – abulka Jan 21 '22 at 01:45
  • 1
    That’s blocked by webpack. Webpack thought it’s a dynamic import and it wants to bundle the js at compile time. The reason why I thought it’s huge and exciting is because with this feature, we will have significant less dependence on webpack. –  Jan 22 '22 at 02:23
12

You could also use scriptjs which in my case requires less configs.

var scriptjs = require('scriptjs');

scriptjs('https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.standalone.js', function() {
    L.mapbox.accessToken = 'MyToken';
});
BaptWaels
  • 1,646
  • 2
  • 14
  • 17
5

TL;DR:

For now, no.

Long answer:

There are two different specs: the ES6 defines the syntax to exporting/importing. And there is the Loader Spec that actually defines how this modules will load.

Spec-speak aside, the important part for us developers is:

The JavaScript Loader allows host environments, like Node.js and browsers, to fetch and load modules on demand. It provides a hookable pipeline, to allow front-end packaging solutions like Browserify, WebPack and jspm to hook into the loading process.

This division provides a single format that developers can use in all JavaScript environments, and a separate loading mechanism for each environment. For example, a Node Loader would load its modules from the file system, using its own module lookup algorithm, while a Browser Loader would fetch modules and use browser-supplied packaging formats.

(...)

The primary goal is to make as much of this process as possible consistent between Node and Browser environments. For example, if a JavaScript program wants to translate .coffee files to JavaScript on the fly, the Loader defines a "translate" hook that can be used. This allows programs to participate in the loading process, even though some details (specifically, the process of getting a particular module from its host-defined storage) will be different between environments.

So we depend on the host environment (node, browser, babel, etc) to resolve/load the modules for us and provide hooks to the process.

Community
  • 1
  • 1
madcampos
  • 452
  • 6
  • 6
2

The specification describes how exactly a module specifier in import is resolved:

https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier

It says URLs are allowed, both absolute and relative ones (starting with /, ./, ../), and it does not differentiate between static and dynamic imports. Further in the text, there's an "Example" box showing examples of valid specifiers:

  • https://example.com/apples.mjs
  • http:example.com\pears.js (becomes http://example.com/pears.js as step 1 parses with no base URL)
  • //example.com/bananas
  • ./strawberries.mjs.cgi
  • ../lychees
  • /limes.jsx
  • data:text/javascript,export default 'grapes';
  • blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f
Marcin Wojnarski
  • 2,362
  • 24
  • 17
0

example in pure javascript how to import google code and replace element on any page to google translate button (can be run from browser debug console for any site you want)

importScriptURI("https://translate.google.com/translate_a/element.js"); 
document.getElementsByTagName("h1")[0].innerHTML='<div id="google_translate_element"></div>';
setTimeout(()=>{ new google.translate.TranslateElement({pageLanguage: 'en'},'google_translate_element');},1000);
commander
  • 1
  • 1
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 24 '23 at 07:59