【学习心得】webpack技术在爬虫逆向中的应用

一、webpack技术是什么?

(1)定义

Webpack 是一个前端资源模块化管理和打包工具,Webpack技术的出现主要是为了解决现代前端开发中JS代码的模块化组织问题(当然还有别的原因,这里只重点讲和逆向有关的)。

随着JavaScript生态的发展,特别是CommonJS和ES6模块等规范的引入,项目中代码需要以模块化的方式组织。然而,浏览器原生并不直接支持这些模块加载机制,WebPack通过解析、编译和打包模块,使得开发者可以利用模块化的优点编写可维护性更强的代码。

(2)webpack的格式

简单的webpack格式:

javascript 复制代码
// 简单
!function (e) {
    加载器
}(接收的参数)

详细的webpack格式:

javascript 复制代码
// 详细
!function (e) {
    // 存放加载器
    var c = {}
    // 加载器
    function n(t) {
        // 创建a对象
        var a = {
            i: t,  // 表示模块的标识符
            l: !1, // 布尔值,初试为false,用来表示当前模块是否被加载
            exports: {}  // 空对象,用于讲模块导出,存储
        };
        c[t] = {
            i: t,  // 表示模块的标识符
            l: !1, // 布尔值,初试为false,用来表示当前模块是否被加载
            exports: {}  // 空对象,用于讲模块导出,存储
        };
        // 执行函数里面的代码
        return e[t].call(a.exports, a, a.exports, n),
            a.l = !0,
            a.exports
    }
    n.m = e  // n.m 用来存所有的模块
    n(2)     // 执行当前选中的模块,下标2就是第三个模块
}([
    function () {...},
    function () {...},
    function () {...},
    function () {...},
])

(3)模块化

比如下面代码中有三个模块,他们其实就是三个函数,假设这三个模块都有着不同的功能,这里演示代码中显示的是打印不同字符。

javascript 复制代码
function ModuleA() {console.log("a")}
function ModuleB() {console.log("b")}
function ModuleC() {console.log("c")}

但如果你的写的功能模块有几百上千个,那么这样的书写方式必须放在同一个JS文件中就会非常臃肿,于是出现了这样的代码结构:

javascript 复制代码
!function(i) {
    function n(t) {
        return i[t].call(a, b, c, d)
    }
}([
    function(t, e, n) {}, 
    function(t, e, r) {}, 
    function(t, e, o) {}, 
    function(t, e) {},
]);

由于在扣JS加密代码时会经常遇到,所以理解这种语法对于逆向来说是非常重要的。

这种代码组织相当于进行了模块化编程,因此被称为 webpack。上面的代码看起来很费劲,其中的一个重要原因就是函数的参数和函数名都是简单的字母没有含义,都不知道这是干什么。于是我们可以写成下面这种方式便于理解:

javascript 复制代码
!function (allModule) {

    // 定义执行模块的函数
    function useModule(whichModule) {
        // 用call方法来执行函数
        allModule[whichModule].call(null, "hello world!");
    }
    useModule(0)  // 这里指定加载哪一个模块
}([
    function ModuleA(param) {console.log("A" + param)},  // 用数组装所有的模块,这是第一个
    function ModuleB(param) {console.log("B" + param)},
    function ModuleC(param) {console.log("C" + param)},
]);

二、技术拆解

(1)JS的自执行函数

IIFE 全称 Immediately-invoked Function Expressions,译为立即调用函数表达式,也称为自执行函数、立即执行函数、自执行匿名函数等,IIFE 是一种语法,这种模式本质上就是函数表达式(命名的或者匿名的)在创建后立即执行。当函数变成立即执行的函数表达式时,表达式中的变量不能从外部访问。IIFE 主要用来隔离作用域,避免污染。它长这个样子(我只介绍最常见的形式):

javascript 复制代码
// 第一种形式:用感叹号表示
!function () {
    console.log("I AM IIFE")
};

!function () {
    console.log(A)
}(A);  // 后面紧跟的小括号里面可以传入参数

// 第二种形式:用括号表示
(function () {
    console.log("I AM IIFE")
}());

(() => {
  console.log("I AM IIFE")
})();

(2)call方法apply方法

JavaScript 中的 call() 和 apply() 方法都是函数对象(Function.prototype)上的方法,它们的主要功能是改变函数调用时的上下文环境(即函数内部 this 的指向),同时允许你传递参数给该函数。

下面是call方法的使用例子:

javascript 复制代码
function sayHello(name) {
  console.log('Hello, ' + this.name + ', ' + name);
}

let user = { name: 'John' };
sayHello.call(user, 'Doe'); // 输出 "Hello, John, Doe"

下面是apply方法的使用例子:

javascript 复制代码
function sum(a, b) {
  return a + b;
}

let numbers = [3, 5];
let result = sum.apply(null, numbers); // 输出 8,等同于 sum(3, 5)

总结起来就是,call和apply第一个参数都是函数运行时的上下文对象thisArg。后面的参数不同,对于call来说,参数是一个个传入;对于apply来说,参数是通过一个数组传入。

  • 当需要以逗号分隔的形式传递参数时,可以使用 call() 方法。
  • 当需要以数组形式传递可变数量的参数时,应该使用 apply() 方法。
相关推荐
ywf12151 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
恋猫de小郭1 小时前
2026,Android Compose 终于支持 Hot Reload 了,但是收费
android·前端·flutter
hpoenixf7 小时前
2026 年前端面试问什么
前端·面试
还是大剑师兰特7 小时前
Vue3 中的 defineExpose 完全指南
前端·javascript·vue.js
泯泷8 小时前
阶段一:从 0 看懂 JSVMP 架构,先在脑子里搭出一台最小 JSVM
前端·javascript·架构
mengchanmian8 小时前
前端node常用配置
前端
华洛9 小时前
利好打工人,openclaw不是企业提效工具,而是个人助理
前端·javascript·产品经理
xkxnq9 小时前
第六阶段:Vue生态高级整合与优化(第93天)Element Plus进阶:自定义主题(变量覆盖)+ 全局配置与组件按需加载优化
前端·javascript·vue.js
A黄俊辉A10 小时前
vue css中 :global的使用
前端·javascript·vue.js
小码哥_常10 小时前
被EdgeToEdge适配折磨疯了,谁懂!
前端