相关文章推荐
热心的移动电源  ·  powerbasic ...·  4 月前    · 
玩命的火车  ·  Android ...·  11 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams "dev": "babel-node src/index.mjs", "build": "babel src --out-dir build", "start": "node build/index.js" "author": "", "license": "ISC", "dependencies": { "express": "^4.18.2" "devDependencies": { "@babel/cli": "^7.19.3", "@babel/core": "^7.19.6", "@babel/node": "^7.19.1", "@babel/plugin-transform-runtime": "^7.19.6", "@babel/preset-env": "^7.19.4", "babel-plugin-module-extension": "^0.1.3"

/.babelrc.js

module.exports = {
  presets: ['@babel/preset-env'],
  plugins: ['@babel/transform-runtime', ['module-extension', { mjs: 'js' }]],
  sourceMaps: false,
  retainLines: false,
  minified: true,

/src/index.mjs

import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import { sum } from './utils.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
app.get('/', (req, res) => {
  const result = sum(3, 2);
  res.send(`current dir: ${__dirname} | sum(3, 2) = ${result}`);
const port = 8080;
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)

src/utils.mjs

export const sum = (num1, num2) => num1 + num2;

I can properly test the website with the command:

$ npm run dev

Then going to: http://localhost:8080

I can properly build the website with the command:

$ npm run build

Which will generate a new directory: /build.

My problem is: When I try to run the built website with command:

$ npm start

I get the following error: SyntaxError: Cannot use 'import.meta' outside a module. Below you have the full error:

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
> test-backend@1.0.0 start
> node build/index.js
D:\myproject\build\index.js:1
"use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _express=_interopRequireDefault(require("express"));var _path=_interopRequireDefault(require("path"));var _url=require("url");var _utils=require("./utils.js");var _filename=(0,_url.fileURLToPath)(import.meta.url);var _dirname=_path["default"].dirname(_filename);var app=(0,_express["default"])();app.get("/",function(req,res){var result=(0,_utils.sum)(3,2);res.send("current dir: ".concat(_dirname," | sum(3, 2) = ").concat(result))});var port=8080;app.listen(port,function(){console.log("Example app listening on port ".concat(port))});
SyntaxError: Cannot use 'import.meta' outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1033:15)
    at Module._compile (node:internal/modules/cjs/loader:1069:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

The issue indicates it is caused because the following lines on: /src/index.mjs:

import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

Here is the transpiled /build/index.js

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _express = _interopRequireDefault(require("express"));
var _path = _interopRequireDefault(require("path"));
var _url = require("url");
var _utils = require("./utils.js");
var _filename = (0, _url.fileURLToPath)(import.meta.url);
var _dirname = _path["default"].dirname(_filename);
var app = (0, _express["default"])();
app.get("/", function (req, res) {
  var result = (0, _utils.sum)(3, 2);
  res.send("current dir: ".concat(_dirname, " | sum(3, 2) = ").concat(result));
var port = 8080;
app.listen(port, function () {
  console.log("Example app listening on port ".concat(port));

where you can see the code uses: import.meta.url which is the conflicting line.

My requirements are:

  • Need to get the current working directoy because I have resources in there that I need for the app to run.
  • Need the source code to be: ES6 so I can use classes, imports, exports, etc.
  • Any idea on how to make this work?

    Thanks!

    Do you need the build to be CommonJS or ESM?

    For an ESM build on a supported Node version you can:

  • Update package.json

    "type": "module"
    
  • Update ./babelrc.js:

      export default {
         presets: [['@babel/preset-env', { modules: false }]],
         // The rest is the same ...
    

    About the modules setting

    Setting this to false will preserve ES modules.

    Now run

    npm run build
    npm start
    

    Alternatively, you can use babel's --out-file-extension option and use .mjs in your build script. You would still need to update @babel/preset-env to preserve the ES module system. I think it is cleaner and clearer to use "type": "module" in the package.json whenever you want to use ES modules.

    For a CommonJS build you would need to:

  • Rename your files from .mjs to .js so the heuristic for determining the module system isn't toggling between ESM and CommonJS for dev/build runs.
  • Remove usage of import.meta and use the __dirname global available to CommonJS modules.
  • Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

  •