How to use ES6 and ES7 in my Gruntfile - node.js

I would like to use ES6 and ES7 in my Gruntfile. The reason is that I would like to write a task, which includes the git-repository module. As you can see from the documentation, the module is only available in ES6 and ES7 and I would like to integrate this module as easy as possible. Is there a way that I can use ES6 and ES7 also in my Gruntfile - somthing like babel grunt? Unfortunately, I did not find anything on Google and therefore I hope that you can help me.
Thank you in advance! :-)

Usually you may want to use a build tool to transpile, so this is a 'who will build a build tool' problem.
It isn't usual for public package on NPM to be available only in ES.next or ES6 with feature set that is not supported by Node. git-repository isn't exception. It surely has transpiled code in the package and can be used without Babel.
Because the package was transpiled with babel-plugin-transform-runtime, it requires babel-polyfill to work.
Documentation uses async...await only as an example because it suits the workflow. async functions use promises, in ES5/ES6 it would be
require('babel-polyfill');
Repo.open('./example', { init: true })
.then(repo =>
repo.setRemote('origin', 'https://github.com/user/example.git')
.then(() => repo.add('--all .'))
.then(() => repo.commit('Commit message'))
...
);
co is excellent alternative to async...await for Node ES6 feature set that requires no transpiler.

Related

mocking es6 modules in unit test

Suppose we have a file(source.js) to test:
// source.js
import x from './x';
export default () => x();
And the unit test code is very simple:
// test.js
import test from 'ava';
import source from './source'
test("OK", t => {
source();
t.pass();
});
But this is the tricky thing. The file "./x" does not exist in the test environment. Since it is a unit test, we do not need "./x". We can mock the function "x()" anyhow(using sinon or something else). But the unit test tool, ava, keeps showing "Error: Cannot find module './x'";
Is there any way to run the unit test without the file "./x"?
To do this, you'd need to override the import process itself. There are libraries for doing something similar-- overriding the require function with proxyquire, for example-- but these force you to invoke their custom function to import the module under test. In other words, you'd need to abandon using ES6 module syntax to use them.
You should also note that ES modules are only supported experimentally (and relatively recently) in Node. If you're transpiling with Babel, you're not actually using ES modules. You're using the syntax, sure, but Babel transpiles them to CommonJS "equivalents", complete with require calls and module.exports assignments.
As such, if you're using Babel, you can probably proxyquire to import modules under test in your test files, even if you're using ES module syntax in those modules. This will break, though, if you ever switch away from Babel. :\
My personal recommendation would be to avoid directly exporting anything you might need to stub. So functions like x should be in a static module imported like import foo from './foo' and invoked like foo.x(). Then, you can easily stub it with sinon.stub(foo, 'x'). Of course, the './foo' file will have to exist for this still, but what it really comes down to is how hardcore you want to be about TDD practices versus how much complexity you're willing to introduce to your mocking/stubbing process. I prefer relaxing the former to avoid the latter, but in the end it's up to you.
If you are using Jest, it can be achieved easily by mocking the import using the inbuilt mock method of jest.
Please refer the link below to find more about ES6 import mocks
https://jestjs.io/docs/en/es6-class-mocks
If you are using jest with JavaScript this is very simple:
use jest.mock('MODULE_NAME')
If it is a node module or your own module, no problem jest will automatically mock that module.

What determines the order of `require` calls in babel-transpiled scripts?

So, my workflow up to this point was to put
import "babel-polyfill";
when using features like async/await to ask babel to include the regenerator runtime in the transpilation.
I see the the following problems for users requiring my module:
The user is in an ES2015 environment and transpiles his code with babel-polyfill, too. Since babel-polyfill can only be required once, he will not be able to use my module at all.
If I thus choose not to include babel-polyfill, babel doesn't know that the module does require babel-polyfill and won't respect that in the generated require order (at least that's what I think happens).
I've recently created an npm module that does not come with babel-polyfill, but requires the user to include babel-polyfill before calling require on my npm module, since it uses async and await.
Thus, in my current project, I'd like to use my module like so in index.js:
import "babel-polyfill";
import Server from "./Server";
import foo from "bar";
import baz from "qux";
where Server is a class that extends my module that requires babel-polyfill.
However, the transpilation of index.js starts like this:
!function(e, r) {
if ("function" == typeof define && define.amd)
define(["bar", "qux", "./Server", "babel-polyfill"], r);
else if ("undefined" != typeof exports)
r(require("bar"), require("qux"), require("./Server"), require("babel-polyfill"));
// etc.
}();
Here, I can clearly see that ./Server is required before babel-polyfill, although my ES2015 import syntax asks for the opposite. In fact, the entire order is mixed up.
That's why I'm getting the error:
ReferenceError: regeneratorRuntime is not defined
How can I tell babel to respect the order in my source?
From what I can tell, you can't tell Babel to respect the order of your source - it will always hoist the imports and evaluate everything else afterwards. The only way seems to be switching to require when you want to ensure evaluation of some code (usually global assignments) first. As per my answer here.
Numerous issues raised (and closed/rejected) against Babel relating to this.

Using node require with Electron and Webpack

I am building a project with Electron, and using Webpack to build the (Angular 2) render process app.
In this app, I need to dynamically require some files at run-time which do not exist at build-time. The code looks something like this:
require("fs").readdirSync(this.path).forEach(file => {
let myModule = require(path.join(this.path, file));
// do stuff with myModule
});
The problem is that the Webpack compiler will convert the require() call to its own __webpack_require__() and at run-time, it will look in its own internal module registry for the dynamic "myModule" file, and of course will not find it.
I have tried using the "externals" config option, but since this is a dynamic require, it doesn't seem to be processed by "externals".
Anyone else had success in solving this problem?
As suggested in a comment to my question by #jantimon, the solution is to use global.require:
require("fs").readdirSync(this.path).forEach(file => {
let myModule = global.require(path.join(this.path, file));
// do stuff with myModule
});
I came across this article and for some other reason the author needs node modules which gets not transpiled by webpack. He suggested to use
new webpack.IgnorePlugin(new RegExp("^(fs|ipc)$"))
in the webpack.config.js file. This should prevent to transpile the module fs and ipc so it can be used (required) in code.
I am not really sure if this hits also your problem but it might help.
The original article for more context can be found here: https://medium.com/#Agro/developing-desktop-applications-with-electron-and-react-40d117d97564#.927tyjq0y

node-migrate: can I use es6 import in migration script?

With node-migration npm package can I use es6 imports
I want to do:
import dash from './utils/rethinkdb';
let r = dash();
exports.up = function(next){
next();
};
exports.down = function(next){
next();
};
I know that i can just require, but I am writing everything in es6 so, wanted to be consistent
Thx
It does not necessarily depend on the migration framework you use, but on node.js itself.
Node.js has a "bit" of support for ES6 already, by using the --harmony flag. Take a look at it, if all your features you want are covered by --harmony, this might be an option:
https://github.com/joyent/node/wiki/es6-%28a.k.a.-harmony%29-features-implemented-in-v8-and-available-in-node
Another option is to use https://babeljs.io/ to transpile your code back to ES5 in order to run it.
Also note, if you're using io.js, you have to know that io.js doesn't handle the --harmony flag exactly the same as node does. All you need to know about this, you can read here:
https://iojs.org/en/es6.html

Is there dojo.hitch equivalent in node.js

I am looking for a function that kind bind the 'this' of a function. Although it is easy to write one, I want to be sure that it is not part of any popular module in node.js environment before I write or use the one from dojo.
(function() {
alert(this.toString());
}).bind(new String("Man ES5 is awesome.")).call();
Function.prototype.bind[docs]
Node.js runs on V8. V8 is fully ES5 compliant.

Resources