npm file方式引入公共包遇到的几个坑
背景
在《前端多个vue项目公共组件的三种方法(推荐npm file引入)》这一篇里讲了npm通过file方式引入公共包的方法,但在实际运用中,会遇到不少坑,这里就讲述笔者遇到的2个问题并给出解决方案。
问题一
通过file方式引入的包,npm不会自动安装该包的依赖。
例:项目A通过file方式引入了包B,如下所示。在
项目A的package.json:
{"name": "A","version": "0.1.0","dependencies": {"B": "file:../B"}//...
}
项目B的package.json:
{"name": "B","version": "0.1.0","dependencies": {"axios": "^0.19.2"}//...
}
如此在项目A中执行npm install时,不会安装axios包,node_modules中只有一个通过软链接引入的B。
解决方案
主要思路:
- 增加一个webpack插件,DepPlugin,在entryOption hook,也就是webpack刚处理完配置项之后,执行插件。
- 读取主项目package.json中dependencies中所有依赖,读取所有file引入npm包中dependencies中的依赖和版本号,两者取差集,也就是在file引入npm包中依赖的但主项目中没有的。
- 一次性安装上述所得的所有依赖,执行
npm install a@1.0 b@2.1 c@3.2 --no-save
(a b c为依赖包名)。
以下是代码:
vue.config.js
chainWebpack: config => {const depPlugin = require('./plugin/DepPlugin')config.plugin('DepPlugin').use(depPlugin).tap(args => args)
}
DepPlugin.js
'use strict'
const path = require('path')
const sep = path.sep
let cwd = process.cwd()
const execSync = require('child_process').execSyncfunction DepPlugin (options) {this.options = options || {}this.done = false
}
DepPlugin.prototype.apply = function (compiler) {const that = thiscompiler.hooks.entryOption.tap('DepPlugin', compiler => {if(that.done) returnconst mainDependency = getDependency('.' + sep + 'package.json')// 假设有file引入了2个项目,baqi和baqi-chatlet subDependency = {...getSubDependency('baqi'),...getSubDependency('baqi-chat')}const subDependencyKey = Object.keys(subDependency)const mainDependencyKey = Object.keys(mainDependency)// 获取当前包中的依赖// 查找baqi,baqi-chat包中有的依赖,但主包中没有的for (let i = 0; i < subDependencyKey.length; i++) {if (mainDependencyKey.includes(subDependencyKey[i])) {delete subDependency[subDependencyKey[i]]}}// 安装这些依赖execCmdSync('cd ' + cwd)let str = ''for (let dep in subDependency) {// node_modules中没有这些包就安装if (fs.existsSync(path.join(cwd, 'node_modules' + sep + dep)) === false) {str += dep + '@' + subDependency[dep].replace(/\"|\^|\~/g, '') + ' '}}if (str) {execCmdSync('npm install ' + str + '--no-save')}})
}function getSubDependency (moduleName) {const filePath = path.join(cwd, '..' + sep + moduleName + sep + 'package.json')const dependencies = getDependency(filePath)return dependencies
}
function getDependency (packageJsonPath) {const fileObj = JSON.parse(readPackageJson(packageJsonPath))const dependency = fileObj.dependenciesreturn dependency
}
function readPackageJson (packageJsonPath) {const fileStr = fs.readFileSync(packageJsonPath, 'utf8')return fileStr
}
function execCmdSync (cmdStr) {console.log('执行:' + cmdStr)const out = execSync(cmdStr, { encoding: 'utf8' })return out
}
问题二
babel不会自动转义file引入的包,也就是子包中若有ES6写法,在低版本的浏览器中运行时会报错。
解决方案
vue官网这么描述的
所以,可以在vue.config.js中添加
transpileDependencies: [ /[/\\]node_modules[/\\]baqi[/\\]/,/[/\\]node_modules[/\\]baqi-chat[/\\]/
]
此问题同样适用与npm link
npm file方式引入公共包遇到的几个坑相关推荐
- maven引用公共包_maven怎么 引入(或引用/使用) 自定义(或本地/第三方) jar的三种方式 图文教程-Fun言...
准备工作: jar包里的源码是: public class RegexUtils { /** * 验证Email * @param email email地址,格式:zhangsan@zuidaima ...
- Android Studio4.0引入arr包和jar包方式
Android Studio升级到 4.0 并且gradle_plugin 也更新到4.0.0,之后引入jar包和arr包的方式有所变更. 一.第一种引入方式如下: 1.File -> New ...
- Thymeleaf引入公共片段方式
引入公共片段 引入公共片段的th属性,包括三种方式 th:insert 将公共片段,整个插入到声明引入的元素中 th:replace 将声明引入的元素,替换为公共片段 th:include 将被引入的 ...
- Andriod开发中正确引入jar包的方式
andriod中如果引入jar包的方式不对就会出现一些奇怪的错误. 工作的时候恰好有一个jar包需要调用,结果用了很长时间才解决出现的bug. 刚开始是这样引用的(eclipse): 右键工程,Bui ...
- Maven仓库理解、如何引入本地包、Maven多种方式打可执行jar包
转载博客:http://quicker.iteye.com/blog/2319947 有关MAVEN仓库的理解参见:http://blog.csdn.net/wanghantong/article/d ...
- 基于 cz88 纯真IP数据库开发的 IP 解析服务 - 支持 http 协议请求或 rpc 协议请求,也支持第三方包的方式引入直接使用
cz88 基于 cz88 纯真IP数据库开发的 IP 解析服务 - 支持 http 协议请求或 rpc 协议请求,也支持第三方包的方式引入直接使用 Go 语言编写 进程内缓存结果,重复的 ip 查询响 ...
- IDEA手动引入jar包方式
IDEA手动引入jar包 第一种方式,使用idea自带的功能引入.注意本地开发可以,但项目打成jar包时因未添加进去导致打包报错或打包成功启动失败 最后一次性选择(选中第一个,按住shift键,点击最 ...
- Rust引入外部包,VsCode引入失败,Blocking waiting for file lock on package cache lock
引入外部包出错的解决方法 VsCode导入包后一直转圈 首先要停掉Rust server Ctrl + Shift + P 快捷键,输入Stop那个,停掉服务 改用命令行,像这样 可以看到它说 Blo ...
- golang 引入外部包的三种方式:go get, go module, vendor目录
import "github.com/astaxie/beego" 编译出错解决方案: go get:确保你的GOPATH是工程目录,代码在src目录下,然后在命令提示符中输入:g ...
最新文章
- SQL Date 函数
- Asp.Net.Core 系列-中间件和依赖注入进阶篇
- 复制内存时检测到可能的io争用条件_这篇高并发服务模型大科普,内部分享时被老大表扬了...
- 八年技术加持,性能提升10倍,阿里云HBase 2.0首发商用
- 【学习笔记】SAP CO模块概念信息(上)
- 【线上直播】:5G时代VR+8K直播 刷新你的视界认知
- 如何修改浏览器服务器时间格式,浏览器模式怎么改模式
- Unity中的SystemInfo.deviceUniqueIdentifier 唯一ID
- python装饰器有几种_Python装饰器使用你可能不知道的几种姿势
- 基于双二阶广义积分器(DSOGI)的软件锁相环需求的根源及s域仿真
- 苏宁易购:苏宁小店将获4.5亿美元增资
- 符号_特殊符号大全狐狸符号加字和复制
- 数学分析-换底公式证明
- 5G网络身份识别---详解5G-GUTI
- 010-WebBuilder-编写可复用模块+阶段实战效果与代码
- ESP8266 上电 boot 模式
- python函数编写脚本
- 服务器系统壁纸,云服务器壁纸
- 【C++】利用Unicode控制字符-RLO构造欺骗性文件后缀
- Python学习初衷、心得
热门文章
- 部署ebe-shop商城系统(使用IDEA克隆Git项目)
- Android Notification详解
- SVN的服务器端与客户端的下载,安装以及在IDEA中的简单使用
- burpsuite小米手机抓包_burpsuite小米手机抓包_Fiddler抓包实用非常详细
- 图 最短路 Dijkstra 迪杰斯特拉算法
- Javascript函数节流 —— How To Use Throttle
- java自学:MySQL
- coreldraw矫正两张图_利用CorelDRAW矫正图像
- 将小米平板2从低版本安卓适配到高版本的若干收获与思考
- word文档(office)打钩处无法打钩的两种解决办法