webpack打包原理解析

一庆亡、什么是 webpack

webpack 是一個模塊打包機匾乓,將根據(jù)文件間的依賴關(guān)系對其進行靜態(tài)分析,然后將這些模塊按指定規(guī)則生成靜態(tài)資源

當 webpack 處理程序時又谋,它會遞歸地構(gòu)建一個依賴關(guān)系圖(dependency graph)拼缝,其中包含應(yīng)用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle

  • 主要承擔如下功能:

    • 打包:將多個文件 打包成 一個文件搂根,減少服務(wù)器壓力和下載帶寬

    • 轉(zhuǎn)換:將預(yù)編譯語言 轉(zhuǎn)換成 瀏覽器識別的語言

    • 優(yōu)化:性能優(yōu)化

  • webpack 特點:

    • 代碼拆分

      webpack 有兩種組織模塊的依賴方式珍促,同步、異步

      異步依賴將作為分割點剩愧,形成一個新的塊;在優(yōu)化了依賴樹之后娇斩,每一個異步區(qū)塊都將作為一個文件被打包

    • 智能解析

      webpack 有一個智能解析器仁卷,幾乎可以處理任何第三方庫

      無論它們的模塊形式是 CommonJS、 AMD 還是普通的 JS 文件犬第;甚至在加載依賴的時候锦积,允許使用動態(tài)表達式 require("./templates/" + name + ".jade")

    • 快速運行

      webpack 使用異步 I/O 、多級緩存提高運行效率歉嗓,使得 webpack 以難以令人置信的速度 快速增量編譯

  • webpack 官網(wǎng)

二丰介、安裝

  • 全局安裝

    sudo npm i webpack -g
    
  • 局部安裝

    // 在已經(jīng) npm 初始化的項目 根目錄執(zhí)行
    
    npm i webpack -D
    
  • 提醒:webpack4.x 版本需要額外安裝 webpack-cli

    // 以下為局部安裝方式,全局安裝同上
    npm i webpack-cli -D
    

三鉴分、模塊交互 runtime哮幢、manifest

  • 在使用 webpack 構(gòu)建的典型應(yīng)用程序或站點中,有三種主要的代碼類型:

    • 你或你的團隊編寫的源碼志珍。

    • 你的源碼會依賴的任何第三方的 library 或 "vendor" 代碼橙垢。

    • webpack 的 runtime 和 manifest,管理所有模塊的交互

  • 下面 闡述 runtime

    runtime 包含:在模塊交互時伦糯,連接模塊所需的加載和解析邏輯柜某;包括瀏覽器中的已加載模塊的連接嗽元,以及懶加載模塊的執(zhí)行邏輯

  • 下面 闡述 manifest

    當編譯器(compiler)開始執(zhí)行、解析喂击、映射應(yīng)用程序時剂癌,它會保留所有模塊的詳細要點,這個數(shù)據(jù)集合稱為 "Manifest"

    當完成打包并發(fā)送到瀏覽器時翰绊,會在運行時通過 manifest 來解析珍手、加載模塊

  • runtime 和 manifest 管理模塊的交互

    在瀏覽器運行時,runtime 和 manifest 用來連接模塊化的應(yīng)用程序的所有代碼

    無論你選擇哪種模塊語法辞做,那些 import 或 require 語句現(xiàn)在都已經(jīng)轉(zhuǎn)換為 __webpack_require__ 方法琳要,此方法指向模塊標識符(module identifier)

    通過使用 manifest 中的數(shù)據(jù)(每個模塊的詳細要點:映射、依賴等)秤茅,runtime 將能夠查詢模塊標識符稚补,檢索出背后對應(yīng)的模塊

四、核心概念:入口 entry

  • 作用

    告訴 webpack 從哪個文件開始構(gòu)建框喳,這個文件將作為 webpack 依賴關(guān)系圖的起點

  • 配置 單入口

    // webpack 配置
    
    module.exports = {
      entry: './path/to/my/entry/file.js'
    };
    
    // webpack 配置
    
    module.exports = {
      entry: {
        main: './src/main.js'
      }
    };
    
  • 配置 多入口

    // 場景一:分離 應(yīng)用程序(app) 和 第三方庫(vendor) 入口
    // webpack 配置
    
    module.exports = {
      entry: {
        app: './src/app.js',
        vendors: './src/vendors.js'
      }
    };
    
    // 場景二:多頁面應(yīng)用程序课幕,告訴 webpack 需要 3 個獨立分離的依賴圖
    // webpack 配置
    
    module.exports = {
      entry: {
        pageOne: './src/pageOne/index.js',
        pageTwo: './src/pageTwo/index.js',
        pageThree: './src/pageThree/index.js'
      }
    };
    

五、核心概念:出口 output

  • 作用

    告訴 webpack 在哪里輸出 構(gòu)建后的包五垮、包的名稱 等

  • 配置 單出口

    // webpack 配置
    
    const path = require('path');
    
    module.exports = {
      entry: main: './src/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      }
    };
    
  • 配置 多出口

    // webpack 配置
    
    const path = require('path');
    
    module.exports = {
      entry: {
        app: './src/app.js',
        vendors: './src/vendors.js'
      },
      output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
      }
    }
    
  • 其他參數(shù)配置

六乍惊、核心概念:loader

  • 作用

    loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)

    loader 可以將所有類型的文件轉(zhuǎn)換為 webpack 能夠處理的有效模塊

  • loader 使用方式:配置(常用)

    // 安裝 loader
    npm install --save-dev css-loader
    
    // webpack 配置
    
    module.exports = {
      module: {
        rules: [{ 
            test: /\.css$/, 
            use: ['style-loader', 'css-loader']
        }]
      }
    };
    
    // 或
    
     module.exports = {
      module: {
        rules: [{ 
            test: /\.css$/, 
            use: ['style-loader', {
                loader: 'css-loader',
                options: {
                    modules: true
                }
            }]
        }]
      }
    };
    
  • loader 使用方式:內(nèi)聯(lián) (不常用)

    // 在項目文件中,import 語句時使用
    
    import Styles from 'style-loader!css-loader?modules!./styles.css';
    
  • loader 使用方式:CLI(不常用)

    webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
    
    // 如上 會對 .jade 文件使用 jade-loader放仗,對 .css 文件使用 style-loader 和 css-loader
    
  • loader 特性

    • 幾乎所有 loader 都 需要安裝润绎,不需要 在 webpack 配置文件中通過 require 引入

    • 逆向編譯,鏈式傳遞

    // webpack 配置
    
    module.exports = {
      module: {
        rules: [{ 
            test: /\.css$/, 
            use: ['style-loader', 'css-loader', 'postcss-loader']
        }]
      }
    };
    
    // 如上诞挨,css 文件編譯順序依次為:postcss-loader ---> css-loader ---> style-loader
    // 編譯過程中莉撇,第一個loader的值 傳遞給下一個loader,依次傳遞惶傻;最后一個loader編譯完成后棍郎,將預(yù)期值傳遞給 webpack
    

七、核心概念:plugin

  • 作用

    可以處理各種任務(wù)银室,從打包優(yōu)化和壓縮涂佃,一直到重新定義環(huán)境中的變量

  • plugin 使用

    npm i html-webpack-plugin -D
    
    // webpack 配置
    const HtmlWebpackPlugin = require('html-webpack-plugin'); 
    
    module.exports = {
      plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
      ]
    };
    
  • plugin 特性

    有些插件需要單獨安裝,有些插件是webpack內(nèi)置插件 不需要單獨安裝

    但所有的插件都 需要 在 webpack 配置文件中通過 require 引入

  • plugin 剖析:

    webpack 插件是一個具有 apply 屬性的 JavaScript 對象

    apply 屬性會被 webpack compiler 調(diào)用蜈敢,并且 compiler 對象可在整個編譯生命周期訪問

    // ConsoleLogOnBuildWebpackPlugin.js
    
    const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
    
    class ConsoleLogOnBuildWebpackPlugin {
        apply(compiler) {
            compiler.hooks.run.tap(pluginName, compilation => {
                console.log("webpack 構(gòu)建過程開始辜荠!");
            });
        }
    }
    

八、核心概念:模式 mode(webpack 4.x)

  • 作用

    告訴 webpack 使用相應(yīng)模式的內(nèi)置優(yōu)化

  • 使用

    // webpack 配置
    
    module.exports = {
      mode: 'production'
    };
    
    // CLI 參數(shù)中
    
    webpack --mode=production
    

兩種模式的區(qū)別
development :會將 process.env.NODE_ENV 的值設(shè)為 development啟用 NamedChunksPlugin 和 NamedModulesPlugin
production :會將 process.env.NODE_ENV 的值設(shè)為 production扶认。 啟用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin

  • // mode: development
    
    module.exports = {
        + mode: 'development'
        - plugins: [
        -   new webpack.NamedModulesPlugin(),
        -   new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
        - ]
    }
    
    // mode: production
    
    module.exports = {
        +  mode: 'production',
        -  plugins: [
        -    new UglifyJsPlugin(/* ... */),
        -    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
        -    new webpack.optimize.ModuleConcatenationPlugin(),
        -    new webpack.NoEmitOnErrorsPlugin()
        -  ]
    }
    
    
  • 在 webpack 中區(qū)分兩種 模式

    if(process.env.NODE_ENV === 'development'){
        //開發(fā)環(huán)境 do something
    }else{
        //生產(chǎn)環(huán)境 do something
    }
    

九侨拦、核心概念:target

  • webpack 能夠為 多種環(huán)境 或 target 構(gòu)建編譯(編譯后代碼 的運行環(huán)境)

    默認值:web

    常見值 見 API

十、核心概念:source map 定位代碼中的錯誤

  • 不同的 source map(資源映射)

    會決定 代碼中錯誤的顯示方式(打包后代碼辐宾、生成后代碼狱从、轉(zhuǎn)換過代碼膨蛮、源代碼等 詳細見

    會影響 構(gòu)建(build)、重新構(gòu)建(rebuild) 的速度

    整個 source map 作為一個單獨的文件生成季研。它為 bundle 添加了一個引用注釋敞葛,以便開發(fā)工具知道在哪里可以找到它

  • 開發(fā)環(huán)境的幾種常見的 source map

    • 以如下代碼為例,運行

      console.log('js');
      
      class A extends test {}
      
      
    • eval-source-map

      構(gòu)建速度:-- 与涡、重新構(gòu)建速度:+ 惹谐、生產(chǎn)環(huán)境:no 、顯示原始源代碼

    • cheap-eval-source-map

      構(gòu)建速度:+ 驼卖、重新構(gòu)建速度:++ 氨肌、生產(chǎn)環(huán)境:no 、轉(zhuǎn)換過的代碼(僅限行)

*   `cheap-module-eval-source-map`【推薦】

    > 構(gòu)建速度:0 酌畜、重新構(gòu)建速度:++ 怎囚、生產(chǎn)環(huán)境:no 、原始源代碼(僅限行)


    *   生產(chǎn)環(huán)境中 常見的 source map

*   以如下代碼為例桥胞,運行

    ```
    console.log('js');

    class A extends test {}
    ```

*   `none` 【推薦】

    > 構(gòu)建速度:+++ 恳守、重新構(gòu)建速度:+++ 、生產(chǎn)環(huán)境:yes 贩虾、打包后代碼


    *   **總結(jié):** 需要注意的是不同的 devtool 的設(shè)置催烘,會導(dǎo)致不同的性能差異。

        *   "eval" 具有最好的性能缎罢,但并不能幫助你轉(zhuǎn)譯代碼伊群。

        *   如果你能接受稍差一些的 mapping 質(zhì)量,可以使用 cheap-source-map 選項來提高性能

        *   使用 eval-source-map 配置進行增量編譯

        *   在大多數(shù)情況下屁使,cheap-module-eval-source-map 是最好的選擇

原文:https://juejin.im/post/5c62a137f265da2db87b87bb

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末在岂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蛮寂,更是在濱河造成了極大的恐慌,老刑警劉巖易茬,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酬蹋,死亡現(xiàn)場離奇詭異,居然都是意外死亡抽莱,警方通過查閱死者的電腦和手機范抓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來食铐,“玉大人匕垫,你說我怎么就攤上這事∨吧耄” “怎么了象泵?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵寞秃,是天一觀的道長。 經(jīng)常有香客問我偶惠,道長春寿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任忽孽,我火速辦了婚禮绑改,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘兄一。我一直安慰自己厘线,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布出革。 她就那樣靜靜地躺著造壮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蹋盆。 梳的紋絲不亂的頭發(fā)上费薄,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音栖雾,去河邊找鬼楞抡。 笑死,一個胖子當著我的面吹牛析藕,可吹牛的內(nèi)容都是我干的召廷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼账胧,長吁一口氣:“原來是場噩夢啊……” “哼竞慢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起治泥,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤筹煮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后居夹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體败潦,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年准脂,在試婚紗的時候發(fā)現(xiàn)自己被綠了劫扒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡狸膏,死狀恐怖沟饥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤贤旷,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布广料,位于F島的核電站,受9級特大地震影響遮晚,放射性物質(zhì)發(fā)生泄漏性昭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一县遣、第九天 我趴在偏房一處隱蔽的房頂上張望糜颠。 院中可真熱鬧,春花似錦萧求、人聲如沸其兴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽元旬。三九已至,卻和暖如春守问,著一層夾襖步出監(jiān)牢的瞬間匀归,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工耗帕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留穆端,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓仿便,卻偏偏與公主長得像体啰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嗽仪,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • GitChat技術(shù)雜談 前言 本文較長荒勇,為了節(jié)省你的閱讀時間,在文前列寫作思路如下: 什么是 webpack闻坚,它要...
    蕭玄辭閱讀 12,674評論 7 110
  • 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載卷玉。 webpack介紹和使用 一、webpack介紹 1喷市、由來 ...
    it筱竹閱讀 11,028評論 0 21
  • 寫在前面的話 閱讀本文之前相种,先看下面這個webpack的配置文件,如果每一項你都懂,那本文能帶給你的收獲也許就比較...
    不忘初心_9a16閱讀 3,232評論 0 17
  • 在現(xiàn)在的前端開發(fā)中寝并,前后端分離箫措、模塊化開發(fā)、版本控制衬潦、文件合并與壓縮斤蔓、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,431評論 1 32
  • 劉若英和陳升沒有走到一起弦牡,但凡是愛過的人都是幸運的 誰不曾為愛癡狂? 02年奶茶的第一部電影《我的美麗與哀愁》上畫...
    間間愛閱讀 618評論 0 0