介入webpack 的打包流程,将某个包给mock 掉
在某些情况下,我们对于包的体积比较敏感,某些第三方的包引用了其他第三方的包,而且第三方的包不支持摇树,我们希望在打包的时候将第三方包所依赖的第三方包给去除掉,因为那部分功能我们并不使用。思路是采用mock 的方式,将第三方的第三方包给去除。
被测试代码的例子
// index.js
// 这个里面直接import 的modA 不mock, modB 里面的 modA要mock
import {greeting} from './modA/modA';
import {greetingWrapper} from './modA/modB';
greetingWrapper();
greeting();// modA.js
import {debounce} from 'lodash';
export const greeting=debounce(()=>`hello world`,10);// modB.js 这个里面的modA 要mock
import { greeting } from "./modA";
export const greetingWrapper = ()=>{greeting();
}// mock_modA.js
export const greeting=()=>`hello world from mock moduleA`;
webpack plugin
我们可以借助webpack 的plugin, 在normalModuleFactory这个hook里面将某个issuer里面所使用的requet给替换掉,这个是webpack 的插件,可以直接使用
class ReplacePlugin{apply(compiler){compiler.hooks.normalModuleFactory.tap('ReplacePlugin', (normalModuleFactory) => {normalModuleFactory.hooks.beforeResolve.tapAsync('ReplacePlugin', (result, callback) => {// 条件判断,issuer 就是使用方,request 就是被导入的模块if(result && /modA(\.js)?$/i.test(result.request) && result.context.issuer && /[\\/]modB(\.js)?$/i.test(result.context.issuer)){// 把request 的路径给替换掉result.request = result.request.replace(/modA(\.js)?$/i, 'mock_modA$1');}callback();});});}
}
webpack resolve 的plugin
借助webpack 的resolve, 在它解析的时候将被使用的模块给替换掉
class ResolvePlugin{apply(resolver){resolver.hooks.resolve.tapAsync('ResolvePlugin', (request, resolveContext, callback) => {const requestPath = request.request;if(/\/modA(\.js)?$/i.test(requestPath) && request.context.issuer && /[\\/]modB(\.js)?$/i.test(request.context.issuer)){console.log(request.context.issuer);const newRequest ={...request,request: requestPath.replace(/modA(\.js)?$/i, 'mock_modA$1'),};return resolver.doResolve(resolver.hooks.resolve, newRequest, `Redirecting ${requestPath} -> ${newRequest.request}`, resolveContext, callback);}callback();});}
}// webpack 的配置
const ResolvePluginInstance = new ResolvePlugin();
resolve:{extensions:['.js'],plugins:[// 记得构建实例ResolvePluginInstance]},
总结
这两种方式经过测试都可以实现我们预设的目标,但是推荐使用resolve 的这种方式,因为它只是发生在文件resolve 的时候,效率更高