之前業(yè)余做了一個聚合搜索工具衙荐,自己使用了大半年捞挥,平日里只顧著用它查資料,對于發(fā)現(xiàn)的 bug赫模,卻一直忍啊忍树肃,直到最近才下決心修理了一波。修理和略作改進之后瀑罗,自我體驗上升了一些胸嘴,便也想分享給幾個朋友用。但是這里還留著個讓人很不舒爽的使用障礙斩祭,讓我犯了糾結(jié)劣像。
糾結(jié)是因為這么幾個問題:
- 要知道很多人使用瀏覽器,基本都是裸奔的
- 能訪問 Chrome 商店也是件奢侈的事
- 用戶使用別的瀏覽器怎么辦摧玫。Firefox 的插件商店耳奕,倒是有幾個能實現(xiàn)類似效果的插件,但是推薦哪個插件也是個問題诬像,自己也不可能一一去試用
以前的想法是屋群,把搜索頁面打包成一個 Chrome Web App,然后把插件的功能自己實現(xiàn)到 App 中坏挠,但這畢竟又是番折騰芍躏,始終下不了決心花這份時間。
Nativefier
最近無意中發(fā)現(xiàn)這個開源項目降狠,Nativefier对竣,看著它的項目介紹,以及1w+ 的 Star榜配,感覺自己錯過了一個世紀(jì)否纬。
Nativefier is a command line tool that allows you to easily create a desktop application for any web site with succinct and minimal configuration.
我們來分解下這段話,a desktop application
, 簡直是比好更好蛋褥,要知道 Chrome Web App 可做不到像在桌面應(yīng)用一樣临燃,按下 cmd + tab / ctrl + tab烙心,切換的那么舒暢膜廊。再看 easily create
,有多 easy 呢弃理?
nativefier --name "Warmhole Search" "http://warmhole.gadn.in"
收工溃论。
上面的命令執(zhí)行后,會生成這樣一個目錄痘昌。圖中箭頭所指钥勋,就是預(yù)想中的 a desktop application
了。
簡單是簡單辆苔,但這和前面提到的整合插件功能的事情算灸,有什么關(guān)聯(lián)呢?這就要提到 Nativefier
與另外一個偉大的開源項目驻啤,Electron
之間的關(guān)系了菲驴。下面這句話,同樣來自 Nativefier 的項目介紹骑冗。
Apps are wrapped by Electron in an OS executable
Electron
這個項目的名聲可要大多了赊瞬,現(xiàn)在前端界最流行的 Visual Studio Code先煎,以及 GitHub 開源的 Atom,兩個非常流行的現(xiàn)代編輯器巧涧,都重要地依賴著這個項目薯蝎。
這里不展開更多的介紹,感興趣的朋友自會前去搜索谤绳。今次只說它的一個特點占锯,Electron 暴露的 API,可以完成 Chrome 暴露給其插件相同的功能缩筛。
既然 Nativefier 是一個生成器消略,生成的是一個個被 Electron 包裹的應(yīng)用,那么如果能找到這個應(yīng)用的源代碼瞎抛,再用 Eelctron 的 API 做些擴展艺演,就可以實現(xiàn)預(yù)期目標(biāo)了。
看到了什么婿失,package.json
, 活脫脫一個 nodejs 項目啊钞艇。
迫不及待地打開 main.js
,再配合著 Electron 的文檔及 GitHub Issues豪硅,一番探究后哩照,明確了修改點, 找到 registerListener(session, ...)
函數(shù)懒浮,在函數(shù)結(jié)束前飘弧,給 session
對象的 webRequest 注冊一個事件回調(diào)函數(shù)。通過這個函數(shù)砚著,來實現(xiàn)之前期望 X-Frame-Options
來達(dá)成的效果次伶。
function registerListener(session, opts = {}, cb = () => {}) {
// ... exists code
var onHeadersReceived=(d, c)=>{
if(d.responseHeaders['x-frame-options']) {
delete d.responseHeaders['x-frame-options'];
}
c({cancel: false, responseHeaders: d.responseHeaders});
}
session.webRequest.onHeadersReceived({}, onHeadersReceived);
}
因為是腳本語言,保存修改后稽穆,再打開應(yīng)用就可以驗證效果冠王。這是原生應(yīng)用不容易做到的啊。
之后還做了點改動舌镶,為了讓網(wǎng)頁能檢測出是否運行在 Electron柱彻,還是運行在瀏覽器里,同樣在 main.js
中找好個時機餐胀,向頁面注入了一句腳本哟楷,來給網(wǎng)頁中的 window
對象增加一個屬性,這樣網(wǎng)頁中就可以根據(jù)這個屬性否灾,來區(qū)別出運行環(huán)境的差異了卖擅。
function injectWindowVariable (browserWindow) {
var injectVariable = function () {
browserWindow.webContents.executeJavaScript("window.electronFlag=true;");
}
browserWindow.webContents.on('did-finish-load', function () {
// remove the injection of css the moment the page is loaded
browserWindow.webContents.removeListener('did-get-response-details', injectVariable);
});
// on every page navigation inject the css
browserWindow.webContents.on('did-navigate', function () {
// we have to inject the css in did-get-response-details to prevent the fouc
// will run multiple times
browserWindow.webContents.on('did-get-response-details', injectVariable);
});
}
function createMainWindow(inpOptions, onAppQuit, setDockBadge) {
// ...
// below `maybeInjectCss(mainWindow);`
injectWindowVariable(mainWindow);
// ...
}
之前的幾個糾結(jié)點,都被強大/偉大的開源項目和社區(qū)消解完了。我也不用再擔(dān)心惩阶,分享給朋友后挎狸,面對種種疑惑時的尷尬。
對于 Nativefier 和 Electron琳猫,一個是相見恨晚伟叛,另一個是慕名已久私痹,只嘆無緣脐嫂。今日初識,就結(jié)出了不錯的成果紊遵,而它們都還有非常多好玩的 API账千,提供著更多的可能性。