天天看點

webpack 4.x的特性與使用

webpack 4.x

的特性

  • webpack 4.x

    有個很大的特性,就是約定大于配置,目的是為了減少配置檔案的體積;
    • 約定預設的打包入口路徑是

      src/index.js

    • 約定預設的打包輸出路徑是

      dist/main.js

      • 是以說現在的項目中,可以不用特地去配置入口和出口路徑,隻需要在指定的目錄下建立對應的

        js

        檔案即可。
  • webpack 4.x

    将CLI(指令行工具)已經轉移到了一個單獨的包

    webpack-cli

    ,是以使用webpack需要

    npm install webpack webpack-cli -D

wepack 4.x

的幾個基本子產品

子產品

  • 通過将

    mode

    參數設定為

    development

    ,

    production

    ,可以啟用對應環境下 webpack 内置的優化。預設值為

    production

    • development

      :生産環境,不壓縮;
    • production

      :部署環境,需要壓縮;

入口

entry

  • 入口起點(entry point)訓示 webpack 應該使用哪個子產品,來作為建構其内部依賴圖的開始,webpack 會找出有哪些子產品和 library 是入口起點(直接和間接)依賴的;
  • 預設值是

    ./src/index.js

  • 可以手動設定;
module.exports = {
  entry: './path/to/my/entry/file.js'
};
           

出口

output

  • output

    屬性告訴 webpack 在哪裡輸出它所建立的 bundles,以及如何命名這些檔案,主輸出檔案預設為 ./dist/main.js,其他生成檔案的預設輸出目錄是

    ./dist

const path = require('path');
module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'), // 絕對路徑
    filename: 'my-first-webpack.bundle.js' // 輸出的js檔案名
  }
};
           

loader

  • 由于

    webpack

    自身隻支援

    js

    檔案,是以當解析其他檔案時,需要使用

    loader

    來讓

    webpack

    去處理那些非

    javascript

    檔案,并且先将他們轉換為有效的子產品,然後在添加到依賴圖中;
  • webpack

    中配置

    loader

    必須有兩個特征:
    • test

      屬性,用于辨別出應該被對應的

      loader

      進行轉換的某個檔案;
    • use

      屬性,表示進行轉換時,應該使用哪個

      loader

  • 注:
    • 對一個單獨的

      module

      對象定義了

      rules

      屬性,裡面包含兩個必須屬性:

      test

      use

    • 在 webpack 配置中定義

      loader

      時,要定義在

      module.rules

      中,而不是

      rules

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  }
};
           

babel-loader

  • 将ES6轉成 ES5
  • npm install -D babel-loader @babel/core @babel/preset-env webpack

    ;
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'] // 與ES6相關的bebal
          presets: ["@babel/preset-flow"] // flow 相關的babel,需要 install
          // ...
        }
      }
    }
  ]
}
           

css-loader & style-loader & less-loader...

  • 支援css以及less,sass等
  • npm install css-loader style-loader less less-loader -D

  • 需要注意的是:webpack中的loader的執行順序是從右到左的,也就是說先執行的

    css-loader

    ,然後将解析後的資料傳遞(webpack支援鍊式操作)給

    style-loader

    ,如果将兩者的執行順序寫錯了,則會執行失敗。
  • 同時需要注意的是:當需要将css單獨抽離成一個檔案,比如添加

    mini-css-extract-plugin

    時,此時再使用

    style-loader

    ,兩者是有沖突的。
{
  test: /\.css$/,
  use: [ 
    'style-loader', // 将解析後的css放在head中的style下
    'css-loader', // 解析css
  ]
}
// ----------- 分割線 -------------
{
  test: /\.less$/,
  use: [ 
    'style-loader', // 将解析後的css放在head中的style下
    'css-loader', // 解析css
    'less-loader', // 解析less
  ]
}
           

插件

plugins

  • loader 被用于轉換某些類型的子產品,而插件則可以用于執行範圍更廣的任務,插件的範圍包括:打包優化、資源管理和注入環境變量。
  • 想要使用一個插件,你隻需要 require(),然後把它添加到 plugins 數組中。多數插件可以通過選項(option)自定義。你也可以在一個配置檔案中,先定義一個執行個體對象,因為不同目的而多次使用同一個插件,這時需要通過使用 new 操作符來建立它的一個執行個體。
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通過 npm 安裝
const webpack = require('webpack'); // 用于通路内置插件
module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'}) // 打包生成的js檔案,将運作在最基本的html模闆中
  ]
};
           
  • 其中

    html-webpack-plugin

    會為你的應用程式生成一個 html 檔案,然後自動注入所有生成的 bundle.js。

常用的plugins

  • CommonsChunksPlugin

    : 将chuks相通的子產品代碼提去成公共js;
  • CleanWebpackPlugin

    : 清理建構目錄;
  • ExtractTextWebpackPlugin

    : 将css從bundle檔案中提去出來;
  • CopyWebpackPlugin

    : 将檔案或者檔案夾拷貝到建構的輸出目錄;
  • HtmlWebpackPlugin

    : 建立html檔案去接受數除的bundle;
  • UglifyjsWebpackPlugin

    : 壓縮js(webpack4.x mode=production已經開啟);
  • ZipWebpackPlugin

    : 将打包出的資源生成一個zip包;

配置

resolve

resolve: {
  extensions: ['.js','.jsx','.json','.css','.less']  // 表示這些檔案的字尾名,忽略不計;
  alias: {
      '@': path.join(__dirname,'./src')  //這樣,在項目中,`@`就表示項目根目錄src的這一層路徑;
  }
}
           

檔案監聽

watch

  • 檔案監聽是發現源碼發生變化時,自動重新建構出新得輸出檔案;
  • 缺陷:我們必須手動重新整理頁面;
  • 開啟監聽模式有兩種方式:
  1. 啟動webpack指令式,帶上

    --watch

    參數;
  1. 在配置

    webpack.config.js

    中設定 watch: true
module.exports = {
  watch: true, // 預設false
  watchOptions: { // 隻有開啟監聽模式時,watchOptions才有意義
    ignored: /node_modules/, // 不監聽的檔案,支援正則
    aggregateTimeout: 300, // 監聽到變化發生後,等300ms再去執行,預設 300ms
    poll: 1000 // 判斷檔案是否發生變化,是通過輪詢的方式去實作的,預設每秒問1000次
  }
}
           

webpack-dev-serve

  • 熱更新
  • npm install --save-dev webpack-dev-server

  • 需要去

    package.json

    下的

    scripts

    中:
  • 增加内容為:

    "dev":"webpack-dev-server --open --port 3000 --hot"

    • --open

      :表示自動打開浏覽器
    • --hot

      :實作熱重新整理
    • --port 3000

      :改變端口号
    • --progress

      :打包進度
    • --compress

      :壓縮
    • 此時:啟動的項目打包後的

      main.js

      是在項目的根路徑下,是在虛拟磁盤下,不是實體磁盤;
devServer:{
  contentBase: './dist', 
  hot: true // 開啟熱更新
},
           

檔案指紋(Hash)

  • 一般用來做版本管理;

Hash:

  • 和整個項目的建構相關,隻要項目檔案有修改,整個項目建構的 hash 值就會更改;

Chunkhash:

  • 和 webpack 打包的

    chunk

    有關,不同的

    entry

    會生成不同的

    chunkhash

    值;
  • 一般 js 檔案使用這塊比較多,這裡我們隻需要設定

    output

    即可
output: {
  filename: '[name][chunkhash:8].js',
  path: __dirname+ './dist'
},
           

Contenthash:

  • 根據檔案内容來定義

    hash

    ,檔案内容不變,則

    contenthash

    不變;
  • 一般

    css

    檔案使用這個 Contenthash 比較多,需要将css 單獨抽離成檔案的情況下使用;
{
  test: /\.less$/,
  use: [ 
    MiniCssExtractPlugin.loader, // 此時與style-loader功能互斥
    'css-loader', // 解析css
    'less-loader', // 解析less
  ]
},

plugins: [
  new MiniCssExtractPlugin({
    filename: '[name][contenthash:8].css'
  })
]
           

其他内容

postcss-loader & Autoprefixing

  • 為 css3 屬性加上字首
  • npm install postcss-loader autoprefixer -D

module: {
  rules: [
    {
      text: /\.less$/,
      use: [
        'css-loader',
        'less-loader',
        {
          loader: 'postcss-loader',
          options: {
            plugins: [
              require('autoprefixer)({
                browsers: [ // 相容浏覽器版本
                  'last 2 version', // 浏覽器最近的版本
                  '>1%', // 版本使用人數大于 1%
                  'IE 10', // IE 10 以上
                  // ....
                ]
              })
            ]
          }
        }
      ]
    }
  ]
}

           

px

rem

  • px2rem-loader

    :将 px 轉換成 rem;
    • npm install lib-flexible -S

    • width: 75px

      :這種寫法會将 px 轉換成 rem
    • 在px後面添加/no/,不會轉化px,會原樣輸出。 — 一般border需用這個
    • 在px後面添加/px/,會根據dpr的不同,生成三套代碼。---- 一般字型需用這個
  • lib-flexible;:手淘适配方案
    • npm install px2rem-loader -D

module: {
  rules: [
    {
      text: /\.less$/,
      use: [
        'css-loader',
        'less-loader',
        {
          loader: 'px2rem-loader',
          options: {
            remUnit: 75, // rem 相對于 px的轉換機關,此時 1 rem = 75px
            remPrecision: 8 // px 轉換成小數點的長度
          }
        }
      ]
    }
  ]
}
           
  • index.html

    中建立

    script

    标簽,手動的将

    lib-flexible/flexible.js

    中的内容拷貝進去,因為這塊需要初始化就要使用。

靜态資源的内聯:

raw-loader

  • 代碼層面的意義:
    • 頁面架構的初始化腳本,比如移動端适配,腳本就需要在加載頁面之前執行
    • css内聯避免頁面閃動
  • 請求層面的意義:減少 HTTP 請求數量
    • 小圖檔或者字型内聯(url-loader)
  • npm install raw-loader -D

<!-- 以上一個移動端适配需要内聯到 html 中為例 -->
<!DOCTYPE html>
<html >
<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>Wepack_Demo</title>
  <!-- 因為使用了 html-webpack-plugin,預設使用 EJS模闆引擎,是以可以直接使用 ${ } -->
  /***
  * 為什麼加上 babel-loader:因為内聯的腳本,裡面可能使用了 ES6 文法,是以需要使用 babel-loader 轉換
  */
  <script>${ require('rwa-loader!babel-loader!../../node_modules.lib-flexible/flexible.js') }</script>
</head>
<body>
  <div class="root"></div>
</body>
</html>

           

繼續閱讀