Systemjs: Please add support for auto-importing index.js files

Created on 2 Sep 2016  路  5Comments  路  Source: systemjs/systemjs

right now I notice that if I have a module with index.js file in it the only way I can import it is by doing

import myModule from './myModule/index.js'

When it comes to working with own code it is not a big problem but trying to migrate existing libraries to system js is a nightmare!

Please add support for auto-loading index.js

Need for it has been already noticed in #1308

Most helpful comment

There is a workaround though, if you have a number of packages with nearly identical config, you can generate it in config.js. For example, this is how it's done in angular.js:

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'forms',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Bundled (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/'+pkgName] = { main: 'bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  }
  // Most environments should use UMD; some (Karma) need the individual index files
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Add package entries for angular packages
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
  };
  System.config(config);

Note also that System.config can be called several times, adding packages or different aspects of configuration.

All 5 comments

This is not a concern in SystemJS, but rather for compilers that create configurations and codebases for SystemJS to load.

We could have a default main for packages defined in SystemJS - System.config({ packages: { 'myModule': { } } }), where you don't need to explicitly note that the main is index.js, but the argument there is that it may be better to use myModule.js instead of index.js as the default main for better editor visibility. Until there's a clear path on this beyond npm, and for es modules in general, it's worth still holding back on a default.

I've just scanned documentation again hoping that I missed something. I am aware of main property on the config but I haven't found viable solution so far.

The problem, I,m dealing with, is converting node library to a work with front-end code for isomorphic app. Let's imagine couple of files, like those listed below:

./app.js
./lib/package/index.js

In node js I would require (or import) it using:

let p = import('./lib/package/')

I can not do it with systemjs, that means manual updating every single require, right?
With `main' property I could configure systemjs like:

System.config({
    baseURL: './',
    defaultJSExtensions: true,
    packages: {
        'lib/package/': {
            main: 'index'
        }
    },
    // ...
}

and then load the package with

let p = import('lib/package/')

It doesn't solve the problem, instead, introduces more complexity. I now need to have config for all loaded node packages and additionally change the code too. From import '../package/' and import ./lib/package/ to import lib/package which breaks the app if run on the server. Yes, I could use ./lib/package/ in my config but it still doesn't solve the problem.

It would be great to be able to just port the code. If imported package ends with / systemjs would look for default main file: index.js. Wouldn't that solve the problem and make porting to systemjs much easier?

There is a workaround though, if you have a number of packages with nearly identical config, you can generate it in config.js. For example, this is how it's done in angular.js:

  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'forms',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Bundled (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/'+pkgName] = { main: 'bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  }
  // Most environments should use UMD; some (Karma) need the individual index files
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Add package entries for angular packages
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
  };
  System.config(config);

Note also that System.config can be called several times, adding packages or different aspects of configuration.

Now once I've seen it it seems totaly obvious. Why didn't I think of that? Thank you @fictitious

For people coming here from Google - an easier solution than the ones proposed here is to add the file to the map configuration:

System.config({
    map: {
        'package': 'node_modules/package/index.js'
    }
});

Then you can use import {fn} from 'package'.

Was this page helpful?
0 / 5 - 0 ratings