我们是不是仍然需要为 NPM 预编译包而付出所有这些努力?

Posted

技术标签:

【中文标题】我们是不是仍然需要为 NPM 预编译包而付出所有这些努力?【英文标题】:Do we still have to make all this effort to precompile packages for NPM?我们是否仍然需要为 NPM 预编译包而付出所有这些努力? 【发布时间】:2020-03-26 08:03:39 【问题描述】:

我目前正在从事一个项目,其中将有许多 npm 包。我想对这个项目采取更激进的方法。因此,不应再预编译任何文件。在包的 src 文件夹中将只有 d.ts、ts、js、mjs 文件(正如我所说,它们中的任何一个都不应该被预编译)。我这样做是出于懒惰,因为我认为是时候停止预编译文件了!

我的意思是我应该创建多少个变体? ESModules、AMD、CommonJs、SystemJS?

我的简单想法是:保持原样(import x from 'x', export foo = 123)并且使用该包的开发人员将已经拥有正确的工具(Babel,Typescript)!还是不行?

第二个问题是:包应该编译到哪一层? ES3,ES6?什么打包只使用现代浏览器并且只支持它们的用户? differential loading 会是正确的方法吗? 我只在 html 文件的环境中看到了差异加载。所以作为一个起点!如果开发人员有选择地使用这些软件包,我就不是这种情况。

具体来说,我的问题是:我们还需要付出所有这些努力吗?目前最小的公分母是什么?我不知道统计数字,但我感觉每个人都在他的项目中使用编译器/预处理器(Babel、PostCss)?

您对此有何看法?

【问题讨论】:

【参考方案1】:

根据我的经验,如今 CommonJS 和 ES 模块是相关技术。你可能决定跳过 CommonJS,然后你就可以在没有转译的情况下相处。但是,很多框架和其他库仍然依赖于 CommonJS,它们不能使用 ES 模块。

作为一种轻量级方法,您可以执行以下操作:

首先:默认将所有内容编写为 ES 模块,并将您的包布局为默认用作 ES 模块(例如,在您的 package.json 中设置 "type":"module" 并使用 @ 987654323@ 作为文件结尾)。

然后:使用 Babel,但仅用于创建模块的 CommonJS 后备。这可能如下所示:

将以下开发依赖项添加到您的项目中。 (对于特殊的语法情况,还有其他 Babel 插件;Babel 通常会告诉你它需要哪些):

npm install --save-dev @babel/cli @babel/core @babel/plugin-syntax-import-meta @babel/plugin-transform-modules-commonjs

然后将以下块添加到您的 package.json:

"babel": 
    "plugins": [
        [ "@babel/plugin-transform-modules-commonjs" ],
        [ "@babel/plugin-syntax-import-meta" ]
    ]

现在您可以使用一行简单的 shell 代码将您的 ES 模块转换为 CommonJS:

# assuming your ES modules are in the lib/ directory
for script in $(find lib/ -iname '*.mjs' | grep -v test.mjs | sed -e 's|.mjs||g'); do
    npx babel $script.mjs > $script.cjs
done

您也可以将其作为脚本添加到您的 package.json。

"scripts": 
    "build": "for script in $(find lib/ -iname '*.mjs' | grep -v test.mjs | sed -e 's|.mjs||g'); do npx babel $script.mjs > $script.cjs; done"

现在您可以使用 npm run build 运行它,将其添加为提交挂钩,或者在推送到 NPM 注册表之前运行它。您还可以构建到与 ES 模块所在的文件夹不同的文件夹,并通过 .gitignore 排除该文件夹。

这就是我创建几个库的方式(出于完全相同的原因),并且它在 CommonJS 和 ES 模块环境中都能完美运行。

顺便说一句,NodeJS 有一些关于将包作为 ES 模块和 CommonJS 运送的文档:https://nodejs.org/api/esm.html#esm_dual_commonjs_es_module_packages

【讨论】:

感谢您的回答!我想有一件事我忘了说。我们项目中的包同时适用于浏览器和 nodejs。据我了解.mjs 仅适用于节点,对吧? 大多数前端框架也在命令行上使用 Node (npm) ......所以,无论如何它通常都是 Node。但是 Node 本身实际上并不能很好地运行 ES 模块,它本身就可以与 CommonJS 一起工作。每个想要使用 ES 模块的 Node 项目都必须进行相应的设置。理论上,你也可以在浏览器中使用原生的 ES 模块,但这真的很尴尬。你至少会想要使用像 Parcel 或 Rollup 这样的打包工具。

以上是关于我们是不是仍然需要为 NPM 预编译包而付出所有这些努力?的主要内容,如果未能解决你的问题,请参考以下文章

在使用 github 操作进行构建期间执行诗歌安装时,使用预编译的 numpy 包而不是构建它

在本地构建和使用npm包

如何预编译 Web 应用程序项目?

OSGi:导出一个包而不导出同一个包中的几个类

使用 Gulp 预编译模板

如何让pypi正确识别操作系统