published on
tags: webpack

NPM 发布ESM源码

Background & Research


如果你调试的时候需要看所依赖的npm包的源码,一般包的入口main都指向dist里被babel或rollup编译过的es5代码。

{
  "name": "my-package",
  "version": "0.1.0",
  "main": "dist/index.js"
}

会指示你的打包工具在require 或 import的时候找到正确的入口文件在哪,但是现在有种更推荐的方式是同时发布编译后的 es5 代码和 es2015+ 源码,让用户选择。

Why?


  1. es2015后,如果使用webpack或rollup构建,可以利用ES Module的很多特性, 加快打包速度, 还可以利用 treeshaking
  2. 每个npm包自行编译,很多模块重复引入,增加代码体积(runtime可能不同)
  3. 转译的结果是固定的,不能根据平台和市场自定义化
  4. 如果编译工具产生隐藏的bug代码,发布到npm上,被大量下载,即使用户编译工具修复了bug,也无法影响包中的源码,只能等待维护者修复。
  5. 发布多种版本库在业内已成为一种标准

How?


publish

将 package.json 的main直接指向es6代码,会产生2个问题。

  1. 在基本上用户webpack编译的时候会选择exclude掉 node_modules下的文件, 这样可以极大的提升编译速度。所以默认都是在npm上发布es5规范的代码。
  2. 如果是node环境的代码,说不会经过构建工具的,不支持es6的话直接运行不起了

因此 package.json 中的main指向es5版本代码,要解决这个问题,rollup提出了module字段,现在也被webpack等构建工具所支持。当构建工具遇到我们的模块时,优先使用module字段入口。然后使用main入口。

创建 library

image

image

webpack config

exclude替换为inclue

{
  test: /\.(js|jsx)$/,
- exclude: /node_modules/,
+ include: [
+       path.resolve('./src'),
+       path.resolve('./node_modules/carno')
+   ], 
  use: {
    loader: 'babel-loader',
  },
}

Research

这里取redux模块进行研究

当我们的 mainFields 设置为 [‘main’] 时,使用webpack build一下 image

设置为[‘module’, ‘main’]时 注意 不能只设置 module,因为有的包只提供 main image

Relate


rollup/rollup

rollup/rollup

nodejs/node-eps

dherman/defense-of-dot-js

解析(resolve)

在 npm 上发布源码

On Consuming (and Publishing) ES2015+ Packages · Babel