webpack 4.x一塊兒學習(二)

接着上一塊https://juejin.im/post/5be29710e51d457e90193cf3

模塊:CSS文件打包

Webpack在生產環境中有一個重要的做用就是減小http的請求數,就是把多個文件打包到一個js裏,這樣請求數就能夠減小好多。在學習CSS打包以前,須要先對webpack.config.js裏的Loaders配置項進行了解。css

Loaders(如下全部的配置都是基於3版本的 若是過程當中有bug 會進行改進)html

Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的緣由。經過使用不一樣的Loader,Webpack能夠的腳本和工具,從而對不一樣的文件格式進行特定處理。前端

簡單的舉幾個Loaders使用例子:vue

能夠把SASS文件的寫法轉換成CSS,而不在使用其餘轉換工具。 能夠把ES6或者ES7的代碼,轉換成大多瀏覽器兼容的JS代碼。 能夠把React中的JSX轉換成JavaScript代碼。webpack

注意:全部的Loaders都須要在npm中單獨進行安裝,並在webpack.config.js裏進行配置。下面咱們對Loaders的配置型簡單梳理一下。web

test:用於匹配處理文件的擴展名的表達式,這個選項是必須進行配置的; use:loader名稱,就是你要使用模塊的名稱,這個選項也必須進行配置,不然報錯; include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選); query:爲loaders提供額外的設置選項(可選)。npm

打包CSS文件json

創建index.css文件 ./src/css/index.css瀏覽器

要打包CSS你必須先要有個CSS文件,在/src目錄下,咱們創建一個css文件夾,在文件夾裏創建index.css文件。代碼內容以下緩存

body{
        background-color: red;  能夠跟我不同 徹底爲了測試
        color: white;
    }
複製代碼

CSS文件創建好後,須要引入到入口文件中,才能夠打包到,這裏咱們引入到entry.js中。

/src/entery.js中在首行加入代碼: import css from './css/index.css';

也就是在entry.js中頂部導入

import  css from './css/index.css';

    document.getElementById('title').innerHTML='Hello Webpack';
複製代碼

CSS和引入作好後,咱們就須要使用loader來解析CSS文件了,這裏咱們須要兩個解析用的loader,分別是style-loader和css-loader

首先咱們先使用npm 安裝(有些腳手架生成的webpack 會自動安裝這些簡單的加載器)

npm install style-loader css-loader --save-dev 一步到位

安裝好以後查看一下package.json

兩個loader都下載安裝好後,咱們就能夠配置咱們loaders了。

loaders配置:

修改webpack.config.js中module屬性中的配置代碼以下:

webpack.config.js

const path = require('path')
    module.exports={
        mode: 'development',
        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑文職
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js'
                    },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [  =>之前此處是loaders 如今是rules
                {
                test: /\.css$/, =>正則 這個好理解
                use: [ 'style-loader', 'css-loader' ] =>使用css 與 style loader 來加載匹配到的css文件
                }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[],
        //配置webpack開發服務功能
        devServer:{              
            host:'localhost',   //服務器的ip地址
            port:1573,  //端口
        }
    }
複製代碼

webpack一下,以前咱們在js中引入了css 運行一下html ok 有樣式了

友情提示:小夥伴們在測試的時候,可能會遇到找不到模塊的 這種error 建議從新新建配置 從新npm插件 剛纔我就莫名其妙找不到模塊了 從新安裝了一下就能夠了

loader的三種寫法:

有些小夥伴看到別人的CSS打包的寫法和個人寫法不太同樣,是否是我寫錯了,loader還有幾種寫法,這裏咱們就看兩種另外的寫法。

使用use

module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },
複製代碼

把use換成loader。

module:{
        rules:[
            {
                test:/\.css$/,
                loader:['style-loader','css-loader']
            }
        ]
    },
複製代碼

第三種寫法:用use+loader的寫法:

module:{
        rules:[
            {
                test:/\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    },
複製代碼

沒有全測 也不知道哪裏須要修改 小夥伴能夠自行測試一下

接下來咱們來試着壓縮一下js

在Webpack中能夠很輕鬆的實現JS代碼的壓縮,它是經過插件的方式實現的,這裏咱們就先來引入一個uglifyjs-webpack-plugin(JS壓縮插件,簡稱uglify)。

注意:雖然uglifyjs是插件,可是webpack版本里默認已經集成,不須要再次安裝。

const path = require('path')
    const webpack =require('webpack')  =>注意這裏咱們引入了webpack
    module.exports={
        mode: 'development',
        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑文職
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js'
                    },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [
                {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
                }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[
            new webpack.optimize.UglifyJsPlugin() =>由於是webpack集成的 因此要在上方引入webpack
        ]            
     
    }
複製代碼

此時咱們webpack一下 你會發現 報錯(報錯的內容就不截屏了)

在webpack4.0版本中已經廢棄了以前 UglifyJsPlugin的用法,用的是optimization.minimize

從新配置一下webpack

const path = require('path') 
                                                     刪除了webpack模塊引入

    const UglifyJsPlugin=require('uglifyjs-webpack-plugin');=>須要 npm 手動安裝
    module.exports={
        mode: 'development',
        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑文職
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js'
                    },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [
                {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
                }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[
            
        ],
        
        optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        compress: false
                    }
                })
            ]
        },
        
     
    }
複製代碼

這裏須要注意一下 webpack打包也是分模式的 默認是mode ‘production(生產環境)’

若是咱們沒在config.js中標明webpack 的mode 直接webpack是會有警告的

就是說咱們打包的命令完整應該是 webpack --mode production/development

默認是production 此方法打包文件會小不少 注意一下便可

production 其實默認自帶了uglifyjs-webpack-plugin 插件 已經不須要使用

也就是咱們在production 狀態下 其實能夠不須要配置 直接 webpack --mode development 便可

接下來我仍是設置默認 production 環境下測試 方便點

插件配置:HTML文件的發佈

webpack 構建項目時, 經過指定的入口文件,會將全部的js css 等以依賴模塊的形式打包成一個或多個的腳本文件,一般狀況下,腳本文件會附屬於html 文件運行,這時候須要將 打包好的腳本文件,注入到html 中, html-webpack-plugin 插件的目的是, 以一個html 爲模板, 將打包好的腳本注入到模板中, 相關的配置以下

先安裝 html-webpack-plugin npm i html-webpack-plugin -D

安裝好以後 咱們在plugins中配置

const path = require('path')
    const htmlPlugin = require('html-webpack-plugin');  =>引入模塊
    module.exports={

        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑文職
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js'
        },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [
                {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
                }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[
            new htmlPlugin({   =>這是通常狀況下的配置  打包html 
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            })
        ],                                 
    }
複製代碼

minify:是對html文件進行壓縮 hash:爲了開發中js有緩存效果,因此加入hash,這樣能夠有效避免緩存JS。 template:是要打包的html模版路徑和文件名稱。

此時咱們webpack --mode production

此時dist下生成了 index.html js是上面的命令生成的 這就是咱們常見的狀態了 熟悉vue的小夥伴都知道 npm run build就會生成這倆文件 此時咱們直接開index.html 也是有效果的 若是須要更名的話能夠再配置一個參數 filename:'filename.html' 必定要加後綴

圖片邁坑:CSS中的圖片處理

在學習Webapck過程當中你可能遇到的第一個坑就是CSS中的圖片處理。不少webpack新手都在圖片的坑中沒法自拔(有的小夥伴在開發環境中是能夠找到圖片的,可是一打包後就找不到圖片了,有的小夥伴是不知道如何正確引入html或者css中的圖片,致使程序出錯)

圖片寫入css 咱們先找張圖片先 img1.imgtn.bdimg.com/it/u=198855…

注意必定要本地圖片啊 剛纔偷懶使用網絡圖片發現竟然成功了 不能成功 必定要失敗的

index.html

<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>webpack</title>
    </head>
    <body>
        <div id="tupian"></div>
        <script src="./../dist/bundle.js"></script>
    </body>
    </html>
複製代碼

index.css css仍是在js中引入

#tupian{
background-image: url('./../image/1.jpg');
width:466px;
height:453px;
 }
複製代碼

咱們這時候 經過webpack --mode production 是會失敗的 失敗的緣由就是缺乏loader的解析

對於圖片咱們也須要安裝兩loader

安裝file-loader和url-loade npm install --save-dev file-loader url-loader

file-loader:解決引用路徑的問題,拿background樣式用url引入背景圖來講,咱們都知道,webpack最終會將各個模塊打包成一個文件,所以咱們樣式中的url路徑是相對入口html頁面的,而不是相對於原始css文件所在的路徑的。這就會致使圖片引入失敗。這個問題是用file-loader解決的,file-loader能夠解析項目中的url引入(不只限於css),根據咱們的配置,將圖片拷貝到相應的路徑,再根據咱們的配置,修改打包後文件引用路徑,使之指向正確的文件。

url-loader:若是圖片較多,會發不少http請求,會下降頁面性能。這個問題能夠經過url-loader解決。url-loader會將引入的圖片編碼,生成dataURl。至關於把圖片數據翻譯成一串字符。再把這串字符打包到文件中,最終只須要引入這個文件就能訪問圖片了。固然,若是圖片較大,編碼會消耗性能。所以url-loader提供了一個limit參數,小於limit字節的文件會被轉爲DataURl,大於limit的還會使用file-loader進行copy。

安裝好以後咱們來配置webpack 直接在module中配置loader

const path = require('path')
    const htmlPlugin = require('html-webpack-plugin');
    module.exports={

        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑文職
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js'
        },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [
                {
                test: /\.css$/,  => css的loader
                use: [ 'style-loader', 'css-loader' ]  =>這邊順帶提一下 其實webpack的loader是從右往左看
                                                 =>也就是 先使用css loader  再使用style loader  
                },
                {
                    test:/\.(png|jpg|gif)/ , =>圖片的loader
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:500000   =>不認識limit的小夥伴能夠自行百度一下  相似咱們的流量 哈哈  好吧其實就是指500000B
                        }
                    }]
                 }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            })
        ],
            
    }
複製代碼

接下來咱們webpack --mode production 便可 成功生成

爲何只使用了url-loader

有的小夥伴會發現咱們並無在webpack.config.js中使用file-loader,可是依然打包成功了。咱們須要瞭解file-loader和url-loader的關係。url-loader和file-loader是什麼關係呢?簡答地說,url-loader封裝了file-loader。url-loader不依賴於file-loader,即便用url-loader時,只須要安裝url-loader便可,不須要安裝file-loader,由於url-loader內置了file-loader。經過上面的介紹,咱們能夠看到,url-loader工做分兩種狀況:

1.文件大小小於limit參數,url-loader將會把文件轉爲DataURL(Base64格式);

2.文件大小大於limit,url-loader會調用file-loader進行處理,參數也會直接傳給file-loader。

也就是說,其實咱們只安裝一個url-loader就能夠了。可是爲了之後的操做方便,咱們這裏就順便安裝上file-loader。

###圖片邁坑:CSS分離與圖片路徑處理

CSS分離:extract-text-webpack-plugin

有些簡單的交互頁面中,你的JavasScript頁面代碼會很是少,而大部分代碼都在CSS中,這時候項目組長會要求把CSS單獨提取出來,方便之後更改。遇到這個需求你不要驚慌,已經有大神爲咱們準備好了對象的插件(plugin)

這個插件就能夠完美的解決咱們提取CSS的需求,可是webpack官方其實並不建議這樣做,他們認爲CSS就應該打包到JavasScript當中以減小http的請求數。但現實中的需求每每不是咱們前端能控制的,有些需求是咱們不能控制的,分離CSS就是這樣一個既合理由不合理的需求,說白了,仍是得聽老大的 ,若是小姐姐讓你這樣你作不作呢?

npm install --save-dev extract-text-webpack-plugin

安裝好了天然要用 咱們直接在webpack上方 引入 const extractTextPlugin = require("extract-text-webpack-plugin")

引入以後 咱們只需在webpack中new 使用 而且還要配置關於css的加載器

const path = require('path')
      const htmlPlugin = require('html-webpack-plugin');
      const extractTextPlugin = require("extract-text-webpack-plugin")
      module.exports={
        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑位置
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js'
        },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [
                {
                // test: /\.css$/,
                // use: [ 'style-loader', 'css-loader' ]
                test: /\.css$/,
                use: extractTextPlugin.extract({
                  fallback: "style-loader",
                  use: "css-loader"
                })
                },
                {
                    test:/\.(png|jpg|gif)/ ,
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:500000
                        }
                    }]
                 }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            }),
            new extractTextPlugin("/css/index.css") =>注意插件的使用   (此處是生成的文件位置  前面配置了path 默認都是dist文件下的)
        ],

    }
複製代碼

此時咱們webpack一下 是有錯誤的 由於extract-text-webpack-plugin 不支持4版本以上的 咱們既然學習4版本的webpack確定不能降級 好 咱們升級 npm install --save-dev extract-text-webpack-plugin@4.0.0-beta.0

安裝好以後 其他不變 再次 webpack一下 由於此時生成打包了三個文件 我給截圖一下

這樣就成功分離了 原本是起初咱們導入js中的 此時成功生成了index.css 而且裏面的url是base64形式的,可是咱們此時瀏覽dist下的html是沒有東西的 由於咱們路徑有問題 這裏是指圖片路徑 不是文件路徑

圖片路徑問題

利用extract-text-webpack-plugin插件很輕鬆的就把CSS文件分離了出來,可是CSS路徑並不正確,不少小夥伴就在這裏搞個幾天仍是沒有頭緒,網上也給出了不少的解決方案,我覺的最好的解決方案是使用publicPath解決

publicPath:是在webpack.config.js文件的output選項中,主要做用就是處理靜態文件路徑的。

此處增長一個知識 webpack-dev-server 原本是不想配置後面給你們簡單提一下,畢竟單獨測試webpack的真的很少,不少時候都是看webpack或者腳手架生成直接修改

測試publicPath的時候 沒設置服務器狀態老報錯 使用live-server也很差配置 因此簡單提一下webpack-dev-server的配置

npm install webpack-dev-server –save-dev 先安裝

在webpack.config.js 中配置

plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            }),
            new extractTextPlugin("/css/index.css")
        ],
        devServer:{  =>注意 與plugins同級
            //設置基本目錄結構
            contentBase:path.join(__dirname,'dist'),
            //服務器的IP地址,可使用IP也可使用localhost
           //  不知道本身IP的能夠 打開cmd 輸入ipconfig 查看
            host:'localhost',
            //服務端壓縮是否開啓
            compress:true,
            //配置服務端口號
            port:1717
        }
複製代碼

在packge.json的 scripts 中輸入"dev": "webpack-dev-server --open"

咱們啓動webpack-dev-server的時候只須要npm run dev 便可

啓動webpack-dev-server以後 會啓動熱更新 當咱們改變內容保存的時候會自動進行webpack命令打包 實時更新內容

別忘了咱們主要的目的 ,解決圖片路徑問題 使用publicPath

主要看output模塊

const path = require('path')
    const htmlPlugin = require('html-webpack-plugin');
    const extractTextPlugin = require("extract-text-webpack-plugin")
    module.exports={
       // mode:'development',
        //入口文件的配置項
        entry:{
            //裏面的entery是能夠隨便寫的
            entry:'./src/entry.js',
        },
        //出口文件的配置項
        output:{
            //打包的路徑文職
            path:path.resolve(__dirname,'dist'),
            //打包的文件名稱
            filename:'bundle.js',
            publicPath:'localhost:1717'  
        },
        //模塊:例如解讀CSS,圖片如何轉換,壓縮
        module:{
            rules: [
                {
                // test: /\.css$/,
                // use: [ 'style-loader', 'css-loader' ]
                test: /\.css$/,
                use: extractTextPlugin.extract({
                  fallback: "style-loader",
                  use: "css-loader"
                })
                },
                {
                    test:/\.(png|jpg|gif)/ ,
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:500000
                        }
                    }]
                 }
            ]
        },
        //插件,用於生產模版和各項功能
        plugins:[
            new htmlPlugin({
                minify:{
                    removeAttributeQuotes:true
                },
                hash:true,
                template:'./src/index.html'
            }),
            new extractTextPlugin("/css/index.css")
        ],
        devServer:{
            //設置基本目錄結構
            contentBase:path.resolve(__dirname,'dist'),
            //服務器的IP地址,可使用IP也可使用localhost
            host:'localhost',
            //服務端壓縮是否開啓
            compress:true,
            //配置服務端口號
            port:1717
        }

    }
複製代碼

接着咱們打包以後 便可顯示圖片了

相關文章
相關標籤/搜索