涉及到的方面較廣,有經(jīng)驗(yàn)的大佬可選擇性跳過植旧。
基礎(chǔ)
1.webpack打包本質(zhì)
本質(zhì)就是nodejs去執(zhí)行webpack腳本得问,由webpack腳本對(duì)項(xiàng)目各個(gè)文件進(jìn)行必要的編譯(翻譯/字符串替換)再輸出到某個(gè)目錄矫夯。即可以簡(jiǎn)單理解為webpack是一個(gè)nodejs的小程序唧龄,功能是讀取文件內(nèi)容旧乞,進(jìn)行字符串修改操作后蔚润,輸出內(nèi)容。
因此具體的前端js文件中是不可使用nodejs的東西的尺栖,因?yàn)樗鼈儧]有被nodejs運(yùn)行嫡纠。至于process變量,在webpack打包中時(shí)的確就是nodejs的process;在最終的瀏覽器中除盏,process只是一個(gè)最簡(jiǎn)單的副本對(duì)象叉橱,擁有與nodejs的process相似的數(shù)據(jù)內(nèi)容,但是并不是同一對(duì)象痴颊。
2.import from 和require
webpack相關(guān)腳本中的require和我們前端js文件中使用的require不是一回事赏迟。
你可以發(fā)現(xiàn)在webpack相關(guān)文件中,全部使用require導(dǎo)入蠢棱,這個(gè)require就是nodejs模塊化的關(guān)鍵字锌杀。
而具體前端js文件中,使用到的require是由webpack提供的一個(gè)函數(shù)泻仙,功能類似但更加強(qiáng)大糕再。主要能力有:完成導(dǎo)入,參數(shù)可以省略部分后綴名(需要配置)玉转、是目錄時(shí)自動(dòng)尋找該目錄下的index.js并導(dǎo)入突想、能夠使用別名(alias,需要配置)究抓、導(dǎo)入圖片(實(shí)際導(dǎo)入為base64編碼后的字符串)猾担、提供給loader以擴(kuò)展導(dǎo)入vue和sass等更多文件。
至于import from
刺下,實(shí)際上是語法糖绑嘹,import img from './a.jpg'
被處理為const img=require('./a.jpg')
,這個(gè)require就是上述的require橘茉,是webpack提供的一個(gè)函數(shù)工腋。
注意:對(duì)于js模塊化,你可能還需要了解下CommonJS和ES6規(guī)范的語法形式:js require/exports和import/export畅卓。
另外nodejs中借助babel相關(guān)包擅腰,同樣可以提供import from的語法糖,但是它的這個(gè)import from只是換成nodejs的關(guān)鍵字require翁潘,并沒有像webpack那樣處理(實(shí)際上也不需要)趁冈。我這里只是想提醒下這個(gè)差異,畢竟前端使用nodejs開發(fā)時(shí)拜马,并不需要nodejs跑我們的前端js文件箱歧,因此我們的前端文件擁有更多可能的自定義語法、格式一膨、功能
正文
1.webpack模塊化處理解析配置
即webpack的resolve配置:解析(resolve)
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),//此resolve是外面定義的一個(gè)函數(shù),用于生成絕對(duì)路徑
'@assets': resolve('src/assets')
}
},
上面require提到的別名洒沦、可省略擴(kuò)展名在這里配置豹绪。
至于require函數(shù)中的路徑參數(shù),具體的解析法則如下:webpack 如何解析代碼模塊路徑
1.解析相對(duì)路徑
查找相對(duì)當(dāng)前模塊的路徑下是否有對(duì)應(yīng)文件或文件夾
是文件則直接加載
是文件夾則繼續(xù)查找文件夾下的 package.json 文件
有 package.json 文件則按照文件中 main 字段的文件名來查找文件
無 package.json 或者無 main 字段則查找 index.js 文件.
2.解析模塊名
查找當(dāng)前文件目錄下瞒津,父級(jí)目錄及以上目錄下的 node_modules 文件夾,看是否有對(duì)應(yīng)名稱的模塊
3.解析絕對(duì)路徑
直接查找對(duì)應(yīng)路徑的文件
2.圖片的去向
一般受url-loader和file-loader控制。
具體可以直接去看他們文檔。簡(jiǎn)單而言u(píng)rl-loader把小圖片變?yōu)閎ase64的字符串然后直接替換路徑僧家;file-loader把url-loader沒處理的那些大圖片給復(fù)制到指定位置(用戶設(shè)置),同時(shí)把原來的的路徑替換成publicPath+指定位置(用戶設(shè)置)
肌稻。
這里的publicPath設(shè)置有講究,因?yàn)橄鄬?duì)路徑中css和js的起始路徑不一致旦棉。
如publicPath:'./'
绑洛,那么在打包后瀏覽器環(huán)境下,css的./
是指css所在路徑绑蔫;而js中的./
是指瀏覽器當(dāng)前地址欄的url的路徑目錄。因此假如/mycss/a.css
中有url(./a.jpg)
,瀏覽器認(rèn)為圖片在/mycss/a.jpg
缸托;假如在/a/b/
網(wǎng)址下矫限,js設(shè)置img.src=url(./a.jpg)
,瀏覽器認(rèn)為圖片在/a/b/a.jpg
這個(gè)時(shí)候我們可以調(diào)整file-loader處理圖片時(shí)的參數(shù)咬扇,單獨(dú)為其設(shè)置publicPath而不是使用全局publicPath,這比較靈活坡垫,對(duì)應(yīng)上自己打包后的圖片路徑即可
3.圖片路徑
1.css中:
問題主要是"路徑別名"堡妒,若要使用皮迟,路徑前要加個(gè)~
,即url('~@assets/a.jpg')
之類的。
因?yàn)閏ss中我們無法使用require函數(shù)辨图,url-loader和file-loader不能確定解析方式。比如說我們有個(gè)別名@
代表src目錄肢藐,但是恰好我們目錄下有個(gè)@
文件夾故河,那么就產(chǎn)生了二義性無法確定。因此默認(rèn)情況下吆豹,css中所有路徑都不認(rèn)別名忧勿,除非路徑開頭有個(gè)~
杉女,指明要額外使用模塊路徑解析
2.html中:
同css,新版本中好像不用加~
也行鸳吸,見仁見智
3.js中:
不用寫~
,require一定使用模塊路徑解析速勇。另外由于js比起他們多了動(dòng)態(tài)設(shè)置晌砾,設(shè)置圖片src時(shí),沒有各種loader幫我們處理了烦磁,很可能對(duì)不上打包后的目錄結(jié)構(gòu)养匈。這要求我們必須正確把地址寫成最終打包后的圖片相對(duì)地址,十分不利于修改和維護(hù)
正確方法是用require函數(shù)(webpack提供)都伪,這個(gè)是運(yùn)行時(shí)也存在的呕乎,它能夠讓路徑參數(shù)的解析仍然從開發(fā)目錄開始計(jì)算,計(jì)算法則同上所述陨晶,因此我們放心在這里寫開發(fā)時(shí)的圖片路徑猬仁。當(dāng)然,這個(gè)require返回值也如上所述先誉,對(duì)于圖片文件返回base64編碼后字符串湿刽。
注意require中路徑別名問題。使用別名時(shí)褐耳,需要把別名字符串的部分直接包含在參數(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`)//錯(cuò)誤
我也不知道這個(gè)是bug還是什么鬼了,有了解的大佬可以說下