4
votes

I'm trying to run async await functions in JavaScript using the babel-loader of webpack. I'm using the following configuration:

{
  name: 'client',
  context: path.join(__dirname, 'src', 'static', 'scripts'),
  entry: {
    index: './index.js'
  },
  output: {
    path: path.join(__dirname, 'src', 'static', 'bundles'),
    filename: '[name].js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'stage-0']
        }
      }
    ]
  },
  resolve: {
    root: path.join(__dirname),
    fallback: path.join(__dirname, 'node_modules'),
    modulesDirectories: ['node_modules'],
  }
}

but it keeps pushing an error with the following message:

Module build failed: Error: ./src/static/scripts/index.js: Expected type "Identifier" with option {}

My index.js has this content:

console.log('hi from app');

async function hello() {
  return Promise.resolve('hi')
}

async function conversation () {
  const hi = await hello()
  console.log(hi);
}
3

3 Answers

1
votes

It looks like you hit a bug. It seems to be solved but not released yet.

If you cannot wait until it is released, you can apply the patch corresponding to the commit that solves the issue.

One way to apply the patch:

Save the following diff into a file (visit.patch for example) in your package root folder. Then apply the patch with git apply visit.patch.


From 940b86dadbd0151c33c02e89f0b5ff61077c9214 Mon Sep 17 00:00:00 2001
From: Henry Zhu <[email protected]>
Date: Thu, 5 Nov 2015 20:10:15 -0500
Subject: [PATCH] transform-regenerator: set node.id to an identifier if null -
 fixes #2835

---
 packages/babel-plugin-transform-regenerator/lib/visit.js | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/node_modules/babel-preset-es2015/node_modules/babel-plugin-transform-regenerator/lib/visit.js b/node_modules/babel-preset-es2015/node_modules/babel-plugin-transform-regenerator/lib/visit.js
index 0f68ffc..c4a0d2e 100644
--- a/node_modules/babel-preset-es2015/node_modules/babel-plugin-transform-regenerator/lib/visit.js
+++ b/node_modules/babel-preset-es2015/node_modules/babel-plugin-transform-regenerator/lib/visit.js
@@ -146,6 +146,10 @@ function getOuterFnExpr(funPath) {
   var node = funPath.node;
   t.assertFunction(node);

+  if (!node.id) {
+    node.id = funPath.scope.parent.generateUidIdentifier("callee");
+  }
+
   if (node.generator && // Non-generator functions don't need to be marked.
       t.isFunctionDeclaration(node)) {
     var pp = funPath.findParent(function (path) {
@@ -171,9 +175,7 @@ function getOuterFnExpr(funPath) {
     );
   }

-  return node.id || (
-    node.id = funPath.scope.parent.generateUidIdentifier("callee")
-  );
+  return node.id;
 }

 function getRuntimeMarkDecl(blockPath) {

Update:

It seems that the bug wasn't properly fixed and the commit has been reverted. Looks like it was due to another problem that has been addressed in this pull request.

2
votes

First, ensure you're using all of the latest versions of babel plug-ins:

npm i -D babel-loader babel-polyfill babel-preset-es2015 babel-preset-stage-0 babel-runtime

(I'm not sure if babel-runtime is actually required- YMMV)

In the entry of your webpack, use this:

  entry: [
    'babel-polyfill',
    './index.js'
  ]

You need the babel-polyfill adding to your entry script to enable "regeneratorRuntime", which is needed for async/await.

Then use the babel-loader in your module section (instead of babel)

  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        loader: 'babel-loader',
        query: {
          presets: [
            'es2015',
            'stage-0'
          ]
        }
      }
    ]

That should fix it.

Note: If you're using Node on the server side, you'll need to add an explicit require('babel-polyfill'); to the top of your entry script to ensure any async/await syntax is recognised.

es2015 and stage-0 weren't enough to polyfill Node 5 - instead, use this in your .babelrc

{
  "presets": [
    "node5"
  ]
}

node5 is a collection of babel plug-ins I maintain to polyfill just those pieces of Node 5.x that are missing. It should mostly work with Node 4.x too (which, with minor variations, are now nearly identical in ES6 compatibility.)

You'll need to install it with NPM first:

npm i -D babel-preset-node5

0
votes

For preset env on node v8.11, I'm having issue of async function simply never run, and no exception.

Then I refer to official documentation and adding target to .babelrc, now it works.

{
  "presets": [
    ["env", {
      "targets": {
        "node": "current"
      }
    }]
  ]
}

Babel documentation