mikach / requirejs-babel

An AMD loader plugin for Babel
117 stars 32 forks source link

Looks like the plugin do not support nested es6 imports ? #26

Open pksorensen opened 7 years ago

pksorensen commented 7 years ago

I tried to load a es6 module which imports relative paths to ther es6 modules, it loads the first file correct but all the imports in this file fails.

Would it be a fair assumption that if a es6 module loaded also has other dependencies, then these should be prefixed with es6! in the generated define call? Can this be done?

peppertech commented 7 years ago

We have a similar situation, that is being described here: https://community.oracle.com/thread/4058276

If there is a fix or workaround for this, it would really be great to know about.

RobertCZ commented 7 years ago

Should work OK when you use Babel resolveModuleSource feature (see demo folder)

    'config': {
        'es6': {
            'resolveModuleSource': function(source) {
                return 'es6!'+source;
            }
        }
    },
amit1911 commented 7 years ago

After I added in the above config, I am now getting Uncaught Error: Mismatched anonymous define() module error. Any ideas on what is causing this and how to fix it?

RobertCZ commented 7 years ago

Maybe you're trying to transpile file with plain define(...). You either use import everywhere or make resolveModuleSource callback smarter about when should es6! prefix be injected. I whitelist relative links and es6 only folders. Eg

    resolveModuleSource(source) {
        let whitelist = ['./', '../', 'lib/']
        let whitelisted = s => whitelist.some(f => s.startsWith(f))
        let hasPrefix = source.startsWith('es6!')
        let prefix = whitelisted(source) && !hasPrefix ? 'es6!' : ''
        return prefix + source
    }
amit1911 commented 7 years ago

I am not using any define() in es6 files. Take a look at the following

// file -> topPage/duck.js

import {handleActions} from 'redux-actions';

const initialState = {
    test: 'hello world!'
};
const reducer = (state, action) => initialState;

export default reducer;
// file -> store/rootReducer.js

import topPage from '../features/topPage/duck';
import {combineReducers} from 'redux';
import {handleActions} from 'redux-actions';

const reducer = combineReducers({
    topPage
});
export default reducer;
// file -> app.js

define(['es6!store/rootReducer'], function(rootReducer) {
    // setup code
})

Now since the rootReducer files is importing topPage/duck file, it throws Uncaught Error: Mismatched anonymous define() module error but if i remove the nested import from rootReducer file then it works fine.

RobertCZ commented 7 years ago

Maybe redux has define in it?

amit1911 commented 7 years ago

just checked and redux-actions has a define() in it. What can I do now?

RobertCZ commented 7 years ago

https://github.com/mikach/requirejs-babel/issues/26#issuecomment-337555031

amit1911 commented 7 years ago

Actually I investigated a bit more and it seems like the define() call inside the redux-actions may not be a problem and nested imports is the problem because if I merge the files together to remove the need for nested imports then it works fine.

import {handleActions} from 'redux-actions';
import {combineReducers} from 'redux';

const initialState = {
    test: 'hello world!'
};

const reducer = handleActions({}, initialState);
const rootReducer = combineReducers({topPage: reducer});
export default rootReducer;

The above works fine, so it seems like the problem might be with nested imports only.

wkeese commented 4 years ago

The resolveModuleSource comments seem to no longer apply, as that is apparently no longer needed, see 5cfb600095c321593b0152bb60870216ed926a40, and the demo example (which has nested imports) is working.

I am seeing issues with relative paths though, as documented in #34.

prantlf commented 2 years ago

I have no problem importing parts based on the baseUrl or relatively:

// src/index.js
import x from 'src/sub/x'
import x from './sub/x'

I use only hand-written modules from the src directory tree. Not modules imported from node_modules. I wonder if this could mess the resolution up.

Nesting ES6 imports is no problem. The problem is mixing ESM and AMD modules. This plugin ensures nesting of ES6 imports by enforcing the ES6 plugin to every JavaScript module:

if (sourcePath.indexOf('!') < 0) {
  return 'es6!' + sourcePath;
}

If you include an ESM module like this in your dependencies:

export default (a, b) => a + b;

The transpiled output will end up well:

define(["exports"], function (_exports) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.default = void 0;

  var _default = (a, b) => a + b;

  _exports.default = _default;
});

But if you include an AMD module like this in your dependencies:

define(function () {
  return (a, b) => a + b;
});

The transpiled output will look like this, which will obviously not work:

define([], function () {
  "use strict";

  define(function () {
    return (a, b) => a + b;
  });
});

The best solution would be making the es6 plugin recognise the module format and not transpile it with transform-modules-amd, if the module is already in the AMD format. Other Babel transformations would be still needed, like supporting modern language features, but reformatting the module imports/exports should be performed only if needed.