對於打包工具來講,最簡單也是最複雜的操做莫過於路徑的安排了,本來都在src
下的資源,想要打包到dist
目錄下,可是打包出來的文件路徑甚不如人意。明明想要分門別類地放置文件文件,而後卻像大雜燴同樣js
,html
,css
甚至圖片都混在了一塊兒。雖然打包以後運行沒什麼問題,可是這是要逼死強迫症患者啊。css
因此這篇文章就是講解如何明明白白安排各資源的路徑,無關webpack性能,無關各種騷操做,只是基礎的路徑操做。html
傳統的網站通常會將文件夾分爲三類,styles
,scripts
,images
,看到這個三個文件夾就會倍感親切,有種老朋友的感受。若是這個時候css文件出如今了scripts中,或者更images文件夾出如今scripts中,估計寫這個網站的前端會被你們吐槽了。可是若是是webpack打包以後發生這種事,絕不驚奇,習覺得常,佛系打包。每次打包都是一個驚喜,若是配置不對,打包出來的文件可能會和你玩捉迷藏。爲此我整理了下webpack打包中可能會出現的路徑問題,以下方大綱所示,若是有夥伴們遇到過此類問題能夠按需查詢。前端
大綱:webpack
webpack打包流程簡單來講就是把全部的資源都變成js的chunk模塊,而後再對chunk們進行操做,最後再根據配置分門別類輸出。git
爲了可以深刻了解咱們的文件打包去哪兒了,我建了一個比較變態的文件目錄。github
JS在這個過程當中是最好控制的,根據配置的entry和output既能夠輕鬆控制前因後果。而這兩個配置在官方文檔中也解釋地至關詳細。web
像下方這樣的配置,應該比較經常使用,就是一個html,一個場景一個entry,而後output的時候按照entry名字生成相對應的文件。工具
entry:{ "index":path.resolve(__dirname,"src/scripts/index/index.js"), "list":path.resolve(__dirname,"src/scripts/list/list.js"), }, output:{ path:path.resolve(__dirname,"dist"), filename:"[name].js" },
這裏須要注意:性能
filename:"scripts/[name].js"
,這樣就會在dist目錄下生成一個scripts的目錄,JS打包以後都會生成在這個文件夾之中。CSS的引用,就比CSS複雜一些,不是直接HTML引用,而是import "../../styles/index/index.css"
像這樣導入,或者require
到JS之中,這樣webpack纔會去打包CSS到新目錄下。不過呢原生的CSS,JS是不認識的,因此這個時候須要loader幫咱們編譯CSS才能導入JS之中。優化
css-loader很顯然就是將CSS編譯成JS認識的語法。
style-loader最主要乾的事情就是將JS中編譯的CSS代碼插入DOM之中,使之生效。
mini-css-extract-plugin,這個插件最主要的目的就是將每一個JS(chunk)中的CSS代碼剝離出來,分別打包到各自命名的CSS文件之中。(注:ExtractTextPlugin只適用於webpack3及如下。),有關CSS文件生成路徑的問題,咱們主要就是用這個插件來實現,而這個插件不只要在loader的時候參與編譯CSS,還須要在打包的時候發揮做用,將CSS打包到相應的文件夾之中。
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports={ ... //loader module: { rules: [ { test: /\.css$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' } }, "css-loader" ] } ] , }, plugins: [ //css打包 new MiniCssExtractPlugin({ filename: "styles/[name].css" }) ] }
上述代碼給出了MiniCssExtractPlugin這個插件的用法。它主要的生成配置是在filename:"styles/[name].css"
,這否以爲似成相識,和webpack的output.filename的配置同樣,能夠將css打包至styles文件夾之下。
HTML的打包編譯就比較特殊,通常使用html-webpack-plugin
插件,經過編寫模版來配置生成html文件。這個插件的功能很強大,不過這裏只說起生成路徑的配置。
const HtmlWebpackPlugin = require('html-webpack-plugin');
我是這樣配置html,導入模版,而後生成文件,我給filename一個絕對路徑,這樣就不用擔憂文件會生成到什麼奇怪的地方了。固然直接filename: 'index.html'
給一個文件名也是能夠的,這樣就會按照webpack中output配置的path,即項目目錄爲對象的相對路徑。這裏的chunks: ["index"]
使之html中包含的獨立,不然會將全部的資源所有潛入當前的html中。
new HtmlWebpackPlugin({ filename: path.join(__dirname,'/dist/index.html'), template: path.join(__dirname,'/src/templates/index.html'), chunks: ["index"] })
這一塊應該是最相對最複雜的一塊了,不過度別分析以後也不會太負責。
這一部分是最簡單的了,由於從JS中獲取資源最直接,不用編譯多道工序。
說到導入文件的地址,咱們最經常使用的是file-loader
這個loader。在outputPath
之中配置文件的生成地址。這裏咱們配置了images/
,也就是dist/images
之下。useRelativePath
這個選項看似人畜無害,可是配置的時候需謹慎否則屢次調用這個loader的話,就會發生dist/images/images
的狀況。
{ test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: { useRelativePath:false, outputPath: 'images/', name: '[name].[ext]' } } ] },
JS想要導入圖片,也很簡單直接import或者require+圖片地址,便可,與CSS的調用一致。
在CSS中咱們常常會用到圖片,好比background這個屬性,那麼在CSS中咱們怎麼打包圖片,而且改變CSS中圖片的地址呢?由於咱們CSS是被import到JS之中的,因此和JS同樣的處理方式,file-loader會幫助咱們處理好圖片的問題的。不過CSS中圖片的引用地址是個問題啊。
{ loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' } }
這個時候就能夠利用loader中publicPath這個屬性,這個屬性不參與編譯,只在最後打包的時候替換路徑。這裏CSS中圖片的路徑是image/xxx.jpg
,若是咱們加上這個../
,那麼就變成../image/xxx.jpg
。經過這樣來控制CSS中圖片的問題,若是想改爲CDN地址也是能夠。
這一部分是最使人頭疼的file-loader
不處理html中的img標籤,這裏咱們會利用html-loader
來處理圖片的問題,以下方配置:
{ test: /\.html$/, use: [ { loader: 'html-loader', options: { publicPath:"./", attrs: ['img:src'] } }], }
這樣咱們就會將html中的圖片文件完美的打包出來啦。不過這個插件沒有publicPath的配置,這裏的地址須要依靠output.publicPath。若是output.publicPath爲空,那麼打包出來的文件地址就是images/xxx.jpg
。若是配置了output.publicPath="./"
,那麼打包出來的就是./images/xxx.jpg
。
打包路徑說複雜各類相對路徑確實容易搞暈,因此這個時候須要保持清醒的頭腦。該用相對路徑的用相對。不須要的就用絕對路徑。有些插件仍是很人性化地有publicPath
這個選項,還能夠手動控制下。
本文所用到的loader,plugin一覽
plugin/loader | usage |
---|---|
file-loader | 用於管理JS中導入的資源或者CSS中引用的資源路徑。 |
html-loader | 用於管理HTML,提取管理引用資源,如img中的src,還能夠對html進行優化,如去除全部的註釋壓縮等。 |
mini-css-extract-plugin | 用於提取CSS,並進行分別打包,雖然有mini,可是意思不是壓縮CSS,如需壓縮還須要其餘的插件配置。 |
html-webpack-plugin | 一個強大的html管理插件,能夠用於生成html,能夠配置模板,靈活的配置chunk。 |