2
votes

My Express.js server is currently being started by running start.js, which in turn runs server.js (code below). For example,

nodemon start.js

Problem: When I try to run the file at src/lib/seed_database.js using

node seed_database.js

we get the errors showing that babel is not transpiling any JS files, such as

SyntaxError: Unexpected token 'export'

What is the recommended way to get babel to work on a file other that server.js?

Environment

  • Node 13.7.0
  • Mac OS X 10.15.2
  • @babel/runtime 7.8.4
  • @babel/core 7.8.4
  • @babel/plugin-transform-runtime 7.8.3
  • @babel/preset-env 7.8.4
  • @babel/register 7.8.3"

Directory Structure

my-app
├── .node_modules
├── src
│   ├── lib
│   │    └── seed_database.js
│   ├── v1
│   │    └── routes.js
│   ├── start.js
│   └── server.js
├── .babelrc
├── package-lock.json
├── package.json

start.js

require("@babel/register")({
    presets: [
      ["@babel/preset-env", {
        "targets": {
          "node": "current"
        }
      }]
    ]
});

module.exports = require('./server.js')

server.js

import express from 'express';
import v1ApiRoutes from './v1/routes';
import constants from './config/constants';

const app = express();
app.use('/v1', v1ApiRoutes);

app.listen(constants.PORT, err => {
    if (err) {
        console.log('Cannot run!')
    } else {
        console.log(`App listening on port: ${constants.PORT}`)
    }
});

seed_database.js

const db = require('../../config/db')['appDb'];

...

db.js

...

export const appDb = appDb;

.babelrc

{
    "plugins": [
        ["@babel/transform-runtime"]
    ]  
}

Update

Jeremy Harris' suggestion works:

require("@babel/register")({
    presets: [
      ["@babel/preset-env", {
        "targets": {
          "node": "current"
        }
      }]
    ]
});

const db = require('../../config/db')['appDb'];

However, when we replace the require line with named imports:

import { appDb as db } from '../../config/db';

we now get a new error

SyntaxError: Cannot use import statement outside a module


Update #2

Using Jeremy Harris' second suggestion of a single entry point works

node start.js seed

start.js

require("@babel/register")({
    presets: [
      ["@babel/preset-env", {
        "targets": {
          "node": "current"
        }
      }]
    ]
});


if (process.argv.indexOf('seed') > -1) {
  module.exports = require('./lib/seed_database.js')
  return
}

 module.exports = require('./server.js')
1
Try adding require("@babel/register") to your seed file.Jeremy Harris
@JeremyHarris That works! However, only works if I use const db = require(...). If we were to use named imports, such as import { appDb as db } from '../../config/db';, then we now get the error SyntaxError: Cannot use import statement outside a moduleNyxynyx
Maybe in start.js, you check for CLI args and if the argument is "seed" then you include the seeder, otherwise the normal server. That way it's only a single entry point for including babel.Jeremy Harris
@JeremyHarris Thanks, now it works! Updated question with the code that works. Is the code written correctly? I find it strange to have 2 module.exports and a return after the first module.exportsNyxynyx
Btw, should the require("@babel/register") line also appear in .bashrc?Nyxynyx

1 Answers

1
votes

As we discussed in the comments, the issue is that your seed file was not including the @babel/register code, hence it didn't transpile it. Per the suggestion with CLI args, you could modify it to use a single module.exports like:

// Default module
let commandModule = './server.js';

// Override with different command
if (process.argv.indexOf('seed') > -1) {
  commandModule = './lib/seed_database.js';
}

module.exports = require(commandModule);

If you want to keep configuration in .babelrc, you can do this when including @babel/register:

require('@babel/register')({
  extends: './.babelrc',
  ignore: [/node_modules/],
});

This GitHub issue discusses some of the issues around it in case you run into any: https://github.com/babel/babel/issues/8321