如果我们开发一个工具库,package.json中的main可以指向哪里呢?
/dist/***.dev.js/dist/***.prod.js/src/index.js
所以就去研究了一下package.json 中 main字段指向有什么讲究。官方网站中对main的解释是:这是一个项目的入口文件。如果你的模块命名为foo,npm installs foo,然后在项目里require("foo") ,那么main中指向的文件的module's exports 对象将被返回。默认设置为该模块根目录下的index.js。
1、指向打包后的开发版本
一个库的开发版本关注的是调试,保留了警告信息,对使用者对库的错误或不合理调用进行提示。问题:terser-webpack-plugin在配置的时候通过exclude排除对node_modules中模块的压缩,这样会导致线上发布版本体积变大,如果不排除,则导致打包时间增长。
2、指向打包后的生产版本
发布版本追求的是尽量减小体积,减少网络传输的时间。使用UglifyJsPlugin 或着 terser 对应用代码进行minify以及删除永不执行的代码。问题:高度精简压缩的代码去掉了警告信息,不利于开发阶段的调试。
3、指向源代码的入口文件
引入源码入口文件,会有以下问题:
webpack配置babel-loader一般会排除node_modules,意味着不会对library进行转译,可能会导致打包后的代码中包含ES6代码,造成低版本浏览器兼容问题;- 如果
library的编译需要一些特别的loader或loader配置,使用者需要在自己的配置中加上这些配置,否则会造成编译失败; - 使用者的打包工具需要收集
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')
}