本文介绍了将ES模块(.mjs)发布到NPMJS,向后兼容Node< 8.5.0(双包)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

直到Node v8.5.0,发布用ES6编写到NPMJS 的模块是一个简单的过程:使用Babel之类的工具转换ES6代码,并将生成的lib目录发布到NPMJS,而GitHub回购包含src文件.

Up to Node v8.5.0, publishing a module written in ES6 to NPMJS was a straightforward process: transpile the ES6 code using a tool like Babel, and publish to NPMJS the resulting lib directory, while your GitHub repo contains the src files.

Node通过 v8.5.0,发布了对本机模块的实验性支持(export/import)通过--experimental-modules标志.现在可以将纯ES6模块发布到NPMJS ,然后直接使用它们,只要所涉及的文件具有. mjs 扩展名.

With v8.5.0, Node has released experimental support for native modules (export/import) via the --experimental-modules flag. It is now possible to publish purely-ES6 modules to NPMJS, and use them without any transpilation, as long as the files involved have an .mjs extension.

如何发布ES6模块( .mjs ),以便它还可以与不支持ES本机模块的较旧的Node版本一起使用?

How can I publish an ES6 module (.mjs) so that it can also be used with older Node versions, which don't support ES native modules?

推荐答案

更新:

在13.7.0及更高版本中,可以使用有条件导出(自13.10.0+不再是实验性的).尚无很好的文档证明或明显的如何以完全向后兼容的方式执行此操作,但这是我以前在实验中进行过研究:

Update:

This is possible with 13.7.0+ using conditional exports (which as of 13.10.0+ are no longer experimental). It's not well documented or obvious how to do this in a completely backwards-compatible way, but here's the trick which I previously researched back when it was experiemental:

node_modules/mod/package.json

{
    "main": "./lib.js",
    "exports": {
        ".": [
            {
                "import": "./lib.mjs",
                "require": "./lib.js",
                "default": "./lib.js"
            },
            "./lib.js"
        ]
    }
}

node_modules/mod/lib.js

exports.format = 'cjs';

node_modules/mod/lib.mjs

export const format = 'mjs';

现在可以同时使用CommonJS:

Now it's possible to use both CommonJS:

main.js

const {format} = require('mod');

console.log(format);
$ node main.js
cjs

和ES模块:

main.mjs

import {format} from 'mod';

console.log(format);
$ node main.mjs
(node:25573) ExperimentalWarning: The ESM module loader is experimental.
mjs









诀窍是不要在 package.json main中指定确切路径条目.而是使用无扩展名的main条目,或在软件包的根目录中同时提供index.jsindex.mjs.

The trick is not to specify an exact path in the package.json main entry. Instead use an extension-less main entry, or supply both an index.js and index.mjs at the root of the package.

如果不包括扩展名,则Node将动态使用.mjs扩展名(如果可用)并使用ES6加载程序,或者在.js上回退.

If you don't include the extension, Node will dynamically use the .mjs extension if available and using the ES6 loader, or fallback on .js.

"main": "lib/entry"

这将在ES6模块模式下解析为lib/entry.mjs,在CommonJS模式下解析为lib/entry.js,如果MJS文件不可用,则ES6加载程序将退回CommonJS版本.

This will resolve to lib/entry.mjs in ES6 module mode, or lib/entry.js in CommonJS mode, with the ES6 loader falling back on the CommonJS version if the MJS file is not available.

如果您的软件包提供根index.mjs,并且index.js节点将在import -ed时首选index.mjs,并且在require -ed时仍使用index.js(如果没有index.mjs如果提供,则ES6加载程序将使用index.js).这意味着您可以同时提供index.mjs中的ES6模块版本和index.js中的CommonJS转译版本.

If your package supplies a root index.mjs and index.js Node will prefer the index.mjs when import-ed, and still use the index.js when require-ed (if no index.mjs is supplied, the ES6 loader will use the index.js). This means you can supply both an ES6 module version from index.mjs and a CommonJS transpiled version from index.js.

但是,如果包的用户同时使用ES6和CommonJS模块并希望他们引用相同的对象集,那么我会想到一个潜在的问题.在某些情况下,这可能是个问题,但是使用完全相同的模块实例的多个程序包绝对不会给定,因为不同的程序包可能需要不同版本的程序包.

There is one potential issue that I can think of though, if users of your package mix using both the ES6 and CommonJS modules and expect them to reference the same set of objects. In certain edge-cases, this could be an issue, but multiple packages using the exact same module instance was never a given anyway because different packages can require different versions of the package.

index.mjs

import testmod from 'testmod';
console.log(testmod);


index.js

const testmod = require('testmod');
console.log(testmod);


node_modules/testmod/package.json

{
    "name": "testmod",
    "version": "1.0.0"
}

在此文件中,您可以选择使用无扩展名的main条目,如下所示:

In this file, you can optionally use an extension-less main entry like this:

{
    "name": "testmod",
    "version": "1.0.0",
    "main": "index"
}


node_modules/testmod/index.mjs

export default {
    from: 'index.mjs'
};


node_modules/testmod/index.js

module.exports = {
    from: 'index.js'
};

示例输出(省略了实验警告):

$ node --experimental-modules index.mjs
{ from: 'index.mjs' }

$ node --experimental-modules index.js
{ from: 'index.js' }

$ node index.js
{ from: 'index.js' }

这篇关于将ES模块(.mjs)发布到NPMJS,向后兼容Node< 8.5.0(双包)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-09 13:06