5

Desired Behaviour

I am trying to import code from one file into another with:

lib.js

// generate unique id
export const guid = () => {
    const s4 = () => {
        return Math.floor((1 + Math.random()) * 0x10000)
            .toString(16)
            .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
        s4() + '-' + s4() + s4() + s4();
}

// get current date as ISO string  
export const currentDateTimeISOString = () => {
    var iso_string = new Date().toISOString();
    return iso_string;
}

// convert boolean string to boolean
export const stringToBoolean = (val) => {
    var a = {
        'true': true,
        'false': false
    };
    return a[val];
}

app_es6.js

import { guid, currentDateTimeISOString, stringToBoolean } from './src/js/lib';  

Actual Behaviour

After build I get the error:

export const guid = () => {
^^^^^^

SyntaxError: Unexpected token export

What I've Tried

I've googled this error and come across various solutions.

The most up to date approach seems to be:

npm install babel-register babel-preset-env --save-dev  

source

I currently have the following babel related dev dependencies in package.json:

"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-0": "^6.24.1",

And .babelrc is:

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

I recently changed .babelrc to the above in order to handle async/await usage, it used to be:

{
    "presets": [
        "env",
        "stage-0"
    ]
}

My build script in package.json is:

"build-server-file": "babel app_es6.js --out-file app.js",

I'm concerned about implementing a solution that is outdated or breaks functionality with another part of the codebase (ie, if i revert to my previous version of .babelrc then async/await will throw errors). I've also read that stage-x is depreciated.

Question

What is the most up to date way to import/export modules in ES6 in a Node.js environment whilst still supporting the .babelrc requirements for async/await?

user1063287
  • 10,265
  • 25
  • 122
  • 218

4 Answers4

1

Notice that the SyntaxError is being thrown from within lib.js and not app.js --this is almost certainly the result of that file not being transformed.

The babel command you're using, babel app_es6.js --out-file app.js is processing app_es6.js; however, lib.js is untouched and that's likely why you still see ESM export syntax when require()ing the file.

I set up a minimal gist with updates to what I know about your current setup to make this work the way (I think) you intended: https://gist.github.com/knksmith57/a554defde2d3d7cf64c4f453565352a0

The trick is to process the entire source directory and not just your entrypoint file.

tl;dr:

  1. process the entire source directory, not just the entrypoint
  2. tell preset-env to use cjs (alias for commonjs) as the target module type
  3. enable a plugin to transform async functions to generator functions (in babel 7.x, that's @babel/plugin-transform-async-to-generator)
  4. look at that gist for a complete working example

If you run into trouble backporting my example to babel 6.x, let me know and I can make some time to follow up.

Hope this helps!

knksmith57
  • 1,096
  • 8
  • 6
0

It looks like you're trying to run a node.js "server".

  1. npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node @babel/plugin-transform-async-to-generator

Using the @babel/ namespace will upgrade you from babel 6 to babel 7, the current latest version. The plugin does the async transformation

  1. Setup a .babelrc or now with 7, especially if you're using node_modules with their own babel configurations, you can use a babel.config.js like this:
module.exports = {
      presets: [ '@babel/preset-env'],
      plugins: [
        '@babel/plugin-transform-async-to-generator'
      ]
    };
  1. Update your package.json build scripts to something more like this:
 "scripts": {
  "build": "babel src --out-dir dist",
  "start": "node dist/app_es6.js"
 }

You want to compile your /lib/ folder into a /dist/ one. This is the most common pattern you'll see in the community.

As you are looking to make an es6 web-app, I would not recommend actually compiling everything to commonjs (cjs), as that will break webpack (via the babel-loader) from performing tree-shaking. It only works when you use import/exports and setting babel to cjs instead of the default ems will make everything require/module.exports.

Nicolas Bouvrette
  • 4,295
  • 1
  • 39
  • 53
adamrights
  • 1,701
  • 1
  • 11
  • 27
0

which version of node are you using?

you can easily update your node to version >= 10v to use official ES6 features support.

eerFun
  • 145
  • 8
0

Actually, I had the same problem and I fix it by a babel plugin that name is transform-runtime, and my .babelrc the file became like below:

{
  "presets": [
    "es2015",
    "es2016",
    "es2017",
    "react",
    "env",
    "stage-0"
  ],
  "plugins": [
    "transform-class-properties",
    "transform-object-rest-spread",
    [
      "transform-runtime",
      {
        "helpers": true,
        "polyfill": true,
        "regenerator": true
      }
    ]
  ],
  "env": {
    "development": {
      "compact": false
    }
  }
}

For more information about this plugin read this link.

AmerllicA
  • 29,059
  • 15
  • 130
  • 154