@new-cli/get-npm-info
v0.0.9
Published
> TODO: description
Downloads
1
Readme
@new-cli/get-npm-info
Usage
const getNpmInfo = require('@new-cli/get-npm-info');
nodejs引用(import、require)的一些小知识
module type 当nodejs尝试读取一个脚本文件的时候:
如果是从另一个js文件中使用import引用,则以esm处理。require同理。 如果文件拥有.mjs或.cjs扩展名(而不是.js),则以对应方式处理。 寻找最近的package.json,如果其中type=commonjs,则认为这是一个老的cjs文件,而如果type=module,则认为这是一个新的esm文件。如果没有package.json,或者不设置type,默认为commonjs。 如果这些全都不行,则默认是commonjs 当浏览器尝试运行脚本的时候:
如果有type=module,则是esm,否则是古老的全局脚本。 无论什么方式,node和浏览器都是先决定如何读取,再去读文件,绝不会通过文件内容(或各种元数据)判断任何事情。一旦引擎“认为”的格式与实际不符,则直接报错。
CommonJs环境 cjs环境可以调用import()函数引用esm文件,但返回的是promise。
用require()引用则会产生“ERR_REQUIRE_ESM”错误。通过“fix-esm”包可以处理这种情况(原理是用babel实时将esm文件转换成cjs),但它不能解决“import.meta”的问题。
总的来说,不推荐继续使用cjs,对于大部分用户来说,他们会用webpack之类的处理一次。少部分不用打包工具的人应该很懂得如何解决这种简单问题。
ESModule环境 esm环境中不存在require函数,只能用import语句引用esm或者cjs文件。但是nodejs提供了“module.createRequire()”,用它可以创建一个require函数。
其中cjs文件必须用“import def from xxx”的方式引用。
由于部分包实现错误,实际使用的时候可能还需要用“def.default.xxx”。typescript中“esModuleInterop”可以解决这种错误。虽然开启后会需要修改一些代码,但强烈建议开启这个功能,毕竟开启时更接近标准要求的行为。
条件导出 从nodejs16开始,package.json中的exports字段成为默认行为,它能实现同一个包在import和require时(以及浏览器引用时)分别引用不同的文件。(文档)
typescript默认不解析exports,设置“resolvePackageJsonExports”则会首先尝试使用exports,如果不行再考虑用main。(我写这个的时候ts的实现与node实际行为不符,所以先不写别的了……)
有一点需要注意:以后不推荐使用types字段了,定义文件最好就放在js旁边,否则模块解析的时候可能产生一堆问题。
文件扩展名问题 过去在node上写代码,通常不写.js这种扩展名,比如require('./xyz'),除非有个文件就叫xyz,否则node会尝试添加几个常见的扩展名,看看哪个存在,如果是文件夹则会看看有没有package.json,然后再尝试index.js。
node 16开始引入了一种思想(但是到node20都不是默认行为),就是不做这种复杂的尝试,写什么就是什么,当你写import "./a"的时候,如果没有一个文件或文件夹叫“a”就直接报错(所以要求import的时候把.js也写上)。希望这种规范早日普及(