中文版在英文版之后。
NPM Publish Reference
Talking over NPM Publish, it is unavoidable to go through the long evolution history of CommonJS and AMD into UMD and finally ES Module. However, we choose to leave it to further reading in References.
In short, we are supposed to publish ES Module stated in module field, for those projects able to recognize ES Module; for other projects unable to do so, we are supposed to publish CommonJS stated in main; if we have browser support requirements, we are supposed to publish UMD instead of CommonJS or side by side.
Published directories
Here we provide a list of well-known javascript/typescript projects on Github, let’s take a look how they publish npm packages:
redux:- adopts
Rollup; - inside repository, places source code under
srcwith nothing else published; - inside
npm, publishes:src;lib(uncompressedCommonJS, pointed bymain);es(uncompressed and compressedES Module, pointed bymodule);dist(uncompressed and compressedUMD, pointed byunpkg);
- adopts
react-use:- adopts
tsc; - inside repository, places source code under
srcwith nothing else published; - inside
npm, publishes:lib(uncompressedCommonJS, pointed bymain);esm(uncompressedES Module, pointed bymodule);
- adopts
vue:- adopts
Rollup; - inside repository, places source code under
src, along withdistpublished; - inside
npm, publishes:src;dist(containing uncompressed and compressedCommonJS, uncompressed and compressedES Moduleand uncompressed and compressedUMD), withmainpointing atCommonJS,modulepointing atES Moduleandunpkgandjsdelivrpointing atUMD;
- adopts
react:- adopts
Rollup; - inside repository, places sources code under
srcof MonoRepo, with nothing else published; - inside
npm, publishes:cjs(uncompressed and compressedCommonJS, pointed bymain);umd(uncompressed and compressedUMD);
- adopts
angular:- adopts internal tools;
- inside repository, places source code under
srcof MonoRepo, with nothing else published; - inside
npm, publishes:bundles(uncompressed and compressedUMD, pointed bymain);- various versions of
ES Module(esmvs.fesm,ES5vs.ES2015,modulepointing atfesm5);
react-router:- adopts
Rollup; - inside repository, places source code under
modulesof MonoRepo, with nothing else published; - inside
npm, publishes:cjs(uncompressed and compressedCommonJS, pointed bymain);esm(uncompressedES Module, pointed bymodule);umd(uncompressed and compressedUMD);
- adopts
axios:- adopts
Webpack; - inside repository, places source code under
lib, along withdistpublished; - inside
npm, publishes:lib;dist(uncompressed and compressedUMD, pointed bymain);
- adopts
material-ui:- adopts
RollupforUMDandBabelforCommonJSandES Module; - inside repository, places source code under
srcof MonoRepo, with nothing else published; - inside
npm, publishes:- root directory (uncompressed
CommonJS, pointed bymain); es(uncompressedES Module);esm(uncompressedES ModuleofES5, pointed bymodule);umd(uncompressed and compressedUMD);
- root directory (uncompressed
- adopts
antd:- adopts
Webpack; - inside repository, places source code under
components, with nothing else published; - inside
npm, publishes:lib(uncompressedCommonJS, pointed bymain);es(uncompressedES Module, pointed bymodule);dist(uncompressed and compressedUMD, pointed byunpkg);
- adopts
element-ui:- adopts
Webpack; - inside repository, places source code under
srcandpackages, with nothing else published; - inside
npm, publishes:lib(single-file and multiple-fileCommonJS, compressedUMD,mainpointing atCommonJS).
- adopts
unpkg links of above mentioned projects can be found in References and package.json has field repository for repository info.
Recommendation
- Adopt
Rollup, for fast compilation, smaller bundle size and clean and straightforward configuration and workflow; - Place source code under
srcorsrcof MonoRepo; - Publish
UMD、CommonJS和ES Modulein separate directories, or in directories with common conventions (e.g.libforCommonJSanddistforUMD); - Publish both uncompressed and compressed
UMD(for development and production purpose); - Publish both uncompressed and compressed
ES Modulesince popular browsers are powerful and smark enough; - Point
mainatCommonJSorUMDandmoduleatES Moduleinpackage.json.
BTW, typescript projects will also publish .d.ts files, which can benefit target users as well as IDEs a lot. Alternatively, you can write your own type definition files.
NPM 发布参考
说到 NPM Publish,免不了去介绍 CommonJS 和 AMD 然后到 UMD 再到 ES Module 的历史,这边把详细介绍放在参考文献里。
简而言之我们需要,发布以 module 为入口的 ES Module 版本,供能识别 ES Module 的项目使用;发布以 main 为入口的 UMD 版本,供浏览器和不能识别 ES Module 的项目使用,如果不需要浏览器支持则可以只发布 CommonJS 版本。
发布目录
这边先罗列一下大家耳熟能详的一些项目的发布方式:
redux:- 使用
Rollup; - 仓库里,源代码在
src,无其他发布内容; npm里,发布:src;lib(非压缩的CommonJS,main);es(非压缩和压缩的ES Module,module);dist(非压缩和压缩的UMD,unpkg);
- 使用
react-use:- 使用
tsc; - 仓库里,源代码在
src,无其他发布内容; npm里,发布:lib(非压缩的CommonJS,main);esm(非压缩的ES Module,module);
- 使用
vue:- 使用
Rollup; - 仓库里,源代码在
src,同时发布dist; npm里,发布:src;dist(非压缩和压缩的CommonJS、非压缩和压缩的ES Module、非压缩和压缩的UMD),main指向CommonJS,module指向ES Module,unpkg和jsdelivr指向UMD;
- 使用
react:- 使用
Rollup; - 仓库里,源代码在 MonoRepo 的
src,无其他发布内容; npm里,发布:cjs(非压缩和压缩的CommonJS,main);umd(非压缩和压缩的UMD);
- 使用
angular:- 使用内部工具;
- 仓库里,源代码在 MonoRepo 的
src,无其他发布内容; npm里,发布:bundles(非压缩和压缩的UMD,main);- 多种
ES Module(esm和fesm,ES5和ES2015,module指向fesm5);
react-router:- 使用
Rollup; - 仓库里,源代码在 MonoRepo 的
modules,无其他发布内容; npm里,发布:cjs(非压缩和压缩的CommonJS,main);esm(非压缩的ES Module,module);umd(非压缩和压缩的UMD);
- 使用
axios:- 使用
Webpack; - 仓库里,源代码在
lib,同时发布dist; npm里,发布:lib;dist(非压缩和压缩的UMD,main);
- 使用
material-ui:- 使用
Rollup生成UMD和Babel生成CommonJS和ES Module; - 仓库里,源代码在 MonoRepo 的
src,无其他发布内容; npm里,发布:- 扁平目录(非压缩的
CommonJS,main); es(非压缩的ES Module);esm(非压缩的ES5的ES Module,module);umd(非压缩和压缩的UMD);
- 扁平目录(非压缩的
- 使用
antd:- 使用
Webpack; - 仓库里,源代码在
components,无其他发布内容; npm里,发布:lib(非压缩的CommonJS,main);es(非压缩的ES Module,module);dist(非压缩和压缩的UMD,unpkg);
- 使用
element-ui:- 使用
Webpack; - 仓库里,源代码在
src和packages,无其他发布内容; npm里,发布:lib(整合和散装的非压缩的CommonJS、压缩的UMD),main指向CommonJS。
- 使用
以上项目都能在参考文献里找到 unpkg 的链接,然后在 package.json 里找到仓库。
推荐方案
- 使用
Rollup,使得你的编译打包更快、体积更小(可以阅读参考文献),编译配置及流程清晰(一些项目整个流程非常繁冗复杂); - 源代码放在
src或者 MonoRepo 的src; - 单独为
UMD、CommonJS和ES Module建立发布目录,或者使用有习惯用途的目录命名(CommonJS放在lib,UMD放在dist); UMD提供非压缩和压缩两个版本(供开发和生产使用);ES Module最好也提供压缩版本,供浏览器使用;package.json的main指向CommonJS或UMD,module指向ES Module。
另外说一下,typescript 的项目会发布 .d.ts 的文件,可以给 IDE 以及开发者提供便利。不过也可以自行编写类型定义文件。
References:
- NPM official documentation: packages-and-modules, npm-package
- JavaScript module system, CommonJS, Asynchronous Module Definition, IIFE
- Popular repositories: redux, react-use, vue, react, angular, react-router, axios, material-ui, antd, element-ui
- Angular Flattening of ES Modules
- The cost of small modules (Rollup recommendation)