1. 程式人生 > 其它 >帶你上手全新版本的Webpack 5

帶你上手全新版本的Webpack 5

摘要:webpack5快速入門,船新版本,建議收藏

本文分享自華為雲社群《webpack5快速入門,船新版本,建議收藏》,作者:北極光之夜。。

一. 快速上手

1.1 Webpack功能:

打包: 將不同型別資源按模組處理進行打包。
靜態: 打包後最終產出靜態資源。
模組: webpack 支援不同規範的模組化開發

1.2 安裝webpack:

終端輸入: npm install webpack -g

1.3 快速模擬搭建一個專案目錄:

utiles.js:

function add(a,b){
    console.log(a+b);
}
export {add} ;

index.js:

import {add} from './utiles/utiles.js'
add(6,9);

1.4 webpack打包:

終端輸入:webpack

webpack會自動尋找src目錄,然後尋找index.js入口檔案,然後進行打包,最終生成一個dist目錄為打包後內容。

index.html引入:

 <script src="../dist/main.js"></script>

結果:

二.基本使用:

2.1.配置檔案:

可以在配置檔案裡定義配置,表示你想如何打包,能設定很多條件。webpack會根據你配置檔案的配置規則來進行打包。在src同級目錄下新建一個webpack.config.js

檔案,裡面寫配置資訊。

如最基本的入口和出口:

const path = require('path');
module.exports = {
  //打包入口檔案路徑
  entry: './src/index.js',
  //path打包出口路徑,filename寫打包後文件名
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
  },
};

終端輸入webpack後成功打包了build.js檔案,跟上面打包的main.js內容一樣:

2.2.loader:

為什麼使用loader:

webpack 只能理解 JavaScript 和 JSON 檔案,這是 webpack 開箱可用的自帶能力。loader 能讓 webpack 能夠去處理其他型別的檔案(比如css型別檔案,圖片型別,txt型別等等),並將它們轉換為有效模組,以供使用。

2.2.1 css-loader:

比如,我想webpack能打包css,終端輸入以下命令先安裝css-loader:

npm i css-loader -D

1.可以在匯入css檔案的時候指定loader,這樣就不報錯了,在匯入css檔案路徑前新增css-loader!:

import 'css-loader!./css/index.css'

2.當然,也可以在配置檔案設定:

const path = require('path');
module.exports = {
  //打包入口檔案路徑
  entry: './src/index.js',
  //path打包出口路徑,filename打包後文件名
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
  },
  //定義一些規則
  module: {
      //數組裡每個元素為一個規則
     rules:[
        {
            test: /\.css$/,
            use: [
                {loader: 'css-loader'}
            ]
          //簡寫為 use: ['css-loader']    
        }
     ]
  }
};

test 屬性,定義一個正則表示式,匹配需要處理的檔案型別。識別出哪些檔案會被轉換。
use 屬性,定義出在進行轉換時,應該使用哪個 loader。

配置檔案裡配置後,別忘了在index入口檔案匯入css檔案。

2.2.2 style-loader:

上面css-loader只是能識別css檔案,而引入了style-loader後css樣式才能在頁面展示。

安裝:

npm i style-loader -D

配置檔案規則:

因為webpack 是 從 後 往 前 執 行,所以style-loader寫在css-loader前面。

module: {
      //數組裡每個元素為一個規則
     rules:[
        {
            test: /\.css$/,
            use: ['style-loader','css-loader']
        }
     ]
  }

2.2.3 sass-loader:

比如,我想 webpack 能打包scss檔案型別。不會sass的可以看這篇文章文章sass全解析。

安裝sass:

npm i sass -D

轉換scss為css(注意在scss同級路徑下轉換,也是終端輸入):

sass index.scss:ouput.css

在入口檔案index.js匯入:

import './css/ouput.css'

安裝sass-loader:

npm i sass-loader -D

配置規則:

 //定義一些規則
  module: {
      //數組裡每個元素為一個規則
     rules:[
        {
            test: /\.css$/,
            use: ['style-loader','css-loader']
        },
         {
            test: /\.scss$/,
            use: ['style-loader','css-loader']
        }
     ]
  }

打包:

webpack

2.3 browserslist:

Webpack 支援所有符合 ES5 標準 的瀏覽器(不支援 IE8 及以下版本)。如果你想要支援舊版本瀏覽器,那就需要藉助到一些工具了。在安裝webpack時預設安裝了browserslist,它可以知道各個瀏覽器的佔有率資料並配置。

這個網站也可以查到目前各個瀏覽器的佔有率資料。後面再詳細講。

2.4 postcss-loader處理css相容:

postcss是JavaScript轉換樣式的工具,這個工具能處理css相容問題。就是這個工具能給我們寫的css程式碼新增一些相容的字首。

首先,你可以通過 這個網站 瞭解css是新增什麼字首怎麼能相容主流瀏覽器的。

安裝:

npm i postcss-loader -D
npm i autoprefixer -D

配置檔案:

在css檔案型別裡新增postcss-loader,並配置引數 :

  {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader',
                //新增postcss-loader
                {
                    loader:'postcss-loader',
                    //配置引數
                    options:{
                       postcssOptions:{
                           //新增外掛autoprefixer,能加字首
                           plugins:[
                               require('autoprefixer')
                           ]
                       }
                    }
                }
            ]
        },

在index.js同級下新建一個名為.browserslistrc 檔案,裡面寫相容的條件,如:

> 0.1%
last 2 version
not dead

然後終端輸入webpack打包後css程式碼會自動新增相容程式碼。

上面只是新增字首,如果還需要更強的相容需要 postcss-preset-env, 安裝:

npm i  postcss-preset-env -D

新增配置(來次全的):

const path = require('path');
module.exports = {
  //打包入口檔案路徑
  entry: './src/index.js',
  //path打包出口路徑,filename打包後文件名
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
  },
  //定義一些規則
  module: {
      //數組裡每個元素為一個規則
     rules:[
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader',
                //新增postcss-loader
                {
                    loader:'postcss-loader',
                    //配置引數
                    options:{
                       postcssOptions:{
                           //新增外掛autoprefixer,能加字首
                           plugins:[
                               require('autoprefixer'),
                               require('postcss-preset-env')
                           ]
                       }
                    }
                }
            ]
        },
         {
            test: /\.scss$/,
            use: ['style-loader','css-loader']
        }
     ]
  }
};

可以只保留postcss-preset-env,簡寫:

 {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader',
                //新增postcss-loader
                {
                    loader:'postcss-loader',
                    //配置引數
                    options:{
                       postcssOptions:{
                           //新增外掛autoprefixer,能加字首
                           plugins:['postcss-preset-env']
                       }
                    }
                }
            ]
        },

不過一般是在index.js同級下新建一個postcss.config.js檔案專門寫配置:

postcss.config.js檔案內容:

module.exports = {
    plugins: [
        require('postcss-preset-env')
    ]
}

然後在webpack.config.js配置檔案裡直接匯入postcss-loader就行:

 use: [
                'style-loader',
                'css-loader',
                //新增postcss-loader
                 'postcss-loader'
            ]

2.5 importLoaders:

importLoaders:用於配置「css-loader 作用於 @import 的資源之前」有多少個 loader。直白來說就是importLoaders設定幾,那麼通過@import 匯入的css檔案也會向前執行前面不再執行的loader。

如下:

 use: [
                'style-loader',
                {
                   loader:'css-loader',
                   options:{
                       importLoaders:1
                   }
                },
                 'postcss-loader'
            ]

本來一個css檔案會執行上面3個loader,如果那個css檔案存在通過import語法匯入的css檔案,那麼那個匯入的css檔案是不會執行最後的postcss-loader。但是我想執行,所以配置importLoaders,表示import匯入的css檔案也會向後執行多少個loader。(注意webpack是從後往前執行的)

2.6 file-loader處理圖片:

file-loader作用:

1.當我們把圖片當一個模組匯入的時候可以識別它。
2.可以把二進位制資源拷貝一份到指定目錄,沒指定就是預設dist目錄。

安裝:

npm i file-loader -D 

2.6.1 在js裡通過src匯入的:

可以在src目錄下新建一個img資料夾存放圖片。

配置檔案(在rules數組裡繼續新增一個規則):

 {
            test: /\.(png|svg|gif|jpe?g)$/,
            use:['file-loader']
        }
  • 第一種用法:
    當把圖片當成一個模組匯入時在末尾新增.default,比如如:
 var img = document.createElement('img');
    img.src = require('../img/1.jpg').default;
    document.body.appendChild(img);
  • 第二種用法:
    如果不想模組匯入時在末尾新增.default,那麼在配置檔案裡新增引數esModule:
{
            test: /\.(png|svg|gif|jpe?g)$/,
            use:{
                loader:'file-loader',
                options: {
                    esModule:false
                }
            }
        }
  • 第三種用法:
    如果你也不想上面這樣寫,還可以通過es6模組匯入方式:

先匯入圖片模組:

import src from '../img/1.jpg';

然後再:

  var img = document.createElement('img');
   img.src = src;
   document.body.appendChild(img);

最後終端webpack打包就行,目前會將圖片預設打包到dist目錄。

2.6.2 在css裡通過url匯入的:

跟上面src區別就是要修改的是css型別檔案規則,加一個esModule引數:

{
            test: /\.css$/,
            use: [
                'style-loader',
                {
                   loader:'css-loader',
                   options:{
                       importLoaders:1,
                       esModule:false
                   }
                },
                 'postcss-loader'
            ]
        },
          {
            test: /\.(png|svg|gif|jpe?g)$/,
            use: ['file-loader']
        }

然後在css裡通過url正常引用即可,webpack打包後會將圖片預設打包到dist目錄:

div {
  width: 200px;
  height: 200px;
  background-image: url("../img/1.jpg");
}

預設位置,如(圖片名稱自動根據內容演算法得出):

2.6.3 設定輸出位置與圖片名稱:

我們可以設定打包後的圖片存放到的地方與名稱。

修改配置檔案的圖片規則,新增一個name配置(名稱)屬性和outputpath屬性(位置):

 {
            test: /\.(png|svg|gif|jpe?g)$/,
            use: {
                loader:'file-loader',
                options:{
                    name: '[name].[hash:6].[ext]',
                    outputPath: 'img'
                }
            }
        }

其中name屬性裡表示:【ext】副檔名,【name】檔名,【hash】檔案內容。outputpath屬性:直接指定img目錄,預設會放在dist目錄下。

兩個屬性可以合併直接簡寫為:

 {
            test: /\.(png|svg|gif|jpe?g)$/,
            use: {
                loader:'file-loader',
                options:{
                    name: 'img/[name].[hash:6].[ext]',
                }
            }
        }

2.7 url-loader處理圖片:

url-loader可以將圖片轉為base64字串,能更快的載入圖片(適用圖片檔案較少情況,過大的話還是用file-loader)。file-loader相對於拷貝,速度較慢。

安裝:

npm i url-loader -D

配置其實跟file-loader差不多的,把loader那一改就行:

{
            test: /\.(png|svg|gif|jpe?g)$/,
            use: {
                loader:'url-loader',
                options:{
                    name: 'img/[name].[hash:6].[ext]',
                }
            }
        }

與file-loader不同的是,打包後圖片會以base64字串形式載入到程式碼裡,所以目錄裡不再可見:

關鍵的是,其實 url-loader 包含 file-loader ,可以設定一個 limit 屬性,當圖片大小超過limit,url-loader會自認不行,會主動去呼叫file-loader去執行。

如下:設定一個筏值20kb,小於它會執行url-loader,大於它會執行file-loader

 {
            test: /\.(png|svg|gif|jpe?g)$/,
            use: {
                loader:'url-loader',
                options:{
                    name: 'img/[name].[hash:6].[ext]',
                    limit: 20*1024
                }
            }
        }

2.8 asset處理圖片:

webpack5之後可以直接使用asset處理圖片,不必再配置file-loader或url-loader。能更好的簡化使用。且它是webpack5內建模組,不必額外進行安裝其它東西。

配置檔案修改圖片規則:

1、預設情況,拷貝圖片,預設放到dist目錄下(跟file-loader沒配置名稱和路徑時結果一樣):

 {
            test: /\.(png|svg|gif|jpe?g)$/,
            type: 'asset/resource'
        }

2、指定圖片打包後位置,放到dist下的img資料夾裡,圖片規則跟上面一樣,要修改的是output打包出口路徑那裡,新增assetModuleFilename:

//path打包出口路徑,filename打包後文件名
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
    assetModuleFilename:'img/[name].[hash:6][ext]'
  },
    {
            test: /\.(png|svg|gif|jpe?g)$/,
            type: 'asset/resource'
        }

3、上面相當於全域性配置,不論什麼圖片都會執行,所以不大好,所以還是在規則裡面加圖片輸出位置與名稱好點,新增generator,裡面的filename寫位置與名稱:

 {
            test: /\.(png|svg|gif|jpe?g)$/,
            type: 'asset/resource',
            generator:{
                filename:'img/[name].[hash:6][ext]'
            }
        }

4、如果想將圖片轉為base64字串,而不是拷貝的話,修改規則如下:

   {
        test: /\.(png|svg|gif|jpe?g)$/,
        type: 'asset/inline',
    }  

5、當然,也能像url-loader設定limit那樣設定一個閥值,超過後還是用拷貝,修改規則如下,maxSize設定大小,這裡閥值為30kb大小:

   {
            test: /\.(png|svg|gif|jpe?g)$/,
            type: 'asset',
            generator:{
                filename:'img/[name].[hash:6][ext]'
            },
            parser:{
                dataUrlCondition: {
                    maxSize: 30*1024
                }
            }
        }

2.9 asset處理字型圖示:

新增如下規則:

 // 字型圖示
        {
            test: /\.(ttf|woff2?)$/,
            type:'asset/resource',
            generator:{
                filename:'font/[name].[hash:3][ext]'
            },
        }

2.10 webpack外掛使用:

眾所周知,外掛能幫助我們更方便的做更多的事情。

2.10.1 dist目錄自動清空外掛:

每次我們重新webpack打包的時候還要把上次打包的dist目錄刪除掉,麻煩,所以這裡下載一個dist目錄自動清空外掛。以後打包會預設把上次打包內容清空後打包。

安裝clean-webpack-plugin外掛:

npm i clean-webpack-plugin -D

設定配置檔案的配置項plugins:

const path = require('path');
// 1.先匯入下載的外掛
const {CleanWebpackPlugin} = require('clean-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
  },
  module: {。。。},
  //2.定義外掛配置的屬性 plugins ,存放每個外掛
  plugins: [
      //3.每個外掛都是一個類,直接new就行
      new CleanWebpackPlugin()
  ]
};

每個外掛都是一個類,直接new就行,可以檢視對應外掛的官網,瞭解傳的引數對應什麼功能。

2.10.2 html-webpack-plugin外掛:

能幫我們打包後在打包目錄裡生成一個html檔案模板,並引用入口檔案。

安裝html-webpack-plugin外掛:

npm i html-webpack-plugin -D

設定配置檔案的配置項plugins:

const path = require('path');

const {CleanWebpackPlugin} = require('clean-webpack-plugin');
// 1.先匯入下載的外掛
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
  },
  module: {。。。},
  plugins: [
      new CleanWebpackPlugin(),
    // 2.新增
     new HtmlWebpackPlugin()
  ]
};

webpack打包後:

html預設內容:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Webpack App</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <script defer="defer" src="build.js"></script>
  </head>
  <body></body>
</html>

對於html很多地方可以設定的,比如title的內容啥的,在配置檔案new的時候傳遞對應引數就行(具體參考該外掛官網):

。。。略
plugins: [
      new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
          title:'北極光之夜。'
      })
  ]

打包後生成的html檔案內容:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>北極光之夜。</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <script defer="defer" src="build.js"></script>
  </head>
  <body></body>
</html>

當然,可以自己提供一個html模板,以我提供的模板為基礎生成新的html模板:

1、在src同級下新建一個public目錄,在裡面新建一個index.html檔案作為模板:

2、比如index.html內容如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div class="app" id="app">test</div>
  </body>
</html>

<%= htmlWebpackPlugin.options.title %>表示使用配置裡的title。

3、新增template引數,值為模板路徑:

  new HtmlWebpackPlugin({
          title:'北極光之夜。',
          template:'./public/index.html'
      })

4、打包結果:

2.11 babel-loader處理js相容:

能處理js相容問題,比如相容es6語法。

安裝:

npm i @babel/core -D
npm i babel-loader -D

在index.js同級下新建一個babel.config.js檔案專門寫配置:

babel.config.js檔案內容:

 module.exports = {
    presets: ['@babel/preset-env']
}

然後在webpack.config.js配置檔案裡新增規則:

  {
            test:/\.js$/,
            use:['babel-loader']
        }

跟在前面說到的postcss-loader一樣,同樣在.browserslistrc 檔案裡面寫相容的條件,如:

0.1%
last 2 version
not dead

最後webpack打包就行了。

2.12 polyfill處理js相容:

babel-loader處理的js相容還不夠多,只能處理簡單的,若存在promise這些新語法也不大行。所以需要polyfill。

安裝:

npm i @babel/polyfill --save

修改babel.config.js:

module.exports = {
    presets: [
        '@babel/preset-env',
        {
            useBuiltIns: 'entry',
            crorejs: 3
        }
    ]
}

2.13 自動更新:

可以實現你修改原始碼後,打包後的程式碼也自動更新,不用每次都手動打包去更新。

1、不使用webpack-dev-serve之前,可以在配置檔案新增watch屬性為true也能實現自動更新,但是效能不太好,不能區域性更新,是一有更新就全都更新:

如:

module.exports = {
//  這裡,自動更新
    watch: true,
  //打包入口檔案路徑
  entry: './src/index.js',
  //path打包出口路徑,filename打包後文件名
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
    //assetModuleFilename:'img/[name].[hash:6][ext]'
  },
  。。。略
}  

2、webpack-dev-serve效能較好,能實現區域性更新,節省效能。

在終端先安裝:

npm install webpack-dev-server --save-dev

以後打包命令改為:

webpack serve

2.14 HMR模組熱替換:

作用:一個模組發生變化,只會重新打包這一個模組(而不是打包所有模組),極大的提升構建速度。

先配置:

module.exports = {
  target: 'web',
  // 開啟HMR
  devServer:{
      hot: true
  }
  。。。
}

然後在入口檔案處通過判斷給需要熱更新的模組熱更新:

import './title'
if(module.hot){
  module.not.accept(['./title.js'])
}

2.15 output的path:

output有一個publicPath屬性,為專案中引用 css,js,img 等資源時候的一個基礎路徑。其輸出解析檔案的目錄,指定資原始檔引用的目錄 ,打包後瀏覽器訪問服務時的 url 路徑中通用的一部分。

 output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'build.js',
    publicPath:''
  },

2.16 devServer常用配置:

 devServer:{
      hot: true
      hotOnly:true,
      //預設埠
      port:4000
      //自動開啟瀏覽器
      open:false
      //開啟服務端壓縮
      compress: true
      //使用 History 路由模式時,若404錯誤時被替代為 index.html
      historyApiFallback: true
  } 

2.17 proxy代理:

通過webpack設定代理解決瀏覽器跨域問題。在 devServer 下新增一個 proxy 屬性:

devServer:{
    ....
      proxy: {
        //定義一個標記,如以後api開頭的請求都走代理的設定
          '/api': {
             // 要請求的真實服務端基地址 相當於被/api替代了
             target: 'https://...',
            //把api重寫為空,因為別人沒有 /api
             pathRewrite: {"^/api":""},
             //傳送請求頭中host會設定成target
             changeOrigin: true
          }
      }
  } 

此時,如果我們原本想請求的服務端地址為 https://… /user 就可以替換成 /api/user , 然後把/api重寫為空,那麼實際上就是相當於寫了 https://… /user, 如:

axios.get('/api/user').then(res=>{...})

2.18 mode模式:

提供 mode 配置選項,告知 webpack 使用相應模式的一些內建優化。如果沒有設定,webpack 會給 mode 的預設值設定為 production。

string = 'production': 'none' | 'development' | 'production'
module.exports = {
  mode: 'development',
};

2.19 打包vue檔案:

1.安裝:

$ cnpm i vue-loader vue-template-compiler -D

2.新增規則:

 {
            test:/\.vue$/,
            use:['vue-loader']
        }

3.匯入外掛並使用:

const VueLoaderPlugin = require('vue-loader/lib/plugin');

未完結,持續更新中。。。

點選關注,第一時間瞭解華為雲新鮮技術~