web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)

这篇具有很好参考价值的文章主要介绍了web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)

一、webpack介绍:

​ Webpack 是一个模块打包工具,主要用于 JavaScript 应用程序。它可以将许多模块打包成一个或多个 bundle,从而优化加载速度和减少加载时间。Webpack 可以处理各种资源,包括 JavaScript、CSS、图片、字体等,并且可以将其转换为浏览器可以理解的格式。

Webpack 的主要特点包括:

  1. 模块化:Webpack 允许你将应用程序划分为许多小的、独立的模块,这些模块可以被重复使用,并且可以轻松地进行更改和更新。
  2. 高效性:Webpack 使用高级优化算法来最小化生成的 bundle 的大小,从而加快加载速度。它还支持代码拆分、懒加载等功能,以便进一步优化性能。
  3. 灵活性:Webpack 支持各种插件和加载器,可以用于处理不同类型的资源,并且可以扩展其功能以适应不同的项目需求。
  4. 可配置性:Webpack 提供了丰富的配置选项,可以根据项目需求进行灵活的配置,以满足不同的构建要求。

总的来说,Webpack 是一个强大的工具,可以帮助开发人员更高效地构建和维护 JavaScript 应用程序。它已经成为前端开发中不可或缺的一部分,被广泛使用于各种项目中。

二、webpack打包简介

qq音乐sign参数逆向,前端,笔记,javascript

1、webpack数组形式
!function(e) {
    var t = {};

    // 加载器  所有的模块都是从这个函数加载 执行
    function n(r) {
        if (t[r])
            return t[r].exports;
        var o = t[r] = {
            i: r,
            l: !1,
            exports: {}
        };
        return e[r].call(o.exports, o, o.exports, n),
            o.l = !0,
            o.exports
    }

    n(0)
}
    ([
        function () {
            console.log('123456')
        },

              function () {
            console.log('模块2')
        },
    ])
2、webpack对象形式
!function(e) {
    var t = {};
    //  所有的模块 都是从这个加载器 执行的  分发器
    function n(r) {
        if (t[r])
            return t[r].exports;
        var o = t[r] = {
            i: r,
            l: !1,
            exports: {}
        };
        return e[r].call(o.exports, o, o.exports, n),
        o.l = !0,
        o.exports
    }
   n('xialuo')  // 对象 根据KEY 找模块
}({

        0: function () {
            console.log('我是模块1  负责加密')
        },

        'xialuo': function () {
            console.log('我是模块2  负责解密')
        },

        2: function () {
            console.log('我是模块3  负责爬数据')
        }
    }
);
三、多个JS文件打包

​ 如果模块比较多,就会将模块打包成JS文件, 然后定义一个全局变量 window[“webpackJsonp”] = [ ],它的作用是存储需要动态导入的模块,然后重写 window[“webpackJsonp”] 数组的 push( ) 方法为 webpackJsonpCallback( ),也就是说 window[“webpackJsonp”].push( ) 其实执行的是 webpackJsonpCallback( ),window[“webpackJsonp”].push( )接收三个参数,第一个参数是模块的ID,第二个参数是 一个数组或者对象,里面定义大量的函数,第三个参数是要调用的函数(可选)

qq音乐sign参数逆向,前端,笔记,javascript

四、QQ音乐sign值获取
1、接口分析

qq音乐sign参数逆向,前端,笔记,javascript

qq音乐sign参数逆向,前端,笔记,javascript

// sign值生成
// n方法为加载器
o = n(147).default;
i = o(e.data);
sign = i;

qq音乐sign参数逆向,前端,笔记,javascript

qq音乐sign参数逆向,前端,笔记,javascript

2、扣取加载器方法
window = global;
// 加载器
!function(e) {
    function t(t) {
        for (var r, n, f = t[0], c = t[1], i = t[2], l = 0, u = []; l < f.length; l++)
            n = f[l],
            Object.prototype.hasOwnProperty.call(o, n) && o[n] && u.push(o[n][0]),
            o[n] = 0;
        for (r in c)
            Object.prototype.hasOwnProperty.call(c, r) && (e[r] = c[r]);
        for (b && b(t); u.length; )
            u.shift()();
        return d.push.apply(d, i || []),
        a()
    }
    function a() {
        for (var e, t = 0; t < d.length; t++) {
            for (var a = d[t], r = !0, n = 1; n < a.length; n++) {
                var c = a[n];
                0 !== o[c] && (r = !1)
            }
            r && (d.splice(t--, 1),
            e = f(f.s = a[0]))
        }
        return e
    }
    var r = {}
      , n = {
        21: 0
    }
      , o = {
        21: 0
    }
      , d = [];
    function f(t) {
        if (r[t])
            return r[t].exports;
        var a = r[t] = {
            i: t,
            l: !1,
            exports: {}
        };
        return e[t].call(a.exports, a, a.exports, f),
        a.l = !0,
        a.exports
    }
    // 定义全局变量介绍加载器方法
    window.xiaopacai = f;
    f.e = function(e) {
        var t = [];
        n[e] ? t.push(n[e]) : 0 !== n[e] && {
            1: 1,
            3: 1,
            4: 1,
            5: 1,
            6: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            13: 1,
            14: 1,
            15: 1,
            16: 1,
            17: 1,
            18: 1,
            19: 1,
            20: 1,
            22: 1,
            23: 1,
            24: 1,
            25: 1,
            26: 1
        }[e] && t.push(n[e] = new Promise((function(t, a) {
            for (var r = "css/" + ({
                1: "common",
                3: "album",
                4: "albumDetail",
                5: "album_mall",
                6: "category",
                7: "cmtpage",
                8: "download_detail",
                9: "index",
                10: "msg_center",
                11: "mv",
                12: "mvList",
                13: "mv_toplist",
                14: "notfound",
                15: "player",
                16: "player_radio",
                17: "playlist",
                18: "playlist_edit",
                19: "profile",
                20: "radio",
                22: "search",
                23: "singer",
                24: "singer_list",
                25: "songDetail",
                26: "toplist"
            }[e] || e) + "." + {
                1: "2e3d715e72682303d35b",
                3: "5cf0d69eaf29bcab23d2",
                4: "798353db5b0eb05d5358",
                5: "df4c243f917604263e58",
                6: "20d532d798099a44bc88",
                7: "e3bedf2b5810f8db0684",
                8: "e3bedf2b5810f8db0684",
                9: "ea0adb959fef9011fc25",
                10: "020422608fe8bfb1719a",
                11: "8bdb1df6c5436b790baa",
                12: "47ce9300786df1b70584",
                13: "4aee33230ba2d6b81dce",
                14: "e6f63b0cf57dd029fbd6",
                15: "1d2dbefbea113438324a",
                16: "d893492de07ce97d8048",
                17: "9484fde660fe93d9f9f0",
                18: "67fb85e7f96455763c83",
                19: "5e8c651e74b13244f7cf",
                20: "3befd83c10b19893ec66",
                22: "b2d11f89ea6a512a2302",
                23: "c7a38353c5f4ebb47491",
                24: "df0961952a2d3f022894",
                25: "4c080567e394fd45608b",
                26: "8edb142553f97482e00f"
            }[e] + ".chunk.css?max_age=2592000", o = f.p + r, d = document.getElementsByTagName("link"), c = 0; c < d.length; c++) {
                var i = (b = d[c]).getAttribute("data-href") || b.getAttribute("href");
                if ("stylesheet" === b.rel && (i === r || i === o))
                    return t()
            }
            var l = document.getElementsByTagName("style");
            for (c = 0; c < l.length; c++) {
                var b;
                if ((i = (b = l[c]).getAttribute("data-href")) === r || i === o)
                    return t()
            }
            var u = document.createElement("link");
            u.rel = "stylesheet",
            u.type = "text/css",
            u.onload = t,
            u.onerror = function(t) {
                var r = t && t.target && t.target.src || o
                  , d = new Error("Loading CSS chunk " + e + " failed.\n(" + r + ")");
                d.code = "CSS_CHUNK_LOAD_FAILED",
                d.request = r,
                delete n[e],
                u.parentNode.removeChild(u),
                a(d)
            }
            ,
            u.href = o,
            0 !== u.href.indexOf(window.location.origin + "/") && (u.crossOrigin = "anonymous"),
            document.getElementsByTagName("head")[0].appendChild(u)
        }
        )).then((function() {
            n[e] = 0
        }
        )));
        var a = o[e];
        if (0 !== a)
            if (a)
                t.push(a[2]);
            else {
                var r = new Promise((function(t, r) {
                    a = o[e] = [t, r]
                }
                ));
                t.push(a[2] = r);
                var d, c = document.createElement("script");
                c.charset = "utf-8",
                c.timeout = 120,
                f.nc && c.setAttribute("nonce", f.nc),
                c.src = function(e) {
                    return f.p + "js/" + ({
                        1: "common",
                        3: "album",
                        4: "albumDetail",
                        5: "album_mall",
                        6: "category",
                        7: "cmtpage",
                        8: "download_detail",
                        9: "index",
                        10: "msg_center",
                        11: "mv",
                        12: "mvList",
                        13: "mv_toplist",
                        14: "notfound",
                        15: "player",
                        16: "player_radio",
                        17: "playlist",
                        18: "playlist_edit",
                        19: "profile",
                        20: "radio",
                        22: "search",
                        23: "singer",
                        24: "singer_list",
                        25: "songDetail",
                        26: "toplist"
                    }[e] || e) + ".chunk." + {
                        1: "0b15a31f7bc269ea76ff",
                        3: "b3395a2d475262b98fa7",
                        4: "dea94b21a47cdb6d0f65",
                        5: "f5b6937e84f33133b31d",
                        6: "6c4ac3718d0230ac3b1c",
                        7: "ae411fac801093307ebc",
                        8: "f1c40f6b3a431ca4c9ac",
                        9: "52f2369df6a4a3649011",
                        10: "90aef56793aff533bf57",
                        11: "4c23320d028878580c26",
                        12: "b43316a48154164d557b",
                        13: "8adf08693025ab48224f",
                        14: "89eb6da604ebcf2dda2d",
                        15: "c9d5d7c9966dea2b213c",
                        16: "07b3290e08abf8a4e901",
                        17: "6838a647ca4abb619832",
                        18: "9d2cbd13db3328dcd357",
                        19: "ce6940fdeda857506a27",
                        20: "8af74f665077243ecefa",
                        22: "5a013d73a1da88cc221e",
                        23: "469f622f5dffdeee26eb",
                        24: "9df420e7d63b8d867fd2",
                        25: "9bea17905ada32dde9b5",
                        26: "bcb481bd9dd2001370ac"
                    }[e] + ".js?max_age=2592000"
                }(e),
                0 !== c.src.indexOf(window.location.origin + "/") && (c.crossOrigin = "anonymous");
                var i = new Error;
                d = function(t) {
                    c.onerror = c.onload = null,
                    clearTimeout(l);
                    var a = o[e];
                    if (0 !== a) {
                        if (a) {
                            var r = t && ("load" === t.type ? "missing" : t.type)
                              , n = t && t.target && t.target.src;
                            i.message = "Loading chunk " + e + " failed.\n(" + r + ": " + n + ")",
                            i.name = "ChunkLoadError",
                            i.type = r,
                            i.request = n,
                            a[1](i)
                        }
                        o[e] = void 0
                    }
                }
                ;
                var l = setTimeout((function() {
                    d({
                        type: "timeout",
                        target: c
                    })
                }
                ), 12e4);
                c.onerror = c.onload = d,
                document.head.appendChild(c)
            }
        return Promise.all(t)
    }
    ,
    f.m = e,
    f.c = r,
    f.d = function(e, t, a) {
        f.o(e, t) || Object.defineProperty(e, t, {
            enumerable: !0,
            get: a
        })
    }
    ,
    f.r = function(e) {
        "undefined" !== typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
            value: "Module"
        }),
        Object.defineProperty(e, "__esModule", {
            value: !0
        })
    }
    ,
    f.t = function(e, t) {
        if (1 & t && (e = f(e)),
        8 & t)
            return e;
        if (4 & t && "object" === typeof e && e && e.__esModule)
            return e;
        var a = Object.create(null);
        if (f.r(a),
        Object.defineProperty(a, "default", {
            enumerable: !0,
            value: e
        }),
        2 & t && "string" != typeof e)
            for (var r in e)
                f.d(a, r, function(t) {
                    return e[t]
                }
                .bind(null, r));
        return a
    }
    ,
    f.n = function(e) {
        var t = e && e.__esModule ? function() {
            return e.default
        }
        : function() {
            return e
        }
        ;
        return f.d(t, "a", t),
        t
    }
    ,
    f.o = function(e, t) {
        return Object.prototype.hasOwnProperty.call(e, t)
    }
    ,
    f.p = "/ryqq/",
    f.oe = function(e) {
        throw e
    }
    ;
    var c = window.webpackJsonp = window.webpackJsonp || []
      , i = c.push.bind(c);
    c.push = t,
    c = c.slice();
    for (var l = 0; l < c.length; l++)
        t(c[l]);
    var b = i;
    a()
}([]);
3、模块扣取(可以单个模块扣取,然后运行,缺什么补什么就可以了;也可以扣取整个js文件,然后通过require(‘./webpack.js’)形式引用即可)。这里为了方便采用了引用的方式。运行结果与网页对比,发现不一致情况。

qq音乐sign参数逆向,前端,笔记,javascript

这里出现这种情况,应该是有浏览器环境检测,我们没有补充。可以放到补环境框架中运行,然后补充对应所需环境;也可以手动补几个常见的浏览器环境(如:document、navigator、location等)并给手动补充的环境挂上代理。
// 挂代理代码(主要监听get、set方法)
ld = {}; 
ld.config = {}; 
ld.config.proxy = true; // 增加属性,用于执行是否开启代理操作
// 获取对象类型操作
ld.typeObject = function typeObject(obj){
    return Object.prototype.toString.call(obj);
}
// 代理函数
ld.proxy = function proxy(obj, objName){
    if(!ld.config.proxy){
        return obj;
    }
    let handler = {
        get:function(target, prop, receiver){
            let result;
            try{ // 防止报错
                result = Reflect.get(target, prop, receiver); // 使用映射的方法,来调用get方法
                // 获取对象类型
                let type = ld.typeObject(result);
                if(result instanceof Object){
                    console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回类型:[${type}]}`);
                    result = ld.proxy(result, `${objName}.${prop.toString()}`);
                }else if(typeof result === "symbol"){
                    console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${result.toString()}]}`);
                }else{
                    console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${result}]}`);
                }
            }catch(e){
                console.log(`{get操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 错误信息:[${e.message}]}`);
            }
            
            return result
        },
        set:function(target, prop, value, receiver){
            let result
            try{ // 防止报错
                result = Reflect.set(target, prop, value, receiver); // 使用映射的方法,来调用set方法
                // 获取对象类型
                let type = ld.typeObject(value);
                if(value instanceof Object){
                    console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回类型:[${type}]}`);
                }else if(typeof value === "symbol"){
                    console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${value.toString()}]}`);
                }else{
                    console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 返回结果:[${value}]}`);
                }
            }catch(e){
                console.log(`{set操作| 对象名:[${objName}] -->属性名:[${prop.toString()}], 错误信息:[${e.message}]}`);
            }
            
            return result
        }};

    return new Proxy(obj, handler);
}

qq音乐sign参数逆向,前端,笔记,javascript文章来源地址https://www.toymoban.com/news/detail-858034.html

补齐缺少的属性值,结果就和浏览器一样了。
3、构造请求,获取所需数据
import requests
import time
import execjs


headers = {
    'authority': 'u6.y.qq.com',
    'accept': 'application/json',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'no-cache',
    'content-type': 'application/x-www-form-urlencoded',
    'pragma': 'no-cache',
    'referer': 'https://y.qq.com/',
    'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-site',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
}
data = '{"comm":{"cv":4747474,"ct":24,"format":"json","inCharset":"utf-8","outCharset":"utf-8","notice":0,"platform":"yqq.json","needNewCode":1,"uin":0,"g_tk_new_20200303":5381,"g_tk":5381},"req_1":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"5630580667","songmid":["001Xs1NW3wgWpq","0027Z2qE0pDuKY"],"songtype":[0,0],"uin":"0","loginflag":1,"platform":"20"}},"req_2":{"module":"music.musicasset.SongFavRead","method":"IsSongFanByMid","param":{"v_songMid":["0016aXcd24qSC8","001Xs1NW3wgWpq","0027Z2qE0pDuKY","003V4xd80ty2df"]}},"req_3":{"module":"music.musichallSong.PlayLyricInfo","method":"GetPlayLyricInfo","param":{"songMID":"0016aXcd24qSC8","songID":457240977}},"req_4":{"method":"GetCommentCount","module":"music.globalComment.GlobalCommentRead","param":{"request_list":[{"biz_type":1,"biz_id":"457240977","biz_sub_type":0}]}},"req_5":{"module":"music.musichallAlbum.AlbumInfoServer","method":"GetAlbumDetail","param":{"albumMid":"001ln9YB420a7b"}},"req_6":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"9307341590","songmid":["0016aXcd24qSC8"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20","filename":["RS020640pBtN0etKNM.mp3"]}}}'

with open('./get_sign.js', 'r', encoding='utf-8') as f:
    code_js = f.read()
sign = execjs.compile(code_js).call('get_sign', data)
params = {
    '_': round(time.time() * 1000),
    'sign': sign,
}



response = requests.post('https://u6.y.qq.com/cgi-bin/musics.fcg', params=params, headers=headers, data=data)
print(response.json()["req_1"]['data']["midurlinfo"])
总结:
1、webpack打包的js文件,无论是单文件还是多文件,在逆向时首先需要找到对应的加载器。
2、加载器获取完成后,可以单个模块扣取代码并进调试,也可以扣取整个js文件,进行加载使用。
3、扣取完整代码后,出现结果与网页不一致时,大多数情况下是缺少浏览器环境;可以尝试补充一些常用的环境,并挂上代理方法查看缺少内容。
4、可以将扣取的完整代码,现在浏览器中运行,查看结果是否正确;在将代码在本地运行进行对比,可以快速确认是否是缺少环境导致结果不一样的。

到了这里,关于web逆向笔记:js逆向案例四 QQ音乐 sign值(webpack打包代码如何扣取)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 小程序新手入门逆向案例来伊某x-co-sign

    声明:本文仅限学习交流使用,禁止用于非法用途、商业活动等。否则后果自负。如有侵权,请告知删除,谢谢!本教程也没有专门针对某个网站而编写,单纯的技术研究 目标案例:5b6u5L+h5pCc57SiLeWwj+eoi+W6j+adpeS8iuS7veS6keW6ly0t6Zeo5bqX5L+h5oGv 对应接口和难点 我这边使用的是 charle

    2024年02月12日
    浏览(18)
  • 【Web】从零开始的js逆向学习笔记(上)

    目录 一、逆向基础 1.1 语法基础 1.2 作用域 1.3 窗口对象属性 1.4 事件 二、浏览器控制台 2.1 Network Network-Headers Network-Header-General Network-Header-Response Headers Network-Header-Request Headers 2.2 Sources 2.3 Application 2.4 Console 三、加密参数的定位方法 3.1 巧用搜索 3.2 堆栈调试 3.3 控制台调试 3.

    2024年02月21日
    浏览(13)
  • 逆向案例十八——webpack逆向红人点集登录密码

    网址链接:红人点集 密码登录,获取数据包: 发现pwd和sig两个加密参数,开始跟栈调试   点击第一个,在send处打上断点,再点击登录。   进入异步栈,r.requests 释放之前的断点,打上断点 ,点击登录 往前跟栈,看什么时候密码是明文,结果,打上断点,同样操作,分析代

    2024年04月18日
    浏览(21)
  • JS逆向 webpack解密

    声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢! 前言:我技术可能不是很牛逼,但我很会偷懒,怎么简单怎么来,所以有更好的解密方法可以在评论区评论~ 目标网站:这个网站很坑,那个验证字段搜不到,XHR断点也断不到,就

    2024年02月06日
    浏览(10)
  • js逆向——webpack扣法

    01 webpack讲解 webpack 是个静态模块打包工具,目的是为了让前端工程师写的前端代码变成浏览器可以识别的代码,并且可以达到前端项目的模块化,也就是如何更高效地管理和维护项目中的每一个资源。 但无疑是对 js逆向 造成了妨碍。但如果掌握了扣取 webpack 的一些技巧也是

    2024年02月03日
    浏览(14)
  • JS逆向之Webpack自吐

    声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢 在这篇文章里面,我们重新利用两个方法来实现扣出代码优化代码。webpack自吐所有方法和webpack精减代码法。把这两个方法结合起来使用。 一、 Webpack 是什么? ? webpack是一个基于模

    2024年02月01日
    浏览(21)
  • webpack实战:某网站JS逆向分析

      好的逆向能够帮助我们了解加密实现,然后根据加密方式( md5,base64,res,des,rsa… )还原加密算法的过程。可以看看我之前的这篇文章:快速定位查找加密方式特征与技巧 目标站点 : aHR0cHM6Ly9hY2NvdW50LnBwZGFpLmNvbS9wYy9sb2dpbg== 此网站的用户名 userName 和密码 password 都是加密的,密

    2024年02月09日
    浏览(15)
  • 网页爬虫之WebPack模块化解密(JS逆向)

    WebPack打包: webpack是一个基于模块化的打包(构建)工具, 它把一切都视作模块。 概念: webpack是 JavaScript 应用程序的模块打包器,可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器)和plugins(插件)对资源进行处理,打包成符合生产环境部署

    2024年02月02日
    浏览(11)
  • Webpack打包简单的js文件

    初始化一个新的npm 步骤一: 初始化npm项目,创建一个package.json文件 步骤二: 添加打包脚本:在 scripts 部分添加一个命令来运行webpack 步骤三: 安装Webpack 步骤四: 创建一个简单的Javascript文件,比如 src/index.js 步骤五: 配置Webpack,创建一个名为 webpack.config.js 的文件 步骤六

    2024年01月24日
    浏览(12)
  • 第三节:Node.js 之 Webpack 打包

    官网网址:https://webpack.docschina.org/ 减少文件数量,缩减代码体积,提高浏览器打开速度。 用于分析、并打包代码。支持所有类型文件的打包,其本质是一个第三方模块包。 初始化包环境 安装依赖包 配置package.json 的 scripts(自定义命令) 在根目录下新建 src 文件夹, 所有要

    2024年02月15日
    浏览(16)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包