102

These are my sample files:

<!DOCTYPE html>
<html>
<head>
  <title>Test</title>
  <script src="t1.js"></script>
</head>
<body></body>
</html>

t1.js:

import Test from 't2.js';

t2.js:

export const Test = console.log("Hello world");

When I load the page in Firefox 46, it returns "SyntaxError: import declarations may only appear at top level of a module" - but I'm not sure how much more top-level the import statement can get here. Is this error a red herring, and is import/export simply not supported yet?

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
Christoph Burschka
  • 3,674
  • 2
  • 14
  • 27

6 Answers6

142

Actually the error you got was because you need to explicitly state that you're loading a module - only then the use of modules is allowed:

<script src="t1.js" type="module"></script>

I found it in this document about using ES6 import in browser. Recommended reading.

Fully supported in those browser versions (and later; full list on caniuse.com):

  • Firefox 60
  • Chrome (desktop) 65
  • Chrome (android) 66
  • Safari 1.1

In older browsers you might need to enable some flags in browsers:

  • Chrome Canary 60 – behind the Experimental Web Platform flag in chrome:flags.
  • Firefox 54 – dom.moduleScripts.enabled setting in about:config.
  • Edge 15 – behind the Experimental JavaScript Features setting in about:flags.
15

This is not accurate anymore. All current browsers now support ES6 modules

Original answer below

From import on MDN:

This feature is not implemented in any browsers natively at this time. It is implemented in many transpilers, such as the Traceur Compiler, Babel or Rollup.

Browsers do not support import.

Here is the browser support table:

enter image description here

If you want to import ES6 modules, I would suggest using a transpiler (for example, babel).

mikemaccana
  • 81,787
  • 73
  • 317
  • 396
Josh Beam
  • 17,535
  • 2
  • 32
  • 63
3

Just using .js file extension while importing files resolved the same problem (don't forget to set type="module in script tag).

Simply write:

import foo from 'foo.js';

instead of

import foo from 'foo';
krmld
  • 908
  • 9
  • 8
1

Add type=module on the scripts which import and export the modules would solve this problem.

0

you have to specify it's type in script and export have to be default ..for ex in your case it should be,

<script src='t1.js' type='module'>

for t2.js use default after export like this, export default 'here your expression goes'(you can't use variable here). you can use function like this,

export default function print(){ return console.log('hello world');}

and for import, your import syntax should be like this, import print from './t2.js' (use file extension and ./ for same directory)..I hope this would be useful to you!

0

For the sake of argument...

One could add a custom module interface to the global window object. Although, it is not recommended. On the other hand, the DOM is already broken and nothing persists. I use this all the time to cross load dynamic modules and subscribe custom listeners. This is probably not an answer- but it works. Stack overflow now has a module.export that calls an event called 'Spork' - at lest until refresh...

//  spam the global window with a custom method with a private get/set-interface and     error handler... 

window.modules = function(){
  window.exports = {
    get(modName) {
      return window.exports[modName] ? window.exports[modName] : new Error(`ERRMODGLOBALNOTFOUND [${modName}]`)
    },
    set(type, modDeclaration){
      window.exports[type] = window.exports[type] || []
      window.exports[type].push(modDeclaration)

    }
  }

}

//  Call the method
window.modules()

//  assign a custom type and function
window.exports.set('Spork', () => console.log('SporkSporSpork!!!'))


// Give your export a ridiculous event subscription chain type...
const foofaalala = window.exports.get('Spork')

// Iterate and call (for a mock-event chain)
foofaalala.forEach(m => m.apply(this))

//  Show and tell...
window