介入webpack 的打包流程,将某个包给mock 掉

介入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 的时候,效率更高

posted @   kongshu  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2024-03-01 介绍几个scss 与css 中的新的特性
点击右上角即可分享
微信分享提示