jspm / jspm-cli

ES Module Package Manager
https://jspm.org
Apache License 2.0
3.78k stars 272 forks source link

Investigate Babel plugin workflows #778

Closed guybedford closed 8 years ago

guybedford commented 9 years ago

@AutoSponge mentioned wanting to use something like https://github.com/codemix/babel-plugin-closure-elimination.

It would be good to have a standard workflow to install and use Babel plugins like this in jspm.

AutoSponge commented 9 years ago

I logged out the options constructed in es6-module-loader.src.js/babelTranspile that get passed to babel.transpile.

Then I ran the same options from the command line (see below). Adding the plugins property to the options object will work from babel.transpile but fail with a ref err when running jspm:

return require("babel-core").transformFile("index.js", { optional: [ 'runtime' ],
    modules: 'system',
    sourceMap: 'inline',
    filename: 'file:/Users/paulgrenier/GitHub/jspm-plugin-test/index.js',
    code: true,
    ast: false,
    plugins: ["closure-elimination"],
    blacklist: [ 'react' ]
}, function (err, result) {
    console.log(result.code);
});

failure from jspm:

> jspm bundle-sfx index

     Building the single-file sfx bundle for index...
{ optional: [ 'runtime' ],
  modules: 'system',
  sourceMap: 'inline',
  filename: 'file:/Users/paulgrenier/GitHub/jspm-plugin-test/index.js',
  code: true,
  ast: false,
  blacklist: [ 'react' ],
  plugins: [ 'closure-elimination' ] }

err  ReferenceError: Unknown plugin "closure-elimination"
         at PluginManager.subnormaliseString (file:/Users/paulgrenier/GitHub/jspm-plugin-test/jspm_packages/npm/babel-core@5.4.3/browser.js:9206:13)
         at PluginManager.add (file:/Users/paulgrenier/GitHub/jspm-plugin-test/jspm_packages/npm/babel-core@5.4.3/browser.js:9243:27)
         at File.buildTransformers (file:/Users/paulgrenier/GitHub/jspm-plugin-test/jspm_packages/npm/babel-core@5.4.3/browser.js:8359:21)
         at new File (file:/Users/paulgrenier/GitHub/jspm-plugin-test/jspm_packages/npm/babel-core@5.4.3/browser.js:8226:10)
         at TransformerPipeline.transform (file:/Users/paulgrenier/GitHub/jspm-plugin-test/jspm_packages/npm/babel-core@5.4.3/browser.js:12089:16)
         at Loader.babelTranspile (/Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/jspm/node_modules/systemjs/node_modules/es6-module-loader/dist/es6-module-loader.src.js:2492:24)

I compared the above trace to a trace from my "hand-coded" transpile script when I misspelled the plugin:

ReferenceError: Unknown plugin "closure-eliminationx"
    at PluginManager.subnormaliseString (/Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-core/lib/babel/transformation/file/plugin-manager.js:73:13)
    at PluginManager.add (/Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-core/lib/babel/transformation/file/plugin-manager.js:110:27)
    at File.buildTransformers (/Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-core/lib/babel/transformation/file/index.js:281:21)
    at new File (/Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-core/lib/babel/transformation/file/index.js:148:10)
    at TransformerPipeline.transform (/Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-core/lib/babel/transformation/transformer-pipeline.js:87:16)
    at /Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-core/lib/babel/api/node.js:95:48

The correct location is /Users/paulgrenier/GitHub/jspm-plugin-test/node_modules/babel-plugin-closure-elimination/lib/index.js

jspm calculates that the location is null.

So I investigated util.resolveRelative in babel/browser.js. We exit early because of this line.

if (typeof _module3["default"] === "object") return null;

The _module3 var is assigned as:

var _module2 = require("module");
//...
var _module3 = _interopRequireDefault(_module2);

which derives from:

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

If I read this right, because resolve 'module' as an object instead of a function, we'll never be able to resolve a babel plugin.

When we run through babel cli, the cwd = '/Users/paulgrenier/GitHub/jspm-plugin-test' but when we run from jspm cwd = '/'. Ultimately, I think this affects whether we can resolve "module" but I'm not sure where/how to process.chdir() to test it.

Any ideas?

areel commented 9 years ago

Is there a work around for this?

This prevents using jspm with angular 2 and babel, Due to Babel needing some plugin's (https://github.com/shuhei/babel-plugin-angular2-annotations) to support es6 constructor parameters. I have tried hard coded relative paths but the

if (typeof _module3["default"] === "object") return null;

guards prevent that.

Aidan

guybedford commented 9 years ago

@areel you can set custom compilation options in babel via the SystemJS babelOptions - https://github.com/systemjs/systemjs/blob/master/docs/config-api.md#babeloptions. This issue is specifically tracking external plugin support.

areel commented 9 years ago

I may be confused here but I think I am trying to include an 3rd party's plugin to Babel using JSPM, but the plugin is not being located, which is how I read this thread. So I am under the assumption that this is the same issue as this thread describes.

I should have added more information, so on the basis that I am on the right thread !

I am creating a workflow using jspm 0.15.7, babel 5.4.7 and angular 2 (alpha 27). I have the class decorators being processed correctly and now I am attempting to get the constructor parameters to be parsed by using angular 2 $Inject in constructor parameter lists. The syntax for this is coming out of Angular2 and is not pure es7 decorator spec, hence the need for the next two external babel plugins (babel-plugin-angular2-annotations & babel-plugin-type-assertion)

so I have installed angular2-annotations and type-assertion using jspm install XXXXXX -save-dev and my config.js looks like

System.config({
  "baseURL": "./",
  "transpiler": "babel",
  "babelOptions": {
    "optional": [
      "runtime",
      "es7.decorators"
    ],
    "plugins": [
      "angular2-annotations",
      "type-assertion"
    ]
  }, .........

But I receive the following error:

Potentially unhandled rejection [3] ReferenceError: Error loading "sb/components/app" at http://localhost:3000/sb/components/app.js
Unknown plugin "angular2-annotations"
    at PluginManager.subnormaliseString (http://localhost:3000/jspm_packages/npm/babel-core@5.4.7/browser.js:9222:13)
    at PluginManager.add (http://localhost:3000/jspm_packages/npm/babel-core@5.4.7/browser.js:9259:27)
    at File.buildTransformers (http://localhost:3000/jspm_packages/npm/babel-core@5.4.7/browser.js:8366:21)
    at new File (http://localhost:3000/jspm_packages/npm/babel-core@5.4.7/browser.js:8233:10)
    at TransformerPipeline.transform (http://localhost:3000/jspm_packages/npm/babel-core@5.4.7/browser.js:12103:16)
    at x.e (http://localhost:3000/jspm_packages/es6-module-loader.js:7:24001)
    at http://localhost:3000/jspm_packages/es6-module-loader.js:7:24475
    at O (http://localhost:3000/jspm_packages/es6-module-loader.js:7:7439)
    at K (http://localhost:3000/jspm_packages/es6-module-loader.js:7:7071)
    at y.7.y.when (http://localhost:3000/jspm_packages/es6-module-loader.js:7:10745)

Stepping through the codebase I seem to be having the same issue as described by AutoSponge on the 20th.

Regards

Aidan

guybedford commented 9 years ago

Sorry I thought you were only looking at included Babel plugins, yes that is exactly this issue then.

This is a todo to basically import the plugin via a System.import statement and pass it to Babel somehow. It may require some new APIs in Babel to be able to hook this process but I'm not sure. PRs are also welcome.

OrKoN commented 9 years ago

I am interested in this feature too (for https://www.npmjs.com/package/babel-plugin-htmlbars-inline-precompile)

joeldenning commented 9 years ago

I looked at implementing the feature a bit, here's what I found.

It looks like it will probably require a change to babel-core. Right now, babel-core uses the npm package try-resolve to require plugins, and try-resolve bails when it's in the browser.

Or I guess if you wanted to do it without changing babel-core, you could change window.Module to be a function that has _nodeModulePaths and _resolveFilename functions, where _resolveFilename returns the actual module. There are probably some scary ramifications though of making those changes.

guybedford commented 9 years ago

Thanks @joeldenning for looking into this. There is actually some work on this for jspm 0.17 in https://github.com/systemjs/plugin-babel, pending release.

kepta commented 9 years ago

@guybedford I want to work on implementing this feature. I am a new comer to open source, can I please work on this?

guybedford commented 9 years ago

@kepta thanks for offering to help out. This feature has already been developed on https://github.com/systemjs/plugin-babel, if you're able to test that out and report any feedback / bugs that would be incredibly helpful.

OrKoN commented 9 years ago

@guybedford does plugin-babel work only with the master branch of jspm? I tried installing it with latest stable jspm: jspm install babel=github:systemjs/plugin-babel -o '{"registry": "jspm", "dependencies" : {"babel": "^5.8.25", "babel-runtime": "^5.8.25"}}' but I get an error:

err  TypeError: Invalid Version: master
         at new SemVer (/home/alex/.npm-packages/lib/node_modules/jspm/node_modules/semver/semver.js:293:11)

Also looks like versions of babel defined in the package.json aren't released yet.

guybedford commented 9 years ago

@OrKoN yes there are no guarantees of this plugin working against the current jspm - it's designed for 0.17, but should be easily adaptable to 0.16.

tyscorp commented 9 years ago

For anyone trying to get plugin-babel working with jspm@0.16, you have to manually set options.plugins array here, instead of in config.js otherwise the default babel loader tries to load the plugin and fails.

veggiemonk commented 9 years ago

Hi @guybedford @tyscorp,

I am dying to make a babel plugin work with jspm. The plugin compiles JSX to mithril.js template. I tried to install the https://github.com/systemjs/plugin-babel But here is the error jspm gave me.

❯ jspm install bp=github:systemjs/plugin-babel
     Looking up github:systemjs/plugin-babel
     Updating registry cache...
     Downloading github:systemjs/plugin-babel@master

warn Error on locate for github:babel
     GitHub packages must be of the form owner/repo.

warn Error on locate for github:babel-runtime
     GitHub packages must be of the form owner/repo.

err  Error: Error locating github:babel.
         at /home/bisconti/code/frontend/cocorico/node_modules/systemjs-builder/lib/builder.js:23:9
         at Object.lib$rsvp$events$$default.trigger (/home/bisconti/code/frontend/cocorico/node_modules/rsvp/dist/rsvp.js:245:13)
         at null._onTimeout (/home/bisconti/code/frontend/cocorico/node_modules/rsvp/dist/rsvp.js:779:47)
         at Timer.listOnTimeout (timers.js:92:15)

err  Error locating github:babel.

warn Installation changes not saved.

How can I make this babel plugin work with jspm?

Thank you so much in advance, it would really helps!!!

AlicanC commented 9 years ago

We have a project we would like to start but is being blocked by this. A mini-guide on how to make this work would be great.

Also, does launch of Babel 6 further complicate this? Maybe it's better to just close this and implement it with Babel 6 support.

guybedford commented 9 years ago

If anyone is looking to work around this, the above issue should be fixed via an override like:

  jspm install github:systemjs/plugin-babel -o "{dependencies:{babel: 'npm:babel-core@^5.8.26','babel-runtime': 'npm:babel-runtime@^5.8.26'}}"
oligot commented 9 years ago

Hi All,

Once installed, how do we use plugin-babel ? A (small) working exemple would really help here.

Thanks for the great work !

OrKoN commented 9 years ago

@guybedford thanks, that was helpful!

veggiemonk commented 9 years ago

Hi everybody,

@guybedford Thank you for your quick response. I really appreciate it. I could install plugin-babel! By the way, jspm is really great and solid tool. So many things i don't have to think about, it is such a relief. Congratulations on that.

I am in a little bit in the same case as @oligot. I don't really understand how to pass the plugin to babel. I did how @tyscorp suggested and added the babelOptions to plugin-babel.js (although it seems really hacky to go inside the code of a dependency to modify it) but without success. plugin-babel is not loaded. (Of course, the app doesn't work) I receive this error message:

Uncaught (in promise) Error: React is not defined(…)

Babel sees jsx and compiles it automatically to React. That is why the babel plugin is so important, I want jsx to transpile to mithril templates, not React.

When I put the plugin in config.js:

babelOptions: {
  "optional": [
    "runtime",
    "optimisation.modules.system"
  ],
  plugins: ['babel-plugin-mjsx']
},

The error:

Uncaught (in promise) Error: Unknown plugin "babel-plugin-mjsx"(…)

I install this plugin by doing:

jspm install npm:babel-plugin-mjsx

Is it the correct way? Should I add an option somewhere?

Especially now with the release of babel 6.0.0 the plugin system is going to change. See http://babeljs.io/blog/2015/10/29/6.0.0/ Will this release make it easier for jspm to handle plugins?

Cheers,

tyscorp commented 9 years ago

@veggiemonk try setting the meta property in config.js.

System.config({
    "meta": {
        "app/*": {
            "loader": "babel-loader"
        }
    }
});
veggiemonk commented 9 years ago

Thanks @tyscorp but I what is that babel-loader? I receive an error by adding the 'meta' property:

Uncaught (in promise) Error: XHR error (404 Not Found) loading http://veggiemonk.ovh:3000/babel-loader.js
    Error loading http://veggiemonk.ovh:3000/babel-loader.js
    Error loading http://veggiemonk.ovh:3000/app/main.jsx
    at o (http://veggiemonk.ovh:3000/jspm_packages/system.js:4:12597)
    at XMLHttpRequest.s.onreadystatechange (http://veggiemonk.ovh:3000/jspm_packages/system.js:4:13122)

I see it is a Webpack plugin for Babel and I could not even install it with jspm.

Here is the error:

❯ jspm install npm:babel-loader
     Looking up npm:babel-loader
     Updating registry cache...
     Downloading npm:babel-loader@5.3.3
     Looking up npm:babel-core
     Looking up npm:loader-utils
     Looking up npm:object-assign
     Looking up npm:webpack
     Downloading npm:loader-utils@0.2.11
     Looking up npm:big.js
     Looking up npm:json5
     Downloading npm:object-assign@3.0.0
ok   Installed npm:object-assign@^3.0.0 (3.0.0)
ok   Installed npm:loader-utils@^0.2.9 (0.2.11)
     Downloading npm:json5@0.4.0
     Downloading npm:big.js@3.1.3
ok   Installed npm:json5@^0.4.0 (0.4.0)
ok   Installed npm:big.js@^3.0.2 (3.1.3)
     Looking up github:jspm/nodelibs-path
     Looking up github:systemjs/plugin-json
     Looking up github:jspm/nodelibs-process
     Looking up github:jspm/nodelibs-fs
     Looking up npm:path-browserify
     Looking up npm:process
     Looking up github:jspm/nodelibs-assert
     Downloading npm:webpack@1.12.2
     Looking up npm:async
     Looking up npm:clone
     Looking up npm:enhanced-resolve
     Looking up npm:esprima
     Looking up npm:interpret
     Looking up npm:memory-fs
     Looking up npm:mkdirp
     Looking up npm:node-libs-browser
     Looking up npm:optimist
     Looking up npm:supports-color
     Looking up npm:tapable
     Looking up npm:uglify-js
     Looking up npm:watchpack
     Looking up npm:webpack-core
     Looking up npm:assert
     Downloading npm:optimist@0.6.1
     Looking up npm:wordwrap
     Looking up npm:minimist
     Downloading npm:tapable@0.1.9
     Downloading npm:memory-fs@0.2.0
     Downloading npm:watchpack@0.2.9
     Looking up npm:chokidar
     Looking up npm:graceful-fs
     Downloading npm:interpret@0.6.6
     Downloading npm:supports-color@3.1.2
     Looking up npm:has-flag
     Downloading npm:mkdirp@0.5.1
     Downloading npm:async@1.5.0
     Downloading npm:uglify-js@2.4.24
     Looking up npm:source-map
     Looking up npm:uglify-to-browserify
     Looking up npm:yargs
     Downloading npm:clone@1.0.2

err  Error: Installing npm:webpack@1.12.2, no version match for npm:node-libs-browser@0.6.0
         at /home/veggiemonk/code/js/cocorico/node_modules/jspm/node_modules/systemjs-builder/lib/builder.js:23:9
         at Object.lib$rsvp$events$$default.trigger (/home/veggiemonk/code/js/cocorico/node_modules/jspm/node_modules/rsvp/dist/rsvp.js:245:13)
         at null._onTimeout (/home/veggiemonk/code/js/cocorico/node_modules/jspm/node_modules/rsvp/dist/rsvp.js:779:47)
         at Timer.listOnTimeout (timers.js:89:15)
     Looking up npm:util
     Downloading npm:async@0.9.2
     Downloading npm:async@0.2.10
     Downloading npm:esprima@2.7.0
     Downloading npm:wordwrap@0.0.3
     Downloading npm:has-flag@1.0.0
     Looking up npm:inherits
     Downloading npm:minimist@0.0.8
     Downloading npm:minimist@0.0.10
ok   Installed npm:interpret@^0.6.4 (0.6.6)
ok   Installed npm:webpack (1.12.2)

err  Installing npm:webpack@1.12.2, no version match for npm:node-libs-browser@0.6.0

warn Installation changes not saved.

Please, forgive my ignorance, but what is the point of having webpack and jspm together?

OrKoN commented 9 years ago

I believe babel-loader is plugin-babel e.g. jspm install babel-loader=github:systemjs/plugin-babel -o "{dependencies:{babel: 'npm:babel-core@^5.8.26','babel-runtime': 'npm:babel-runtime@^5.8.26'}}"

tyscorp commented 9 years ago

Oops, forgot that I renamed it. Yes, it's systemjs/babel-plugin.

veggiemonk commented 9 years ago

Thank you @OrKoN it allowed me to load the plugin-babel for jspm. Now things make more sense :smile:

I just did a

options.plugins.push( 'babel-plugin-mjsx' )

Maybe I am missing something because, I got this error:

Uncaught (in promise) Error: The plugin {} didn't export a Plugin instance(…)t @ system.src.js:4573g @ system.src.js:4573(anonymous function) @ system.src.js:4573

When debugging it in babel-plugin, I found that those options are transformed and options.plugins = ['babel-plugin-mjsx'] becomes an object

plugins = {
   transformer: ['babel-plugin-mjsx']
}

When reaching babel.transform(code, options), It is like babel doesn't know where to get the plugin. Although, I see the plugin in my config.js mapped to

"babel-loader": "github:systemjs/plugin-babel@master",
"babel-plugin-mjsx": "npm:babel-plugin-mjsx@1.0.3",

@tyscorp how did you pass the plugin to babel?

oligot commented 9 years ago

I just changed this line to this one

plugin.transformer = transformer;

and now it works :wink:

Still don't know if this is the correct way of doing things but at least it works now.

veggiemonk commented 9 years ago

@oligot thanks!

Vanuan commented 8 years ago

Babel 6 is released, where everything is pluginified.

veggiemonk commented 8 years ago

@Vanuan That's true, did you make it work with jspm? Can you tell us how?

veggiemonk commented 8 years ago

By the way, there is a fork with a recap of all the things to do to make babel 5 plugins work

https://github.com/veggiemonk/plugin-babel

Vanuan commented 8 years ago

So, it's like jspm -> babel -> system.js? I thought it's jspm -> system.js -> babel Or maybe it's "jspm -> System.js builder -> Babel transpiler -> System.js loader"?

guybedford commented 8 years ago

Released in jspm 0.17 beta.