webpack 圖片路徑的深入淺出

涉及到的方面較廣,有經驗的大佬可選擇性跳過。


基礎

1.webpack打包本質

本質就是nodejs去執(zhí)行webpack腳本,由webpack腳本對項目各個文件進行必要的編譯(翻譯/字符串替換)再輸出到某個目錄。即可以簡單理解為webpack是一個nodejs的小程序,功能是讀取文件內容,進行字符串修改操作后,輸出內容。

因此具體的前端js文件中是不可使用nodejs的東西的,因為它們沒有被nodejs運行。至于process變量,在webpack打包中時的確就是nodejs的process;在最終的瀏覽器中,process只是一個最簡單的副本對象,擁有與nodejs的process相似的數(shù)據內容,但是并不是同一對象。

2.import from 和require

webpack相關腳本中的require和我們前端js文件中使用的require不是一回事。

你可以發(fā)現(xiàn)在webpack相關文件中,全部使用require導入,這個require就是nodejs模塊化的關鍵字。

而具體前端js文件中,使用到的require是由webpack提供的一個函數(shù),功能類似但更加強大。主要能力有:完成導入,參數(shù)可以省略部分后綴名(需要配置)、是目錄時自動尋找該目錄下的index.js并導入、能夠使用別名(alias,需要配置)、導入圖片(實際導入為base64編碼后的字符串)、提供給loader以擴展導入vue和sass等更多文件
至于import from,實際上是語法糖,import img from './a.jpg'被處理為const img=require('./a.jpg'),這個require就是上述的require,是webpack提供的一個函數(shù)。

注意:對于js模塊化,你可能還需要了解下CommonJS和ES6規(guī)范的語法形式:js require/exports和import/export。
另外nodejs中借助babel相關包,同樣可以提供import from的語法糖,但是它的這個import from只是換成nodejs的關鍵字require,并沒有像webpack那樣處理(實際上也不需要)。我這里只是想提醒下這個差異,畢竟前端使用nodejs開發(fā)時,并不需要nodejs跑我們的前端js文件,因此我們的前端文件擁有更多可能的自定義語法、格式、功能


正文

1.webpack模塊化處理解析配置

即webpack的resolve配置:解析(resolve)

  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'),//此resolve是外面定義的一個函數(shù),用于生成絕對路徑
      '@assets': resolve('src/assets')
    }
  },

上面require提到的別名、可省略擴展名在這里配置。
至于require函數(shù)中的路徑參數(shù),具體的解析法則如下:webpack 如何解析代碼模塊路徑

1.解析相對路徑
查找相對當前模塊的路徑下是否有對應文件或文件夾
是文件則直接加載
是文件夾則繼續(xù)查找文件夾下的 package.json 文件
有 package.json 文件則按照文件中 main 字段的文件名來查找文件
無 package.json 或者無 main 字段則查找 index.js 文件.
2.解析模塊名
查找當前文件目錄下,父級目錄及以上目錄下的 node_modules 文件夾,看是否有對應名稱的模塊
3.解析絕對路徑
直接查找對應路徑的文件

2.圖片的去向

一般受url-loader和file-loader控制。
具體可以直接去看他們文檔。簡單而言url-loader把小圖片變?yōu)閎ase64的字符串然后直接替換路徑;file-loader把url-loader沒處理的那些大圖片給復制到指定位置(用戶設置),同時把原來的的路徑替換成publicPath+指定位置(用戶設置)

這里的publicPath設置有講究,因為相對路徑中css和js的起始路徑不一致。
publicPath:'./',那么在打包后瀏覽器環(huán)境下,css的./是指css所在路徑;而js中的./是指瀏覽器當前地址欄的url的路徑目錄。因此假如/mycss/a.css中有url(./a.jpg),瀏覽器認為圖片在/mycss/a.jpg;假如在/a/b/網址下,js設置img.src=url(./a.jpg),瀏覽器認為圖片在/a/b/a.jpg
這個時候我們可以調整file-loader處理圖片時的參數(shù),單獨為其設置publicPath而不是使用全局publicPath,這比較靈活,對應上自己打包后的圖片路徑即可

3.圖片路徑

1.css中:
問題主要是"路徑別名",若要使用,路徑前要加個~,即url('~@assets/a.jpg')之類的。
因為css中我們無法使用require函數(shù),url-loader和file-loader不能確定解析方式。比如說我們有個別名@代表src目錄,但是恰好我們目錄下有個@文件夾,那么就產生了二義性無法確定。因此默認情況下,css中所有路徑都不認別名,除非路徑開頭有個~,指明要額外使用模塊路徑解析

2.html中:
同css,新版本中好像不用加~也行,見仁見智

3.js中:
不用寫~,require一定使用模塊路徑解析。另外由于js比起他們多了動態(tài)設置,設置圖片src時,沒有各種loader幫我們處理了,很可能對不上打包后的目錄結構。這要求我們必須正確把地址寫成最終打包后的圖片相對地址,十分不利于修改和維護

正確方法是用require函數(shù)(webpack提供),這個是運行時也存在的,它能夠讓路徑參數(shù)的解析仍然從開發(fā)目錄開始計算,計算法則同上所述,因此我們放心在這里寫開發(fā)時的圖片路徑。當然,這個require返回值也如上所述,對于圖片文件返回base64編碼后字符串。

注意require中路徑別名問題。使用別名時,需要把別名字符串的部分直接包含在參數(shù)中。即

let number=1, p1='./', p2='@assets'

img.src=require(`./assets/img${number}.jpg`)//正確
img.src=require(`@assets/img${number}.jpg`)//正確
img.src=require(`${p1}assets/img${number}.jpg`)//正確

img.src=require(`${p2}/img${number}.jpg`)//錯誤

我也不知道這個是bug還是什么鬼了,有了解的大佬可以說下

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容