Search code examples
babeljses6-module-loader

es6-module-loader cannot find module without .js extension


I am porting an application which uses System.import from traceur to Babel. My simplified HTML looks like this:

<script src="../node_modules/babel-core/browser.js"></script>
<script src="../node_modules/es6-module-loader/dist/es6-module-loader-dev.js"></script>
<script> 
    System.transpiler = 'babel';
    System.import('./css');
</script>

This gives me

Uncaught (in promise) File not found: http://connect:8000/sam/css
    Error loading http://connect:8000/sam/css

If instead I specify ./css.js, with the .js extension, it works. However, then imports inside css.js, and throughout the system, of the form

import 'foo';

fail.

It appears es6-module-loader wants the .js extension. I notice some commit in es6-module-loader involving the demo page which adds .js extension to the names of imports. On this page, I also see

.js extensions are also no longer added by default. These changes are part of the transition into the new specification work. See the discussion at whatwg/loader#52 for further information. .js extension adding can easily be added back if needed with a custom hook.

But I don't know what kind of hook is being referred to, or how to write it.

I am aware that dynamically loading and transpiling in the browser may not be ideal and is not a robust production approach. However, this particular app dynamically loads individual ES6 files and I need to stick to doing it this way for the time being.

My question is: does es6-module-loader require the .js extension, or is there any way to tell it to look for .js files by default?


Solution

  • I ended up overriding the locate hook, based on the documentation at https://github.com/ModuleLoader/es6-module-loader/blob/master/docs/loader-extensions.md:

    var systemLocate = System.locate;                                                                  
    System.locate = function(load) {                                                                   
      var System = this; // its good to ensure exact instance-binding                                  
      return Promise.resolve(systemLocate.call(this, load)).then(function(address) {                   
        return address + '.js';                                                                        
      });                                                                                              
    }