从一个webpack打包bug到探索resolve背后的机制

本文详述了一次在业务升级中遇到的webpack打包bug,深入探讨了webpack resolve plugin和tsconfig-paths-webpack-plugin的工作原理,分析了bug产生的原因并提出了解决方案。重点介绍了如何通过理解enhanced-resolve库来定位和修复问题。
摘要由CSDN通过智能技术生成
背景

最近在业务项目配置升级改造的时候遇到了一个诡异的运行时报错

image

经过进一步调试发现,原因是在业务代码的lib/axios.tsimport axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios';这行代码的引入居然是引入的 业务代码的lib/``axios``.ts而不是node_modules中的axios

由于项目使用的是司内一个二次封装webpack的框架,找相关同学排查后发现是tsconfig-paths-webpack-plugin的一个bug导致。可以看到网上也有人提出了这个issue,并且可以看到有人也提了一个MR去修复这个问题。但是由于提出MR修复的老哥也表示不了解为啥这样改就好了,所作者也表示需要等有足够的单元测试才能将这个进行合并

https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/83
https://github.com/dividab/tsconfig-paths-webpack-plugin/pull/85

image

来都来了,不如就研究清楚这个bug是如何发生的,以及如何去修复

webpack resolve plugin原理

首先tsconfig-paths-webpack-plugin这个plugin是做啥的?

Use this to load modules whose location is specified in the paths section of tsconfig.json when using webpack. This package provides the functionality of the tsconfig-paths package but as a webpack plug-in.

Using this plugin means that you should no longer need to add alias entries in your webpack.config.js which correspond to the paths entries in your tsconfig.json. This plugin creates those alias entries for you, so you don’t have to!

简单说,就是我们使用ts开发项目的时候通常需要配置tsconfig.compilerOptions.paths。默认情况下webpack是不认识这个配置的,通过配置这个webpack插件,即可实现无需在webpack中配置resolve.alias 即可让webpack打包时根据tsconfig的paths找到对应的文件。它底层是是依赖了tsconfig-pathcreateMatchPathAsync函数实现这个模块路径的查找功能

还需要注意一点的是tsconfig-paths-webpack-plugin 是webpack的resolve plugin而不是常规的webpack plugin。两者的区别在于webpack plugin是配置在webpack的config.plugins字段,而webpack resolve plugin是配置在config.resolve.plugins字段。两种插件对应的api也不太一样,webpack plugin一般通过complier/compilation去监听生命周期处理webpack打包整个过程的一些行为;而resolve plugin则专注于处理模块resolve的过程。而webpack配置文件的config.resolve字段基本是都传递给enhanced-resolve这个库是实例化resolver的。webpack内部的模块解析打包的路径处理就是由enhanced-resolve去实现。

下图来自webpack源码的createResolver就是enhanced-resolve提供的

image

在查看tsconfig-paths-webpack-plugin的实现之前了解下enhanced-resolver的架构有助于我们更好地去查bug。

enhanced-resolver 是一种基于core+plugin的运行机制。enhanced-resolver主要提供一个基础的resolver对象通过其resolve方法去处理模块路径查找;提供plugin的机制,基于tapable实现事件通信串联起webpack内部和resolver plugin之间的关系。resolver通过调用resolve/doResolve方法即可串联起来各个plugin进而实现模块查找。

resolver基本用法:可参考https://github.com/webpack/enhanced-resolve#creating-a-resolver

resolver的插件机制:

resolver对象在实例化时内部注册了4个hook对象,hook都是tabable的实例,用到的hook类型如下

resolve AsyncSeriesBailHook  tapAsync/tapPromise/callAsync/promise 执行过程中注册的回调返回非 undefined 时就会直接执行 callAsync 或者 promise 中的函数,并且注册的后续回调都不会执行
resolveStep SyncHook 同步hook。call/tap
noResolve SyncHook 同步hook。call/tap
result AsyncSeriesHook tapAsync/tapPromise/callAsync/promise 顺序的执行注册的异步

回调

r

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Geek技术前线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值