开发Lerna组件库时,如何让Babel-loader忽略package.json的main入口?
嘿,这个问题我维护Lerna组件库的时候也踩过坑!核心就是要让开发环境和生产环境用不同的模块入口——开发时直接加载源码,打包构建后再用dist里的产物。下面给你几个实用的解决方案:
exports字段(最推荐) 现在Node.js、Webpack、Rollup这些工具都支持exports字段,它的优先级比main更高,还能精准区分环境。你可以在每个组件的package.json里这么配置:
{ "name": "@your-lib/button", "main": "./dist/index.js", // 生产环境默认用打包产物 "exports": { ".": { "development": "./src/index.js", // 开发环境直接加载源码 "default": "./dist/index.js" // 兜底用生产产物 } } }
只要你的项目启动时设置了NODE_ENV=development,工具就会自动读取development对应的入口,完全跳过dist目录,直接加载src里的源码。
如果你的项目用Webpack+Babel-loader,可以通过配置强制让工具优先识别源码:
方法A:添加别名映射
在webpack.config.js里,把组件的导入路径直接指向src目录:
const fs = require('fs'); const path = require('path'); module.exports = { resolve: { alias: { // 单个组件配置示例 '@your-lib/button': path.resolve(__dirname, 'packages/button/src/index.js'), // 批量处理所有组件(不用挨个写) ...Object.fromEntries( fs.readdirSync(path.resolve(__dirname, 'packages')).map(pkgName => [ `@your-lib/${pkgName}`, path.resolve(__dirname, `packages/${pkgName}/src/index.js`) ]) ) } } };
这样不管package.json里的main字段写的是什么,Webpack都会直接去src目录找源码文件。
方法B:调整解析字段优先级
你可以在每个组件的package.json里新增一个source字段指向源码:
{ "source": "./src/index.js", "main": "./dist/index.js" }
然后在Webpack配置里把source字段的优先级设为最高:
module.exports = { resolve: { mainFields: ['source', 'main'] // 先找source字段,找不到再用main } };
同时,给Babel-loader设置只处理src目录的文件,排除dist:
module.exports = { module: { rules: [ { test: /\.jsx?$/, include: path.resolve(__dirname, 'packages/**/src'), exclude: path.resolve(__dirname, 'packages/**/dist'), use: 'babel-loader' } ] } };
如果上面的方法暂时没法用,你可以在组件根目录加一个入口文件,根据环境变量切换导入:
// packages/button/index.js if (process.env.NODE_ENV === 'development') { module.exports = require('./src/index.js'); } else { module.exports = require('./dist/index.js'); }
然后把package.json的main设为这个根目录的index.js:
{ "main": "./index.js" }
不过这个方法有点繁琐,每个组件都要加,还可能有缓存问题,只适合临时应急。
最后提醒下:开发时记得把dist目录加入.gitignore,别提交构建产物;生产构建时要确保正确打包到dist目录,保证线上环境能读到正确的产物。
内容的提问来源于stack exchange,提问作者adi518

