Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ES Modules recipe #1593

Merged
merged 10 commits into from
Feb 12, 2018
146 changes: 146 additions & 0 deletions docs/recipes/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# ES Modules

As of Node.js 8.5.0, ES modules are natively supported, behind a command line option `--experimental-modules`.

However, it works a bit different on Node.js than on web browsers that also natively supported ES Modules. In Node.js, you need to write `.mjs` files instead of commonly known `.js` files. The `.mjs` files do work on the web browsers but they have to be served with the correct Media Type (`text/javascript` or `application/javascript`). There is a [ongoing effort](https://tools.ietf.org/html/draft-bfarias-javascript-mjs-00) working on standardizing `.mjs`.

Good news is that there's already a library named [@std/esm](https://github.com/standard-things/esm) that allows you to write and run ES modules with transpiling. It basically does everything the specs says to make ES modules work on Node.js 4.x and above.

`ava` should be able to do right? Yes, it definitely can but it requires a bit more effort to make things work magically!

## @std/esm

First, install [@std/esm](https://github.com/standard-things/esm) first:

```sh
# Install @std/esm
$ npm install --save @std/esm # or yarn add @std/esm
```

Here's all the configuration that you need to write native ES modules with `ava`:

```json
// package.json

{
...
"scripts": {
...
"test": "ava"
},
"dependencies": {
...
"@std/esm": "^0.15.0"
},
"ava": {
"require": [
"@std/esm"
]
},
"@std/esm": {
"esm": "all",
"cjs": true,
"await": true,
"gz": true
}
Copy link
Contributor

@jdalton jdalton Nov 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👆 I don't believe all those options are needed. Can you try snipping it down to something like:

"@std/esm": "cjs"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdalton Sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet 🍬 !

...
}
```

That's basically it. You can now write native ES modules with `ava`.

```js
// test/index.js

import test from 'ava';

test('2 + 2 = 4', async (t) => {
try {
t.true(2 + 2 === 4);
} catch (e) {
t.fail();
}
});
```

## @std/esm + Typescript

For [TypeScript](https://github.com/Microsoft/TypeScript) users, you can do that too! Let's dive in.

First install `typescript`.

```sh
# Install typescript
$ npm install --save-dev typescript # or yarn add -D typescript
```

To use native ES modules, please modify `tsconfig.json` accordingly.

```json
// tsconfig.json

{
...
"moduleResolution": "node",
"module": "es2015", // or "esnext"
"target": "es2015" // or "esnext"
...
}
```

Then add `@std/esm` configuration into `package.json`.

```json
// package.json

{
...
"scripts": {
...
"test": "tsc && ava"
},
"dependencies": {
...
"@std/esm": "^0.15.0"
},
"devDependencies": {
"typescript": "^2.6.1"
},
"ava": {
"require": [
"@std/esm"
],
},
"@std/esm": {
"esm": "all",
"cjs": true,
"await": true,
"gz": true
}
...
}
```

Effortless writing test scripts with `ava` + `@std/esm` + `TypeScript` is done!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👆 So rad!

```ts
// test/index.ts

// @ts-check

import test from 'ava';

test('2 + 2 = 4', async (ts) => {
try {
t.true(2 + 2 === 4);
} catch (e) {
t.fail();
}
});
```

## Execute test with ava

```sh
$ npm run test # or npm t
```