顯微鏡下的webpack4:路徑操做

對於打包工具來講,最簡單也是最複雜的操做莫過於路徑的安排了,本來都在src下的資源,想要打包到dist目錄下,可是打包出來的文件路徑甚不如人意。明明想要分門別類地放置文件文件,而後卻像大雜燴同樣js,htmlcss甚至圖片都混在了一塊兒。雖然打包以後運行沒什麼問題,可是這是要逼死強迫症患者啊。css

因此這篇文章就是講解如何明明白白安排各資源的路徑,無關webpack性能,無關各種騷操做,只是基礎的路徑操做。html

傳統的網站通常會將文件夾分爲三類,styles,scripts,images,看到這個三個文件夾就會倍感親切,有種老朋友的感受。若是這個時候css文件出如今了scripts中,或者更images文件夾出如今scripts中,估計寫這個網站的前端會被你們吐槽了。可是若是是webpack打包以後發生這種事,絕不驚奇,習覺得常,佛系打包。每次打包都是一個驚喜,若是配置不對,打包出來的文件可能會和你玩捉迷藏。爲此我整理了下webpack打包中可能會出現的路徑問題,以下方大綱所示,若是有夥伴們遇到過此類問題能夠按需查詢。前端

大綱:webpack

  • js路徑問題
  • css路徑問題
  • html路徑問題
  • 圖片路徑問題(important)
    • js中的圖片引用路徑
    • css中的圖片引用路徑
    • html中的圖片引用路徑

webpack打包流程

webpack打包流程簡單來講就是把全部的資源都變成js的chunk模塊,而後再對chunk們進行操做,最後再根據配置分門別類輸出。git

爲了可以深刻了解咱們的文件打包去哪兒了,我建了一個比較變態的文件目錄。github

JS生成路徑

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"
},

這裏須要注意:性能

  • output.path是項目的路徑,也就是以後的css,圖片等打包會按着這個path爲相對路徑來生成文件。
  • output.filename不只僅能夠命名,若是你想要js放在特定目錄下能夠在這裏配置,就像這樣filename:"scripts/[name].js",這樣就會在dist目錄下生成一個scripts的目錄,JS打包以後都會生成在這個文件夾之中。

CSS生成路徑

CSS的引用,就比CSS複雜一些,不是直接HTML引用,而是import "../../styles/index/index.css"像這樣導入,或者require到JS之中,這樣webpack纔會去打包CSS到新目錄下。不過呢原生的CSS,JS是不認識的,因此這個時候須要loader幫咱們編譯CSS才能導入JS之中。優化

CSS的loader們

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的打包編譯就比較特殊,通常使用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"]
})

圖片生成路徑

這一塊應該是最相對最複雜的一塊了,不過度別分析以後也不會太負責。

images in JS

這一部分是最簡單的了,由於從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的調用一致。

images in 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地址也是能夠。

images in HTML

這一部分是最使人頭疼的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。
相關文章
相關標籤/搜索