如何科学修改 node_modules 里的文件
作者:沉末_ 原文:https://juejin.im/post/5d25b39bf265da1bb67a4176
前言
有时候使用npm
上的包,发现有bug
,我们知道如何修改,但是别人可能一时半会没法更新,或者是我们特殊需求,别人不愿意修改,这时候我们只能自己动手丰衣足食。那么我们应该如何修改别人的源码呢?首先,直接修改node_modules
里面的文件是不太行的,重新安装依赖就没有了。一般常用办法有两个:
- 下载别人代码到本地,放在
src
目录,修改后手动引入。 -
fork
别人的代码到自己仓库,修改后,从自己仓库安装这个插件。
这两个办法的缺陷就是:更新麻烦,我们每次都需要手动去更新代码,无法与插件同步更新。如果我们要修改的代码仅仅是别人的一个小模块,其他大部分代码都不动,这时候有一个很投机的操作:利用 webpack alias
来覆盖别人代码。
webpack alias 的作用
webpack alias
一般用来配置路径别名,使我们可以少写路径代码:
chainWebpack: config => {
config.resolve.alias
.set('@', resolve('src'))
.set('#', resolve('src/views/page1'))
.set('&', resolve('src/views/page2'));
},
也就是说,webpack alias
会替换我们写的“简写路径”,并且它对node_modules
里面的文件也是生效的。这时候我们可以将别人源码里面引用模块的路径替换成我们自己的文件。
具体操作如下:
- 找到别人源码里面的需要修改的模块,复制代码到
src
目录 - 修改其中的
bug
,注意里面引用其他的文件都需要写成绝对路径 - 找到这个模块被引入的路径(我们需要拦截的路径)
- 配置
webpack alias
实际操作一下
以qiankun
框架的patchers
模块为例:
文件被引用的路径为:./patchers
(我们要拦截的路径)
文件内容为:
复制内容到src/assets/patchers.js
,修改其 import
路径为绝对路径,并添加我们的代码:
配置webpack alias
(我用的是vue-cli4
,配置文件是vue.config.js
):
const path = require('path');
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set('./patchers', path.resolve(__dirname, 'src/assets/patchers.js'))
}
};
运行代码,控制台打印成功,表明我们已经成功覆盖别人的代码,而且别人的代码有更新时,我们也可以同步更新,只是这个模块的代码使用我们自定义的。打包之后也是可以的。
补充:使用patch-package
来修改
经掘友 @Leemagination 指点,使用patch-package
来修改node_modules
里面的文件更方便
步骤也很简单:
- 安装
patch-package
:npm i patch-package --save-dev
- 修改
package.json
,新增命令postinstall
:
"scripts": {
+ "postinstall": "patch-package"
}
- 修改
node_modules
里面的代码 - 执行命令:
npx patch-package qiankun
。
第一次使用patch-package
会在项目根目录生成patches
文件夹,里面有修改过的文件diff
记录。
当这个包版本更新后,执行命令:git apply --ignore-whitespace patches/qiankun+2.0.11.patch
即可。其中qiankun+2.0.11.patch
是它生成的文件名。
关于这个 loader 我已经发布到 npm 上,有兴趣的朋友可以直接调用 npm install async-catch-loader -D
安装和研究,使用方法和一般 loader 一样,记得放在 babel-loader 后面,以便优先执行,将注入后的结果继续交给 babel 转义
{
test: /.js$/,
use: [
"babel-loader?cacheDirectory=true",
'async-catch-loader'
]
}
更多细节和源代码可以查看 github,同时本文对您有收获的话,希望能点个 star,非常感谢~
最后
1.看到这里了就点个在看支持下吧,你的「在看」是我创作的动力。
2.关注公众号程序员成长指北
,「带你一起学Node」!
点赞、在看、转发支持作者❤️
- Unikernel初体验
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
- Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、
- Scala学习教程笔记一之基础语法,条件控制,循环控制,函数,数组,集合
- Kafka的生产者和消费者代码解析
- Caused by: java.lang.ClassNotFoundException: backtype.storm.topology.IRichSpout
- 作为完美主义者(强迫症)如何将linux的eth1网卡修改为eth0网卡
- 【入门篇】一个小白在Jetson TX2上安装caffe的踩坑之旅
- 【入门篇】Jetson TX2深度学习Inference初体验
- zeromq的安装,部署(号称最快的消息队列,消息中间件)
- OpenDaylight新建HelloWorld工程并集成版本
- 摸索出来的chrom调试前后台数据(Java&&Ajax)交互的方法分享一下咯!!!
- 机器学习:单词拼写纠正器python实现
- java.lang.Exception: 资源处理失败,失败原因:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【回溯算法】N叉树相关技巧
- 【回溯算法】回溯,从入门到入土,七道试题精选、精讲、精练
- 数据结构练手小项目(AVL树、哈希表、循环链表、MySQL数据库)
- 【LeetCode】每日一题(8.2)二叉树展开为链表
- 【小技巧】argc和argv的用法
- 全面分析redis持久化机制
- 【奇技淫巧】-- 接雨水
- 【奇技淫巧】-- 最长连续序列
- 【redis】跟我一起动手玩玩redis主从复制和哨兵模式
- 【C++】八大排序算法 :GIF + 亲测代码 +专项练习平台
- 【C++】勉强能看的线程池详解
- 国密SSL协议之Java编程
- 7. Jackson用树模型处理JSON是必备技能,不信你看
- epoll,求知者离我近点
- SOCKET网络编程 (通俗易懂入门篇)