使用React.js開發Chrome外掛

發表於2018-07-09

一、背景

相信看到這篇文章的人應該都用過Chrome外掛吧,最近剛好有個這方面的需求,我就把Chrome外掛的相關知識學習了一下,發現其實Chrome外掛的開發和大前端Web開發的底子是一樣的,無非就是runtime只限於Chrome瀏覽器,並且可以呼叫Chrome提供的一些chrome.* API來實現一些基於Chrome瀏覽器的小功能。這裡非要類比的話,我理解chrome.* API就像我們開發Hybird應用一樣,需要有一個bridge層來提供底層原生的能力給js。我是做Android開發出生的,這只是我的個人理解,可能對大Web技術的理解還是不夠。

其實Chrome上的外掛,從UI上主要分成兩類:一類是瀏覽器按鈕(BrowserAction),另一類是頁面按鈕(PageAction)。兩者的開發大同小異,我這裡今天主要介紹的主角不是Chrome外掛開發,而是如何使用React.js來開發Chrome外掛,本文先簡單介紹下Chrome外掛的開發和ReactJS,最後介紹如何採用Facebook官方推薦的creat-react-app腳手架來開發Chrome外掛。

二、Chrome外掛開發基礎知識

下面是我看的幾篇教程,簡單看一下應該就可以算Chrome外掛速成了:

簡單來說,一個最基本Chrome外掛應用需要有一個manifest.json清單檔案,這個檔案一般長這樣:

這個檔案裡描述了外掛應用的一些屬性,如名稱、版本、需要的許可權、介面的對應的html檔名等等。額!!乍一看怎麼和AndroidManifest.xml的功能這麼像啊?是的大兄弟!!恭喜你對技術的理解已經融會貫通了!

根據manifest.json檔案可以看到,一個Chrome外掛最少得有:manifest.json檔案,icon.png圖示和popup.html檔案。當然檔名可以隨便改,只要和manifest.json裡宣告的一致就行。

這裡就不浪費時間具體說怎麼開發外掛了,各路前端大牛比我強100倍。但我只強調一點,那就是popup.html中引用的js檔案只能是外部引入,不能在popup.html檔案裡面寫js程式碼。所以一般我們還有見到popup.js檔案。另外如果你想知道自己使用的外掛有什麼祕密,完全可以去Chrome瀏覽器的安裝目錄下面把它們給扒出來。。

三、React JS基礎知識

React.js不需要多說了吧,從React這個詞在技術界誕生起,就是一顆明星,連我這種死抱著Native技術的人都不得不去學習它。。

簡單扯兩句React JS的話題(React Native下次再說),作為一個Android App/SDK開發,我沒有開發過太多傳統意義上的Web頁面,但是經過我學習了大概一週多的時間,我發現React JS開發Web頁面的思路其實和客戶端很像,不去用jQuery/Zepto啊操作DOM,而是關注資料本身,以資料驅動去改變介面。重構寫好了靜態html後,哪塊地方需要變化,你就把哪裡變成一個變數放到元件的State/Props裡面(至於元件怎麼切分,哪個資料放State,哪個放Prop不是今天要討論的話題),然後就只用關注資料的變化,然後setState一下介面就可以重新整理了。理解了這一點,就會發現其實開發Web頁面很簡單。比起操作DOM,一些模板引擎之類的東西,我認為React這個思想非常容易接受,寫起來也很舒服,完全沒有那種混亂的感覺,而且現在ReactJS生態圈非常大,諸如Redux這類的庫使得ReactJS越發的犀利,很多公司早就用得飛起了。

扯得有點遠了,ReactJS開發我推薦大家就看Facebook官方的示例就夠了。英文不好的朋友可以看看阮一峰老師的部落格,或者看看這篇入門教程也是闊以的。

四、應該用哪個腳手架?

當然是Facebook官方推薦的creat-react-app。開啟終端,依次輸入:

然後就在my-app下面看到這些檔案了。

到此為止,是一個標準的ReactJS編寫WebApp的步驟,在終端輸入npm start,就可以在瀏覽器中訪問本地的localServer了。

1.怎麼讓這個專案支援Chrome外掛開發呢?

前面介紹了,Chrome外掛最重要的檔案就是manifest.json清單檔案。我們先看下腳手架給我們預設生成的manifest.json長啥樣:

對於一個普通的WebApp來說,manifest.json檔案在快取、離線模式以及最新的PWA場景下會起作用,但是這裡我們是要開發Chrome外掛,那麼把它原來的內容通通刪掉,改成你的Chrome外掛所需要的格式和內容就好了。例如可以改成這樣:

這裡儘可能對腳手架的東西做最小的改動,把default_popup的檔名改成了index.html,因為腳手架預設會把js檔案都打包到一個main.js檔案中,並在index.html中插入這個main.js。

我們執行一下npm run build命令,就會發現生成了一個my-app/build目錄,這個目錄就是我們可以在chrome://extensions/去載入的外掛目錄,當然也可以用Chrome把這個目錄打包成一個crx外掛。

使用creat-react-app腳手架開發Chrome外掛的基本方法就是這樣了,但是在實際中我們會遇到很多的問題,有時甚至會想要執行npm run eject,然後去完全自定義webpack.config.js來實現打包。

2.background.js怎麼打包?

我們在開發外掛的時候,非常可能需要用到後臺的background.js,原因如下:

注意:不要在popup頁面的js空間變數中儲存資料。由於popup頁面只在使用者點選圖示時才會開啟,當使用者關閉這個頁面時就會停止,並沒有一個從始至終的例項分配給popup頁面。所以每當使用者開啟popup頁面時,它都是嶄新的,之前儲存在變數中的資料都會消失。如果需要通過popup頁面儲存使用者的資料,可以通過通訊將資料交給後臺頁面(background頁面)處理,或者通過localStorage和chrome.storage將資料儲存在使用者的硬碟上。

所以background.js最後也是要進入到我們的釋出資料夾下面的,這裡建議還是要堅持最低程度地修改腳手架的設定,建議不要npm run eject之後來修改webpack的配置,因為實在是真的有點複雜。

這次修改下package.json檔案:

可以看到我們新增了一個命令npm run build-chrome-ext,並把background.js丟到了build目錄下。如果你還有其他的js,我建議在my-app/src下建立一個my-app/src/chrome資料夾,專用於存在chrome相關其他js程式碼,然後在build的時候統一丟到build裡面。如果要minify這些js,同樣可以採用&&方式去新增命令。修改

3.需要注意的細節

由於使用了一些chrome.* API,我們需要在編譯js的時候將chrome這個全域性物件宣告一下。

creat-react-app這個腳手架在非eject模式下,沒辦法修改ESlint的配置來新增global物件,只能在用到了 chrome.* API的程式碼處新增 // eslint-disable-line 註釋來實現保證編譯通過。

如果你已經npm run eject了,在eject模式下,可以在package.json檔案裡配置ESLint:

五、其他腳手架推薦

除了自己改造Facebook推薦的creat-react-app外,下面兩個腳手架也算是使用者比較多的,專門用於開發Chrome外掛的腳手架。

相關文章