banner
cos

cos

愿热情永存,愿热爱不灭,愿生活无憾
github
tg_channel
bilibili

青訓營 |「構建Webpack知識體系」

本節課重點內容#

  • 理解前端 "工程化" 概念、工具、目標
  • 一個團隊總要有那麼幾個人熟悉 Webpack, 某種程度上可以成為個人的核心競爭力
  • 高階前端必經之路

課程目標:

  • 理解 Webpack 的基本用法
  • 通過介紹 Webpack 功能、Loader 與 Plugin 組件設計,建立一個知識體系
  • 不會事無巨細,介紹 Webpack 所有
  • 也不是深入源碼,講解底層實現原理

什麼是 Webpack#

前端項目由什麼構成?—— 資源

image.png

舊時代手動管理這些資源,但有以下幾個對開發效率影響非常大的缺點:

  • 依賴手工,比如有 50 個 JS 文件……操作過程繁瑣
  • 當代碼文件之間有依賴的時候,就得嚴格按依賴順序書寫
  • 開發與生產環境一致,難以接入 TS 或 JS 新特性
  • 比較難接入 Less、Sass 等工具
  • JS、 圖片、CSS 資源管理模型不一致

後來,出現了很多前端工程化工具,特別是 Webpack

image.png

Web 本質上是一種前端資源編譯打包工具

  • 多份資源文件打包成一個 Bundle
  • 支持
    • Babel、Eslint、 TS、 CoffeScript、Less、 Sass
  • 支持模塊化處理 css、圖片等資源文件
  • 支持 HMR + 開發服務器
  • 支持持續監聽持續構建
  • 支持代碼分離
  • 支持 Tree-shaking
  • 支持 Sourcemap
  • ...

Webpack 打包核心流程#

示例#

  1. 安裝(注意用管理員權限打開命令行)

    npm i -D webpack webpack-cli
    

    image.png

  2. 編輯配置文件 webpack.config.js

    module.exports = {
        entry: 'main.js',   // 定義目前項目的入口文件
        output: {   // 定義目前項目的輸出文件
            filename: "[name].js",
            path: path.join(__dirname, "./dist"),
        },
        module: {// 定義一些loader相關的內容,可在下文看到
            rules: [{
                test: /\.less$/i,
                use: ['style-loader', 'css-loader', 'less-loader']
            }]
        }
    }
    
  3. 執行編譯命令

    npx webpack
    

步驟#

Entry => Dependencies Lookup => Transform => Bundle => Output

極度簡化版:

image.png

  1. 從 entry 中的入口文件開始啟動編譯
  2. 依賴解析:根據require 或者 import 等語句找到依賴資源
  3. 根據module 配置,調用資源轉移器將非 JS 資源編譯為 JS 內容,直至所有資源處理完畢
  4. 資源合併打包:將轉譯後的資源內容合併打包為可直接在瀏覽器運行的 JS 文件

模塊化 + 一致性

  • 多個文件資源合併成一個,減少 http 請求數
  • 支持模塊化開發
  • 支持高級 JS 特性
  • 支持 Typescript、 CoffeeScript 方言
  • 統一圖片、CSS、字體等其他資源的處理模型
  • Etc...

關鍵配置項(如何使用?)#

關於 Webpack 的使用方法,基本都圍繞 配置 展開,而這些配置大致可劃分為兩類:

  • 流程類:作用於流程中某個或若干個環節,直接影響打包效果的配置項
  • 工具類:主流程之外,提供更多工程化能力的配置項

ps:官網文檔確實,看不太懂()

配置總覽:

image.png

按使用頻率,主要有以下幾大配置項

  • entry/output—— 程序輸入輸出,必需的

  • module/plugins

    • 如圖,比如我這個項目需要加載 less 文件,需要導入以下 loader 等

      image.png

  • mode

  • watch/devServer/devtool

Webpack 配置官方文檔

使用 Webpack 處理 CSS/less 等#

  1. 安裝 Loader

    npm add -D css-loader style-loader
    
  2. 添加 module 處理 css 文件

image.png

思考題#

  • Loader 有什麼作用?為什麼這裡需要用到 css-loader、style-loader
  • 與舊時代,在 HTML 文件中維護 CSS 相比,這種方式會有什麼優劣處?
  • 有沒有接觸過 Less、Sass、 Stylus 這一類 CSS 預編譯框架?如何在 Webpack 接入這些工具?
    • 答:接觸過 less

參考資料:

使用 Webpack 接入 Babel#

  1. 安裝依賴

    npm -D @babel/core @babel/preset-env babel-loader
    
  2. 聲明入口 entry & 產物出口output

  3. 添加 module 處理 css 文件

    module:{
        rules:[
        {
            test:/\.js?$/,
            use:[{
                loader: 'babel-loader',
                options: {
                    presets: [
                        [
                            '@babel/preset-env'
                        ]
                    }
                }
            }]
        }
    ]
    }
    
  4. 執行 npx webpack

思考題#

  • Babel 具體有什麼功能
  • Babel 與 Webpack 分別解決了什麼問題?為何兩者能協作到一起了?

參考資料:

使用 Webpack 生成 html#

  1. 安裝依賴

    npm i -D html-webpack-plugin
    
  2. 配置

const path = require( "path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
   entry: "./src/index",
   output: {
       filename:" [name]. js",
       path: path.join(__dirname, "./dist"),
   },
   plugins: [new HtmlWebpackPlugin()]
};
  1. 執行npx webpack

思考題#

  • 相比於手工維護 HTML 內容,這種自動生成的方式有什麼優缺點?

參考資料:

使用 Webpack——HMR#

Hot Module Replacement—— 模塊熱替換(寫的代碼會被立刻更新到瀏覽器上~)

  1. 開啟 HMR

    module.exports={
    	// ...
    	devServer: {
            hot:true; // 必需
        }
    };
    
  2. 啟動 webpack

原理可參考:Webpack 原理系列十:HMR 原理全解析 (qq.com)

使用 Webpack——Tree-Shaking#

Tree-Shaking - 樹搖,用於刪除Dead Code

Dead Code

  • 代碼沒有被用到,不可到達
  • 代碼的執行結果不會被用到
  • 代碼只讀不寫

Tree-Shaking

  • 模塊導出了,但未被其他模塊使用

開啟步驟?

  • mode: "production"
  • optimization: {usedExports: true}
  module.exports = {
  	entry: "./src/ index",
  	mode: "production",
  	devtool: false,
  	optimization: {
  		usedExports: true, 
  	},
  };

ps:對工具類庫如 Lodash 有奇效,能大大減小產物體積

其他工具#

  • 緩存
  • Sourcemap (前面的課程中有提過)
  • 性能監控
  • 日誌
  • 代碼壓縮
  • 分包
  • ...

思考題#

  • 除上面提到的內容,還有哪些配置可劃分為 “流程類” 配置?
  • 工具類配置具體有什麼作用?包括 devtool/cache/stat 等

理解 Loader#

Loader 核心功能:將非 JS 資源轉換為 JS 資源

  1. 安裝 Loader

    npm add -D css-loader style-loader less-loader
    
  2. 添加 module 處理 less 文件

module.exports = { 
    module: {
        rules: [
            {
                test: /\.less$/i,
                use:[
                    "style-loader",
                    "css-loader",
                    "less-loader"
                ],
            },
        ],
    },
};

認識 Loader:鏈式調用#

  • less-loader: 實現less => css 的轉換
  • css-loader: 實現css => js 的轉換,將 CSS 包裝成類似 module.exports = "${css}" 的內容,包裝後的內容符合 JavaScript 語法
  • style-loader將 css 模塊包進 require 語句,並在運行時調用injectStyle等函數將內容注入到頁面的 style 標籤

image.png

認識 Loader:其他特性#

特點

image.png

module.exports = function(source, sourceMap?, data?) {
	// source 為loader的輸入
	//可能是文件內容,也可能是上個loader處理結果
	return source;
};

常用 Loader#

  • 站在使用角度,建議掌握這些常見 Loader 的功能、配置方法

image.png

思考題#

  • Loader 輸入是什麼?要求的輸出是什麼?
  • Loader 的鏈式調用是什麼意思?如何串聯多個 Loader?
  • Loader 中如何處理異步場景?要拋一個異常的話要怎麼拋

理解插件 Plugin#

什麼是插件#

  • 很多知名工具,如:
    • VS Code、Web Storm、Chrome、Firefox
    • Babel、Webpack、 Rollup、 Eslint
    • Vue、Redux、 Quill、 Axios
  • 等等,都設計了所謂 " 插件” 架構,為什麼?

插件可以提升整個應用的拓展性

假設一個應用沒有任何插件,整個就是特別複雜的過程,那麼:

  • 新人需要了解整個流程細節,上手成本高
  • 功能迭代成本高,牽一發動全身
  • 功能僵化,作為開源項目而言缺乏成長性

心智成本高 => 可維護性低 => 生命力弱
插件架構精髓:對擴展開放,對修改封閉,其實就是開閉原則

image.png

甚至,Webpack 本身的很多功能也是基於插件實現的

image.png

如何編寫插件#

首先:插件圍繞 鉤子 展開

class SomePlugin {
    apply(compile) {
    	compiler.hooks.thisCompilation.tap('SomePlugin', (compilation) => {
    	})
    }
}

鉤子#

  1. 時機:編譯過程的特定節點,Webpack 會以鉤子形式通知插件此刻正在發生什麼事情

  2. 上下文:通過 tapable 提供的回調機制,以參數方式傳遞上下文信息;

  3. 交互:在上下文參數對象中附帶了很多存在 side effect 的交互接口,插件可以通過這些接口改變

    image.png

    時機:compier.hooks.compilation

    參數:compilation 等

    交互:dependencyFactories.set

思考題#

  • Loader 與插件有什麼區同點?
  • " 鉤子 “有什麼作用?如何監聽鉤子函數?

參考資料:

如何學習 Webpack#

入門級:學會靈活應用#

  • 理解打包流程
  • 熟練掌握常用配置項、Loader、 插件的使用方法,能夠靈活搭建集成 Vue、React、 Babel、 Eslint、 Less、 Sass、 圖片處理等工具的 Webpack 環境
  • 掌握常見腳手架工具的用法,例如: Vue-cli、 create-react- app、@angular/cli

image.png

進階:學會擴展 Webpack#

  • 理解 Loader、 Plugin 機制,能夠自行開發 Webpack 組件
  • 理解常見性能優化手段,並能用於解決實際問題
  • 理解前端工程化概念生態現狀

大師:源碼級理解 Webpack 打包編譯原理#

  • 閱讀源碼,理解 Webpack 編譯、打包原理,甚至能夠參與共建

總結感想#

這節課詳細講了 Webpack 的 Webpack 的作用、配置結構及其關鍵配置項,還講了 Loader 中的鏈式調用、插件的實現原理與一些其他特性等,可以看出老師對 Webpack 的研究非常詳細透徹,課上都是直接進行調試進入 loader 內部等幫助我們理解。老師還總結了 Webpack 知識體系:Webpack 5 知識體系 - GitMind

Q&A#

Q:面試要掌握到什麼程度

A:網上很多面試主要圍繞三種主題

  • Loader 有什麼作用?怎麼寫 loader?常用 loader 有哪些
    • 常用 loader:css-loader、style-loader、vue-loader、file-loader、eslint-loader、babel-loader 等
  • 插件有什麼用?怎麼寫插件?編譯原理?
  • Bundle、chunk、module 分別是什麼含義?

一些資源:深入淺出 Webpack

本文引用的大部分內容來自范文杰老師的課,歡迎關注老師的公眾號:Tecvan

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。