填坑:在 SegmentFault 開發單頁應用之圖片引用的問題探索

前言

前段時間,SegmentFault 低調上線了 技術號 模塊,方便用戶對數據進行集中管理。在開發過程當中,第一次引入了 MV* 框架。css

clipboard.png

SF 的基本架構仍是後端路由,這也使得頁面頻繁地總體請求,體驗很是很差。而技術號這個模塊,不依賴 SEO,側邊導航又具備很是強烈的可切換性,因此適當地引入一個 MV* 框架是很是合適的。基於此考慮,決定在這個模塊的開發中引入 Vue.js。前端

SF 目前的前端架構是很是傳統的,jQuery+BootStrap+Requirejs+Gulp 的開發組合,r.js 作上線前的打包。如何將 Vue.js 應用進入目前的架構?其實很是簡單,遵循一個原則便可,r.js 最後打包成一個 js 文件,而 webpack 最後也是打包成一個 js 文件。webpack

咱們用 webpack-dev-server 起前端 server 後,在內存中生成的 js 的路徑相似 localhost:8080/xxx.js,而後在後端模版中引用這個 js 便可。值得注意的是,必須寫死絕對路徑,因此只能指定端口,目前我尚未找到更好的辦法解決這個問題。程序員

圖片引用

其餘部分的開發,好比 js 和 css 都沒有什麼大的問題,圖片的引用成了問題。在第一次上線時我用了線上的絕對路徑,這顯然是不合理的。web

以前的圖片引用,實際上是依賴後端的。前端上線時,會有一個文件夾包含全部的 js、css 以及圖片文件,而後將這個文件夾重命名(重命名成一個哈希版本號),再上傳到 CDN。因此若是獨立打開 js、css 或者圖片文件,其實路徑上是會有一個版本號的。chrome

那麼目前線上是如何解決的?目前應用圖片的地方主要是後端模版文件以及 css。若是是後端模版文件,引用圖片時會先調用一個後端函數,這個函數會返回圖片路徑,很顯然開發環境和線上環境這個路徑的結果是不一樣的。一樣,js 和 css 的引入,都會被這個函數先調用才返回引用路徑。而在 css 中引用圖片就沒啥問題了,只是個相對路徑的事。segmentfault

而將圖片引用放入前端了呢?圖片的路徑和 js 的路徑具備某種聯繫,本質是須要獲取這個哈希版本號。問題在於,如何獲取正在執行的 js 文件的路徑?其實這很像是一道腦筋急轉彎,若是習慣了 Node 的方式,可能會從 __dirnameprocess.cwd() 去入手,可是很遺憾雖然客戶端也能引入 process 、path 等包,可是獲取不到相似的值。答案也很簡單,直接獲取 script 的 dom 節點,而後取 src 便可,就是完美的絕對路徑。另外還有個方法,能夠用 document.currentScript.getAttribute('src'),可是 src 賦值的字符串是什麼,它就是什麼,並且在實際開發中莫名報錯,因此我用了前者。後端

cdn: src => {
  let jsPath = document.getElementById('indexScript').src.replace(/script.*/, 'img/') 
  src = jsPath + src
  return src
}

這樣就粗暴地解決了線上圖片引用的問題。架構

開發 VS 線上

可是本地開發引用圖片的問題尚未解決。app

綜上所述,本地開發起的前端 server,實際上是用了絕對地址 localhost:8080/xxx.js,若是用以上規則獲取圖片,很顯然獲取的仍是 localhost:8080 域名下的圖片,咱們須要將其切換到後端路由的測試域名下。

也就是規則相似 localhost:8080/build/xxx/img/xxx.png 的請求都須要轉到另一個域名下(實際開發中是 sf.testapp.org),chrome 下有個神器 ReRes 能夠輕易作到。

配置以下:

// If URL match
http://localhost:8080/build/(.*)/img/
// Response
http://sf.testapp.org/build/$1/img/

這樣就粗暴解決了開發環境引用不到圖片的問題。

待續

這並非終點。其實目前的圖片是放在最終上線的靜態文件文件夾中,和 Vue.js 整個開發項目剝離,這並非一個好的方式。最好的方式確定是放在 Vue.js 項目中,好比 assets 或者 static 文件夾下。這就須要在前端引用圖片的時候判斷是開發仍是線上環境,分別引用不一樣地址,開發完後,打包前須要將項目中的圖片同步到須要上線的靜態文件文件夾中。還有另外一種方案,開發和線上引用一個地址,可是開發環境引用時再作一次映射,跳到 Vue.js 項目內。

目前還沒考慮這點,由於這只是 MV* 的第一次嘗試,文件目錄的結構還沒最終肯定。

思考

這個功能的開發其實不具備典型的參考意義,我稱之爲 "走 SF 特點的一次開發嘗試"。畢竟須要先後端路由混雜,並且還和最終線上打包方式有關,只能因地制宜,走本身的路。

這讓我想到了以前一位前輩對我說的話:

前端的主要競爭力仍是學習能力,程序員的競爭力是解決問題的能力。

共勉之

相關文章
相關標籤/搜索