如何通过用户脚本修改Webpack模块内代码以完整显示Twitter/X长推文
如何通过用户脚本修改Webpack模块内代码以完整显示Twitter/X长推文
嘿,这个问题我之前也碰到过,Webpack打包后的模块确实有点棘手,但有两种可行的方案能帮你实现完整显示长推文的需求,我给你详细拆解下:
方案一:拦截API请求替换推文内容(更稳定)
这种方法不用碰Webpack的模块代码,而是直接在Twitter获取推文数据的阶段,把full_text替换成note_tweet.text,让原页面代码自动用完整文本渲染。好处是Webpack模块ID变了也不影响,容错性更强。
你可以直接用这个用户脚本:
// ==UserScript== // @name Twitter/X 完整显示长推文 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 自动显示完整长推文,无需点击"查看更多" // @author 自定义名称 // @match https://twitter.com/* // @match https://x.com/* // @grant none // ==/UserScript== (function() { 'use strict'; // 拦截原生fetch请求 const originalFetch = window.fetch; window.fetch = async function(...args) { const response = await originalFetch.apply(this, args); // 只处理推文相关的API请求 const requestUrl = args[0]; if (typeof requestUrl === 'string' && (requestUrl.includes('TweetDetail') || requestUrl.includes('timeline'))) { // 克隆响应避免原响应被消耗 const clonedResp = response.clone(); try { const data = await clonedResp.json(); // 递归处理所有推文(包括转发、引用的推文) const processTweet = (tweet) => { if (tweet.note_tweet?.text) { // 把full_text和text替换成完整的note_tweet内容 tweet.full_text = tweet.note_tweet.text; tweet.text = tweet.note_tweet.text; } // 处理嵌套的转发/引用推文 if (tweet.retweeted_status) processTweet(tweet.retweeted_status); if (tweet.quoted_status) processTweet(tweet.quoted_status); return tweet; }; // 处理推文详情页的API结构 if (data.data?.threaded_conversation_with_injections_v2) { data.data.threaded_conversation_with_injections_v2.instructions.forEach(inst => { if (inst.addEntries) { inst.addEntries.entries.forEach(entry => { const tweetResult = entry.content?.itemContent?.tweet_results?.result; if (tweetResult) processTweet(tweetResult); }); } }); } // 处理首页/时间线的API结构 else if (data.data?.home_timeline_urt) { data.data.home_timeline_urt.instructions.forEach(inst => { if (inst.addEntries) { inst.addEntries.entries.forEach(entry => { const tweetResult = entry.content?.itemContent?.tweet_results?.result; if (tweetResult) processTweet(tweetResult); }); } }); } // 返回修改后的新响应 return new Response(JSON.stringify(data), { status: response.status, statusText: response.statusText, headers: response.headers }); } catch (err) { // 解析失败时返回原响应,避免影响页面 return response; } } return response; }; })();
方案二:直接Patch Webpack模块(更直接)
如果你还是想修改那个Webpack模块里的代码,可以通过定位Webpack的模块缓存来替换目标函数。不过要注意:Twitter更新后模块ID(比如你说的147093)可能会变,到时需要重新用DevTools查找。
这个脚本需要在页面加载初期运行:
// ==UserScript== // @name Twitter/X 补丁Webpack模块显示长推文 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 修改Webpack模块内的代码,直接使用note_tweet.text // @author 自定义名称 // @match https://twitter.com/* // @match https://x.com/* // @grant none // @run-at document-start // ==/UserScript== (function() { 'use strict'; // 等待Webpack模块加载完成 function waitForWebpack() { // Twitter的Webpack模块通常存在window.__webpack_modules__中 if (window.__webpack_modules__) { const targetModuleId = '147093'; // 你找到的模块ID const originalModule = window.__webpack_modules__[targetModuleId]; if (originalModule) { // 重写目标模块 window.__webpack_modules__[targetModuleId] = function(e, n, d) { // 先执行原模块的所有逻辑 originalModule(e, n, d); // 获取原导出的h函数(模块导出的Z就是h) const originalH = n.Z; // 替换h函数,加入我们的逻辑 n.Z = function(...args) { const tweetData = args[0]; // 先调用原函数拿到处理后的对象 const processedTweet = originalH.apply(this, args); // 如果存在note_tweet.text,替换text和full_text if (tweetData.note_tweet?.text) { processedTweet.text = tweetData.note_tweet.text; processedTweet.full_text = tweetData.note_tweet.text; } return processedTweet; }; console.log('Webpack模块已成功补丁!'); }; } else { // 模块还没加载,100ms后重试 setTimeout(waitForWebpack, 100); } } else { setTimeout(waitForWebpack, 100); } } waitForWebpack(); })();
两种方案的优缺点对比
- API拦截方案:稳定性高,不受Webpack模块更新影响;缺点是需要适配Twitter的API结构,如果API返回格式变了,需要调整脚本里的遍历逻辑。
- Webpack补丁方案:逻辑更直接,完全对应你找到的代码问题;缺点是模块ID可能随Twitter更新变化,到时需要重新在DevTools里定位模块。
如果之后Twitter改了API结构或者模块ID,你可以打开浏览器DevTools的Sources面板,重新查找对应的请求或模块位置调整脚本就行。
备注:内容来源于stack exchange,提问作者Ahmad Hk
相关产品推荐
相关产品推荐

