5

关于package.json中main字段的指向问题

 2 years ago
source link: https://jingsam.github.io/2018/03/12/npm-main.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

package.json中的main字段指向的是Library的入口,通常有3个选择:

1.指向源代码入口文件,如src/index.js;
2.指向打包后的开发版本,如dist/library.js;
3.指向打包后的发布版本,如dist/library.min.js

引用Library的方式也分为两种:

1.通过script标签直接引用,适用于简单页面;
2.通过require或import方式引用,需要借助打包工具打包,适用于复杂页面。

本文探讨一下main字段如何指定,才能兼顾各种引用方式。

指向源代码入口文件

第一种方式指向源码入口,这种情况仅适用于require方式引用。由于指向的是源代码,需要库使用者借助打包工具如webpack,自行对库进行打包。此方式存在以下问题:

1.webpack配置babel-loader一般会排除node_modules,意味着不会对library进行转译,可能会导致打包后的代码中包含ES6代码,造成低版本浏览器兼容问题;
2.如果library的编译需要一些特别的loader或loader配置,使用者需要在自己的配置中加上这些配置,否则会造成编译失败;
3.使用者的打包工具需要收集library的依赖,造成打包编译速度慢,影响开发体验。

总的来说,第一种方式需要使用者自行对library进行编译打包,对使用者造成额外的负担,因此源代码入口文件不适宜作为库的入口。但是,如果library的目标运行环境只是node端,由于node端不需要对源代码进行编译打包,所以这种情况下可以使用src/index.js作为库入口。

指向打包后的开发版本

开发版本的主要作用是便于调试,文件体积并不是开发版本所关心的问题,这是因为开发版本通常是托管在localhost上,文件大小基本没影响。

开发版本主要通过以下手段来方便调试,提升开发体验:

1.预先进行依赖收集和babel转译,即使用者不再需要对library进行这两步工作了,提高编译打包的效率;
2.尽量保留源代码的格式,保证开发版本里面的源代码基本可读;
3.保留警告信息,对开发者对库的错误或不合理调用进行提示。

其中第3点是通过库代码中添加如下类似代码实现的:

if (process.env.NODE_ENV === 'development') {
console.warn('Some useful warnings.')
}

生成开发版本的似乎,webpack的DefinePlugin会将process.env.NODE_ENV替换为development,所以以上代码变为:

if ('development' === 'development') {
console.warn('Some useful warnings.')
}

这就表示上述条件一直成立,warning信息会显示出来。

最近和iview的开发者争论一件事,即在生成library的开发版本的时候,NODE_ENV应该设置为development还是production。他们认为应该设置为production,理由是可以减小开发版本的体积。假设DefinePlugin将process.env.NODE_ENV替换为production,之前的示例代码会变为:

if ('production' === 'development') {
console.warn('Some useful warnings.')
}

这就意味着你使用库开发应用时,不会看到任何警告信息,这不利于提前发现错误。可能有的人会说,我的源代码中没有if (process.env.NODE_ENV === 'development') {}这类代码,所以设置为production也不会有任何问题呀。殊不知,虽然你的源代码中这种没有这类提示代码,但是你的devependencies里面可能会有啊,这样做就会关闭依赖中的warning信息。

可能又有疑问:“引用开发版本的包体积很大,岂不是让我的应用打包上线版本很大?”其实完全不用担心,因为应用打包为上线版本时,会经过两个额外的工作:

1.使用DefinePlugin将process.env.NODE_ENV替换为production,关闭所有警告信息;
2.使用UglifyJsPlugin对应用代码进行minify,减小应用体积。同时会删除if ('production' === 'development') {}这类永远不会执行的代码,进一步减小应用体积。

所以,在开发时应用开发版本,不必担心最后的应用体积。但是如果开发时是以script标签的方式引用库的开发版本,上线时应该替换为响应的发布版本。

指向打包后的发布版本

发布版本追求的是尽量减小体积,因为相比于JS引擎解析的时间,网络传输是最慢的,所以要通过减小库的体积,减少网络传输的时间。

减小发布版本的文件体积,主要是通过将process.env.NODE_ENV设置为production,然后再使用UglifyJsPlugin对应用代码进行minify以及删除永不执行的代码。

那么将库的发布版本作为入口文件合不合适呢?显然不合适,因为发布版本的是经过高度压缩精简的,代码完全不可读,应用开发阶段难以调试。

发布版本是适用于在应用上线时,通过script标签形式引用。

通过上面的分析,可以发现将库的开发版本作为库的入口才是正确合理的做法,即设置"main": "dist/library.js"。而作为库的开发者,也要遵循约定,生成库的开发版本的时候,使用development环境变量,保留警告信息。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK