admin管理员组文章数量:1193808
I have an Azure Function (which uses NodeJS) from which I'm trying to consume an npm module published by another team. After npm adding the module in question, I try to use it like this:
import * as Model from "@thing/app-model";
...
const appModel: Model.TheModel = new Model.TheModel([]);
However, when I try to run the Azure Function, I get this error:
[error] Worker was unable to load function pump: 'SyntaxError: Unexpected token export'
The results related to that error message that I could find online say that this error usually indicates I'm trying to consume an ES6 module, something that Node doesn't support (instead I should be consuming a CommonJS module). The challenge is that I thought the module WAS a CommonJS module. The tsconfig.json for the project that is producing the module has this line in the compilerOptions:
"module": "commonjs"
In order to verify or rule out the ES6 vs CommonJS problem, if I look at the imported module in my Azure Function's node_modules directory, is there a way to tell by looking at it if it's an ES6 module or a CommonJS module?
Thanks!
I have an Azure Function (which uses NodeJS) from which I'm trying to consume an npm module published by another team. After npm adding the module in question, I try to use it like this:
import * as Model from "@thing/app-model";
...
const appModel: Model.TheModel = new Model.TheModel([]);
However, when I try to run the Azure Function, I get this error:
[error] Worker was unable to load function pump: 'SyntaxError: Unexpected token export'
The results related to that error message that I could find online say that this error usually indicates I'm trying to consume an ES6 module, something that Node doesn't support (instead I should be consuming a CommonJS module). The challenge is that I thought the module WAS a CommonJS module. The tsconfig.json for the project that is producing the module has this line in the compilerOptions:
"module": "commonjs"
In order to verify or rule out the ES6 vs CommonJS problem, if I look at the imported module in my Azure Function's node_modules directory, is there a way to tell by looking at it if it's an ES6 module or a CommonJS module?
Thanks!
Share Improve this question edited Nov 4, 2021 at 22:47 Auth Infant asked Jul 9, 2019 at 21:35 Auth InfantAuth Infant 1,9752 gold badges20 silver badges37 bronze badges 2- Check out related question stackoverflow.com/questions/42708484/…, and the blog post linked there (medium.com/webpack/…), and the now-removed documentation github.com/nodejs/node-eps/blob/… to see if this helps you. I don't have time to distill a proper answer, and link-only answers are not acceptable, so this is as far as I can point you right now. – 000 Commented Jul 9, 2019 at 21:55
- So, in some ways the answer to this question is far more clear, but since modules are now often times compiled into different module types in an attempt to extend support to a larger group of users, you can't just assume that a module is of a certain type. It could be both. Hopefully module-authors will clearly document what they are doing, but in the event that they do not document there project well, I have added a fairly clear & concise answer below. – AKUMA no ONI Commented Jun 6, 2022 at 15:28
3 Answers
Reset to default 16Modules in Node are very different than they were only a Month ago, and even more so than 18-20 months ago. As of JUNE 2022 this is the most current means for inspecting a TS-Node package, and inferring the module-type of the package.
The inspected package can be, cjs
, esm
or both (cjs
& esm
)
Its now possible to use TypeScript to build a CJS module, and an ESM module from one TS-Node code-base (or project if you will). In-fact, if your going to maintain both module types, its almost a necessity to have a transpiler (unfortunately I can't go further into detail, as such a topic extends past the scope of the original question).
It Should be Noted: Knowing how to infer a module type from a TS-Node package, is close to the same as knowing how to configure TS-Node packages as different mod0ule-types.
The Module-type of a TS-Node Package can be Inferred from 2 Files
- The
package.json
- The
tsconfig.json
In the package.json
File
...the "type"
property is where the module type is defined. Its important to note, that this is where Node.js
will also infer what the modules type is, and how it should be expected to resolve modules with-in the project. TypeScript isn't present during Runtime, where Node.js is the Runtime Environment. Because Node.js is the RTE, its a bit more concrete to look at the package.json
, and infer the module type from it, however, the story is far from over. JavaScript Modules make for a complex topic now.
Before I move on, lets look at a package.json
for an ESM configuration.
ESM Configured package.json
// FILE: "./package.json"
{
"name": "foo-pkg-bar"
"version": "1.23.4",
"type": "module", // <-- You're Looking for this K/V pair
"license": "MIT",
"desc": "some description here...",
/*
...rest of the JSON-file's properties...
*/
}
When the module is an ES-Module
or (ESM
), it will have its package.json
property set to "module"
.
In a CommonJS Module
(or CJS Module
) the configuration isn't required to be explicit. This means that you can have the "type"
property completely left out of the package.json
file, and in that very common situation the module-type will default to CJS
. The "type"
property can be configured to implicitly declare the module-type as CJS
though, which in that case the "type"
property will look like this:
{
name: "foobar-foofoo-head",
version: 1.23.4,
type: "commonjs"
}
Multiple Package.json Files
Often times there can be, and in dual-module-typed packages (packages that are built to support both ESM & CJS environments), there is going to be, more than a single package.json
file. In a dual-module-typed package, the ESM
build will have a package.json
file that has the single property added to it as shown bellow.
// package.json for the ESM build
{
"type": "module"
}
CJS
will also have its own type package.json file, and it will also have a single property added to it (see below).
// package.json for the CJS build
{
"type": "commonjs"
}
The rest of the package.json file will be in the ROOT-package.json file. In such a situation the file-structure will look somthing like this.
├── build
│ ├── cjs
│ │ ├── lib
│ │ │ ├── project-stuff.d.ts
│ │ │ └── project-stuff.js
│ │ ├── main.cjs
│ │ ├── main.d.cts
│ │ └── package.json // <-- CJS "package.json"
│ └── esm
│ ├── lib
│ │ ├── project-stuff.d.ts
│ │ └── project-stuff.js
│ ├── main.d.mts
│ ├── main.mjs
│ └── package.json // <-- ESM "package.json"
├── package.json // <-- ROOT "package.json"
├── package-lock.json
├── src
│ ├── lib
│ │ └── project-stuff.ts
│ ├── main.cts
│ └── main.mts
├── tsconfig.base.json
├── tsconfig.cjs.json
└── tsconfig.esm.json
The above is actually from the project I built to teach myself how to trans-pile to both module types.
You probably noticed the many tsconfig.json
files?
Honestly, if you see tsconfig files with that naming convention, you don't need to inspect any further, it definitely can be used as either a CJS
, or an ESM
module (assuming its a working package).
Inspecting the TSConfig for the Package's Module-type
The TSConfig can also be used to infer which module-type any given TS/Node project is. Open the TSConfig, and look for the Module & Module resolution properties.
TS v4.7, eased support for ESM in Node/TS projects
The support for ESM in Node packages that are trans-piled using TypeScript was eased by the addition of valid values that can be passed to the tsconfig.json
files configuration properties "module"
and "moduleResolution"
"module"
& module resolution can now accept the new values
node12
(no top level await),node16
(ESM standard implemented for the LTS node16 version) &nodenext
(most current ESM standard)
If you see the module
& moduleResolution
properties set to these values then the project is being transpiled as an ES-Module.
CJS & ESM
Modules can be both, CJS & ESM. If a package is being trans piled into a CJS build & ESM build, you should see two separate directories for the builds.
There should be separate package.json
files for each build, that take advantage of the cascading file structure that package.json
files are able to be placed in (e.g. a tree-like hierarchy).
- There should be a base
package.json
file. - One
package.json
file should have its"type"
property set tomodule
- while the other
package.json
file should have its"type"
property set tocommonjs
this is a sign that the package, not only supports both ESM & CJS, but is both ESM & CJS
You can, once again, Infer the Module-type by Inspecting the tsconfig.json
files.
There will also be multiple TSConfig files. The thing about the TS Configuration files, is that there is not any one way that they will be named, or structurally set up. From what I see, most use a tsconfig.base
, then extend it to two other tsconfig.*.json
files.
Something like this:
- There will be the tsconfig.base.json file (I have seen this also named
tsconfig-base.json
as well) - There should be a
tsconfig.*.json
file for CJS - Then there should be a
tsconfig.*.json
file for ESM as well.
The naming conventions are not static, there highly configurable, and customizable (which is what we all love about TS right?). Getting use to this can be difficult for some. It was hard for me at first.
The key is to read each TSConfig, and see what the module
& moduleResolution
properties are set to. If you see a tsconfig with the module property set to "commonjs", and another tsconfig
has its module
property set to NodeNext
, that means the project trans-piles to both ESM
& CJS
module types.
Find the npm package in your node_modules folder the open the package.json
.
The package may support CommonJs and/or ES6, so you may have combination.
You should see something like this:
"main": "dist/index.js",
"module": "dist/my-module.esm.js",
The main
usually points to the CommonJs version and module
points to the ESM version.
This is a general case and isn't always true. Sometimes the file ended can show you if it supports both, e.g. index.cjs.js
, index.esm.js
The compiler configuration in the repo you're importing does not tell you what code is downloaded when you install the package. Open package.json from the imported package and check what the main property is pointing to. Next open that file and you will see what code you're actually receiving. It is up to the publishing of a package to transpile the code into whatever format the author wants to make available to the users of the package.
本文标签: javascriptHow can I tell if a particular module is a CommonJS module or an ES6 moduleStack Overflow
版权声明:本文标题:javascript - How can I tell if a particular module is a CommonJS module or an ES6 module? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738428730a2086274.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论