Azure / azure-functions-nodejs-worker

The Node.js worker for the Azure Functions runtime - https://functions.azure.com
MIT License
107 stars 44 forks source link

Add ES6 Style Exports #104

Open ColbyTresness opened 6 years ago

ColbyTresness commented 6 years ago

Will update issue with more information later on.

mhoeger commented 6 years ago

@ColbyTresness - you brought this up, but putting here for posterity: We'll wait until node.js has ES6 style export capabilities, and not worry about trying to enable an experimental node feature or transpiling user code (status of feature here).

ColbyTresness commented 6 years ago

Assigning myself so I don't forget about this

jeffhollan commented 6 years ago

I expect this is what this is tracking but any thoughts on why when I use things like:

import foo from './foo.js'

export default function() { }

I get errors in functions, where as for other node projects where I use node 10 it seems to work? VS Code is telling me something about CommonJS and I frankly don't know where CommonJS, ES6, and Node overlap and if this is related 😕 . Seems from link above seems like we are waiting for something with node?

EDIT: I think I may understand this now. Have only used this in projects with Babel before so I think it was converting to a node compatible format as node doesn't fully adhere to ES6 it appears? Who knows.. and I thought .NET Core / .NET Standard was strange. Is weird that VS Code prompts me to change this though.

willmorgan commented 6 years ago

@jeffhollan You're correct - Node currently just supports CJS style exports (that's require and module.exports = { stuff }. But with a flag, you can switch on ESM, which is in the experimental phase: https://nodejs.org/docs/latest-v10.x/api/esm.html

ColbyTresness commented 6 years ago

@jeffhollan Yes, the fact that VS Code prompts for this is a bug that I brought up with @fiveisprime. We left this issue open though since we'd like to support this once Node does.

jeffhollan commented 6 years ago

Nice thanks. @fiveisprime would be nice if any related code issue we could link

bennypowers commented 4 years ago

You might try using esm, which allows seamless interop between cjs and esm in older node versions:

npm i -S esm
// index.js
// ESM polyfill lets us write source code with Modules, while running CJS
// App code is in main.js.

// Set options as a parameter, environment variable, or rc file.
require = require('esm')(module/* , options*/);
module.exports = require('./main.js');
// main.js
export default async function(context, req) {
  context.log('JavaScript HTTP trigger function processed a request.');

  if (req.query.name || (req.body && req.body.name)) {
    context.res = {
      // status: 200, /* Defaults to 200 */
      body: `Hello ${req.query.name || req.body.name}`,
    };
  } else {
    context.res = {
      status: 400,
      body: 'ESM: Please pass a name on the query string or in the request body',
    };
  }
}
zidzin commented 4 years ago

Is it okay to write require = require('esm')(module/* , options*/); module.exports = require('./main.js'); as module.exports = require('esm')('./main.js');

fabiocav commented 4 years ago

Flagging this as blocked for now. @mhoeger will provide an update and assign it to the correct milestone once we have more information.

simonua commented 3 years ago

Hi,

Quick check if there are any updates. Thank you!

anthonychu commented 3 years ago

This is on the way. We’re adding support for ES modules. If you use the .mjs extension in your function file, you can use ESM syntax. This will be available as a preview feature when running on Node 14.

wpitallo commented 3 years ago

Any updates on this?

anthonychu commented 3 years ago

Yes please see our docs for more details. It’s unclear if ES modules will become stable in Node.js 14 so this feature may keep its “preview” label in Azure Functions until Node.js 16 LTS is available on the platform. https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node?tabs=v2#ecmascript-modules

wpitallo commented 3 years ago

Awesome thank you :)

nosvalds commented 2 years ago

@anthonychu should this be out of Preview now? ES Modules are stable in Node.js 16 now: https://nodejs.org/docs/latest-v16.x/api/esm.html#modules-ecmascript-modules

ejizba commented 2 years ago

Yes this should probably be out of preview by now - we will look into it

sittingbool commented 1 year ago

Hey, since not just Node 16 LTS is stable now but also 18 LTS, how is this ESM support coming? ESM is becoming the new standard.

kf6kjg commented 1 year ago

MAJOR EDIT: I've cleaned up my comment heavily as it showed TWO wrong ways of doing this.

Wow. I'm running an ESM stack with TypeScript. Got this error when trying to start my func:

Worker was unable to load entry point "./dist/index.mjs": Named export 'HttpResponse' not found. The requested module '@azure/functions' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@azure/functions';
const { HttpResponse, app } = pkg;

My index.mts looked like:

import { HttpResponse, app } from '@azure/functions';

app.http('home', {
    methods: ['GET'],
    authLevel: 'anonymous',
    handler: (): HttpResponse => {
        return new HttpResponse({
            status: 200,
            jsonBody: { msg: 'Test succeeded' },
        });
    },
    route: '',
});

And my package.json contained both "type": "module" and a "main": "./dist/index.mjs". The last one irks me a mite since pure ESM projects should be using "module": "./dist/index.mjs" not main - or even exports.*.import. But that's not part of this ticket.

EDIT: bad code and conclusions removed, replaced by correct code that actually works:

import { HttpResponseInit, app } from '@azure/functions';

app.http('home', {
    methods: ['GET'],
    authLevel: 'anonymous',
    handler: (): HttpResponseInit => {
        return {
            status: 200,
            jsonBody: { msg: 'Test succeeded' },
        };
    },
    route: '',
});