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

734 阅读2分钟

如果我们开发一个工具库,package.json中的main可以指向哪里呢?

  1. /dist/***.dev.js
  2. /dist/***.prod.js
  3. /src/index.js

所以就去研究了一下package.json 中 main字段指向有什么讲究。官方网站中对main的解释是:这是一个项目的入口文件。如果你的模块命名为foonpm installs foo,然后在项目里require("foo") ,那么main中指向的文件的module's exports 对象将被返回。默认设置为该模块根目录下的index.js

1、指向打包后的开发版本

一个库的开发版本关注的是调试,保留了警告信息,对使用者对库的错误或不合理调用进行提示。问题:terser-webpack-plugin在配置的时候通过exclude排除对node_modules中模块的压缩,这样会导致线上发布版本体积变大,如果不排除,则导致打包时间增长。

2、指向打包后的生产版本

发布版本追求的是尽量减小体积,减少网络传输的时间。使用UglifyJsPlugin 或着 terser 对应用代码进行minify以及删除永不执行的代码。问题:高度精简压缩的代码去掉了警告信息,不利于开发阶段的调试。

3、指向源代码的入口文件

引入源码入口文件,会有以下问题:

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

4、结论

通过将process.env.NODE_ENV是否是production输出打包后的开发版本和生产版本,这样既满足了我们在开发环境下引入该库时调试代码的需求,也避免了上线后体积过大影响性能的问题。

例如vue3源码每个库的package.json中"main": "index.js",内容类似如下:

'use strict'

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./dist/compiler-core.cjs.prod.js')
} else {
  module.exports = require('./dist/compiler-core.cjs.js')
}

参考:

  1. docs.npmjs.com
  2. 关于package.json中main字段的指向问题