文章首發於個人我的項目SunHuawei/SourceDetectorjavascript
此前我在回答這個問題的時候提到,「我偶然間得到了知乎的源碼」。本文將解釋我是如何「偶然獲取」的。另外本repo便是由此而生的一個chrome extension。html
前端工程化的一個重要部分就是就是源碼轉換,一方面壓縮體積,另外一方面合併文件。固然還有多是爲了轉換Typescript、ES6+或其餘代碼。但一般轉換完的代碼難以閱讀和調試。Source Map就是爲了解決這個問題而出現的。前端
關於Source Map的詳細信息,推薦阮一峯的這篇文章-JavaScript Source Map 詳解。java
話說,某天我在逛知乎的時候習慣性的打開了Chrome Dev-tools,在Sources欄下居然發現了一個webpack://
目錄。用過webpack source map的前端應該馬上就會反應過來-哇,有源碼!因而我便如此「偶然得到」了文件zfeedback.js.map
。node
故事還沒完。webpack
事實上,我此時是能夠直接查看各個源碼文件的。只是如何將其保存到本地呢?我嘗試點擊右鍵,貌似並無保存整個目錄到本地的選項,看起來只能一個一個文件的保存,好累。git
受好奇心驅使,我在github上搜了一圈,找到了一個開源項目-mozilla/source-map。因而本身手動寫了些代碼便將整個目錄下載到了本地。啊哈~github
源碼以下,可用node app.js
執行。web
// app.js const fs = require('fs-extra') const https = require('https') const crypto = require('crypto') const SourceMapConsumer = require('source-map').SourceMapConsumer const analyse = (srcMapURL) => { const BASE_CACHE_PATH = __dirname + '/cache/' const BASE_OUTPUT_PATH = __dirname + '/output/' + srcMapURL.substr(srcMapURL.lastIndexOf('/') + 1) + '/' const BASE_OUTPUT_LIB_PATH = BASE_OUTPUT_PATH + 'node_modules/' const md5 = (content) => { let md5Maker = crypto.createHash('md5'); md5Maker.update(content); return md5Maker.digest('hex'); } const download = (url, callback) => { const hash = md5(url) const cacheFileName = BASE_CACHE_PATH + hash if (fs.existsSync(cacheFileName)) { fs.readFile(cacheFileName, 'utf8', (err, data) => { console.log("From cache") callback(data) }) } else { return https.get(url, function(response) { let body = ''; let totalSize = parseInt(response.headers['content-length']) response.on('data', function(d) { body += d printDownloading(body, totalSize) }); response.on('end', function() { printFinishDownload(body) fs.outputFile(cacheFileName, body, error => { callback(body) }) }); }); } } const printDownloading = (body, totalSize) => { let statusLine = '\r' statusLine += 'Downloading ' statusLine += srcMapURL.substr(srcMapURL.lastIndexOf('/') + 1) statusLine += ' ' statusLine += (body.length / totalSize * 100).toFixed(2) statusLine += '%' process.stdout.write(statusLine) } const printFinishDownload = (body) => { let statusLine = 'Finish Download ' statusLine += srcMapURL.substr(srcMapURL.lastIndexOf('/') + 1) statusLine += ' total size: ' statusLine += body.length statusLine += 'bytes' console.log('\n' + statusLine) } download(srcMapURL, (rawSourceMap) => { try { const consumer = new SourceMapConsumer(rawSourceMap); if (consumer.hasContentsOfAllSources()) { consumer.sources.forEach(fileName => { if (fileName.indexOf('webpack://') !== 0) { return } let fileContent = consumer.sourceContentFor(fileName) fileName = fileName.replace(/^webpack:\/\//, '') fileName = fileName.replace(/^\//, BASE_OUTPUT_PATH) fileName = fileName.replace(/^.*\/\~\//, BASE_OUTPUT_LIB_PATH) fs.outputFile(fileName, fileContent, error => { // console.log(error) // TODO, debug code, to delete before commit }) }) console.log('Please check here for sources: ', BASE_OUTPUT_PATH) } else { console.log('TODO') } } catch (e) { console.log("Failed to parse", srcMapURL) // TODO, debug code, to delete before commit } }) } let jsURLs = ` https://zhstatic.zhihu.com/assets/zfeedback/3.0.13/zfeedback.js ` jsURLs.split('\n').filter(Boolean).forEach(jsURL => { const srcMapURL = jsURL + '.map' analyse(srcMapURL) })
以後的故事是,我將分析源碼的過程寫到了這個回答。以後知乎某員工詢問我如何獲取的源碼,建議我與知乎開發及安全團隊取得聯繫,我解釋了該過程,而後知乎修復了問題。chrome
不過依然不過癮。這樣只能是當我有了某個.map文件時能夠解析出源文件。若是能有一個工具隨時提醒我,我訪問的某個網站有源碼,並幫我下載下來就更完美了。因而便有了這個Chrome extension。
git clone https://github.com/SunHuawei/SourceDetector.git
npm install
bower install
gulp
打開Chrome設置-擴展程序
點擊"加載已解壓的擴展程序..."
選擇path/to/source-detector/dist
目錄
以後你在瀏覽任何網頁時,該插件將自動檢測是否有.map文件。其會自動按網站分組顯示源碼文件,並可點擊下載所有或部分源碼文件。
進入webpack首頁,查看右上角的小圖標吧~
歡迎說出你的想法。歡迎issue和PR。