Webpack 知識(shí)點(diǎn)總結(jié)

隨著現(xiàn)代前端開發(fā)的規(guī)模日益龐大包竹,幾乎已經(jīng)不能拋開諸如 React 或 Vue 等前端開發(fā)框架來獨(dú)立開發(fā)了脐恩,這些框架很大程度上的提高了我們的開發(fā)效率,但是框架中所使用特殊文件疆瑰,比如 jsx是辕、vue囤热、scssless 等猎提,瀏覽器是無法直接識(shí)別的获三,必須經(jīng)過編譯后才能在瀏覽器中使用。于是在眾多的前端工程化工具中锨苏,Webpack 脫穎而出成為了當(dāng)今最流行的前端構(gòu)建工具疙教。 [1]

webpack

Webpack 配置模板:

// webpack.config.js
const path = require("path");
module.exports = {
  entry: "./app/entry", // string | object | array
  // Webpack打包的入口
  output: {
    // 定義webpack如何輸出的選項(xiàng)
    path: path.resolve(__dirname, "dist"), // string
    // 所有輸出文件的目標(biāo)路徑
    filename: "[chunkhash].js", // string
    // 「入口(entry chunk)」文件命名模版
    publicPath: "/assets/", // string
    // 構(gòu)建文件的輸出目錄
    /* 其它高級(jí)配置 */
  },
  module: {
    // 模塊相關(guān)配置
    rules: [
      // 配置模塊loaders,解析規(guī)則
      {
        test: /\.jsx?$/, // RegExp | string
        include: [
          // 和test一樣伞租,必須匹配選項(xiàng)
          path.resolve(__dirname, "app"),
        ],
        exclude: [
          // 必不匹配選項(xiàng)(優(yōu)先級(jí)高于test和include)
          path.resolve(__dirname, "app/demo-files"),
        ],
        loader: "babel-loader", // 模塊上下文解析
        options: {
          // loader的可選項(xiàng)
          presets: ["es2015"],
        },
      },
    ],
  },
  resolve: {
    //  解析模塊的可選項(xiàng)
    modules: [
      // 模塊的查找目錄
      "node_modules",
      path.resolve(__dirname, "app"),
    ],
    extensions: [".js", ".json", ".jsx", ".css"], // 用到的文件的擴(kuò)展
    alias: {
      // 模塊別名列表
      module: "new-module",
    },
  },
  devtool: "source-map", // enum
  // 為瀏覽器開發(fā)者工具添加元數(shù)據(jù)增強(qiáng)調(diào)試
  plugins: [
    // 附加插件列表
    // ...
  ],
};

Webpack 的運(yùn)行流程是怎樣的贞谓?

Webpack 的運(yùn)行流程是一個(gè)串行的過程,從啟動(dòng)到結(jié)束會(huì)依次執(zhí)行以下流程:[2]
  1. 初始化參數(shù):從配置文件 webpack.config.js 和命令行中讀取與合并參數(shù)葵诈,初始化本次構(gòu)建的配置參數(shù)裸弦,得出最終的參數(shù);
  2. 開始編譯:用上一步得到的參數(shù)初始化 Compiler 對(duì)象作喘,加載配置文件的所有 plugin理疙,執(zhí)行對(duì)象的 run 方法開始執(zhí)行編譯;
  3. 確定入口:根據(jù)配置中的 entry 找出所有的入口文件泞坦,遞歸遍歷所有的入口文件窖贤;
  4. 編譯模塊:從入口文件出發(fā),調(diào)用所有配置的 loader 對(duì)模塊進(jìn)行編譯,再找出該模塊依賴的模塊赃梧,再遞歸本步驟直到所有入口依賴的文件都經(jīng)過了本步驟的處理滤蝠。
  5. 輸出資源:所有文件的編譯及轉(zhuǎn)化都已經(jīng)完成,也就是最終輸出的資源授嘀,其中包括即將輸出的資源物咳、代碼塊 Chunk 等等信息。
運(yùn)行流程圖:[3]
Webpack 運(yùn)行流程圖

Webpack 的 Loader 是什么蹄皱?

Webpack 只能理解 JavaScriptJSON 文件所森,這是 Webpack 開箱可用的自帶能力。loader 可以讓 Webpack 能夠去處理其他類型的文件夯接,比如 .scss.ts焕济,并將它們轉(zhuǎn)換為有效的功能離散的 chunk 文件以供應(yīng)用程序使用,以及被添加到依賴圖中盔几,也可將內(nèi)聯(lián)圖像轉(zhuǎn)換為 data URL晴弃。簡單來說,loader 可以將一段代碼轉(zhuǎn)換成另一端代碼逊拍,通常用來將一段特殊代碼轉(zhuǎn)換成一段瀏覽器可識(shí)別的代碼上鞠。

loader從下到上地取值(evaluate)/執(zhí)行(execute),也就是是從后往前執(zhí)行芯丧。在下面的示例中芍阎,從 ts-loader開始執(zhí)行,然后繼續(xù)執(zhí)行 css-loader缨恒,最后以 raw-loader 為結(jié)束谴咸。loader 有兩個(gè)屬性:test,正則表達(dá)式骗露,用于識(shí)別出哪些文件會(huì)被轉(zhuǎn)換岭佳,use 定義在進(jìn)行轉(zhuǎn)換時(shí)應(yīng)該使用哪個(gè) loader,可以是字符串萧锉、數(shù)組和對(duì)象珊随。[4]

// webpack.config.js
module.exports = {
  output: {
    filename: "my-first-webpack.bundle.js",
  },
  module: {
    rules: [
      { test: /\.txt$/, use: "raw-loader" }, // 通過 npm 安裝
      {
        test: /\\.css$/,
        use: [
          {
            loader: "css-loader", // 通過 npm 安裝
            options: { modules: true },
          },
        ],
      },
      { test: /\\.ts$/, use: "ts-loader" }, // 通過 npm 安裝
    ],
  },
};

有哪些常見的 Loader ??? Loaders

  • raw-loader:加載文件原始內(nèi)容(utf-8)
  • file-loader:把文件輸出到一個(gè)文件夾中柿隙,在代碼中通過相對(duì) URL 去引用輸出的文件 (處理圖片和字體)
  • url-loader:與 file-loader 類似叶洞,區(qū)別是用戶可以設(shè)置一個(gè)閾值,大于閾值會(huì)交給 file-loader 處理禀崖,小于閾值時(shí)返回文件 base64 形式編碼 (處理圖片和字體)
  • source-map-loader:加載額外的 Source Map 文件衩辟,以方便斷點(diǎn)調(diào)試
  • svg-inline-loader:將壓縮后的 SVG 內(nèi)容注入代碼中
  • image-loader:加載并且壓縮圖片文件
  • json-loader 加載 JSON 文件(默認(rèn)包含)
  • handlebars-loader: 將 Handlebars 模版編譯成函數(shù)并返回
  • babel-loader:把 ES6 轉(zhuǎn)換成 ES5
  • ts-loader: 將 TypeScript 轉(zhuǎn)換成 JavaScript
  • awesome-typescript-loader:將 TypeScript 轉(zhuǎn)換成 JavaScript,性能優(yōu)于 ts-loader
  • sass-loader:將SCSS/SASS代碼轉(zhuǎn)換成CSS
  • css-loader:加載 CSS帆焕,支持模塊化惭婿、壓縮不恭、文件導(dǎo)入等特性
  • style-loader:把 CSS 代碼注入到 JavaScript 中,通過 DOM 操作去加載 CSS
  • postcss-loader:擴(kuò)展 CSS 語法财饥,使用下一代 CSS换吧,可以配合 autoprefixer 插件自動(dòng)補(bǔ)齊 CSS3 前綴
  • eslint-loader:通過 ESLint 檢查 JavaScript 代碼
  • tslint-loader:通過 TSLint檢查 TypeScript 代碼
  • mocha-loader:加載 Mocha 測(cè)試用例的代碼
  • coverjs-loader:計(jì)算測(cè)試的覆蓋率
  • vue-loader:加載 Vue.js 單文件組件
  • i18n-loader: 國際化
  • cache-loader: 可以在一些性能開銷較大的 Loader 之前添加,目的是將結(jié)果緩存到磁盤里

Webpack 的 Plugin 是什么钥星?

loader 用于轉(zhuǎn)換某些類型的模塊沾瓦,而 plugin(插件)則可以用于執(zhí)行范圍更廣的任務(wù)。包括:打包優(yōu)化谦炒,資源管理贯莺,注入環(huán)境變量。想要使用一個(gè) plugin宁改,你只需要 require() 它缕探,然后把它添加到 plugins 數(shù)組中。多數(shù)插件可以通過 option 自定義还蹲,也可以在一個(gè)配置文件中因?yàn)椴煌康亩啻问褂猛粋€(gè)插件爹耗,這時(shí)需要通過使用 new 操作符來創(chuàng)建一個(gè)插件實(shí)例。[5]

// webpack.config.js
const webpack = require('webpack'); // 用于訪問內(nèi)置插件
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通過 npm 安裝

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

有哪些常見的 Plugin 谜喊?Plugins

  • define-plugin:定義環(huán)境變量 (Webpack4 之后指定 mode 會(huì)自動(dòng)配置)
  • ignore-plugin:忽略部分文件
  • html-webpack-plugin:簡化 HTML 文件創(chuàng)建 (依賴于 html-loader)
  • web-webpack-plugin:可方便地為單頁應(yīng)用輸出 HTML潭兽,比 html-webpack-plugin 好用
  • uglifyjs-webpack-plugin:不支持 ES6 壓縮 (Webpack4 以前)
  • terser-webpack-plugin: 支持壓縮 ES6 (Webpack4)
  • webpack-parallel-uglify-plugin: 多進(jìn)程執(zhí)行代碼壓縮,提升構(gòu)建速度
  • mini-css-extract-plugin: 分離樣式文件斗遏,CSS 提取為獨(dú)立文件山卦,支持按需加載 (替代extract-text-webpack-plugin)
  • serviceworker-webpack-plugin:為網(wǎng)頁應(yīng)用增加離線緩存功能
  • clean-webpack-plugin: 目錄清理
  • ModuleConcatenationPlugin: 開啟 Scope Hoisting
  • speed-measure-webpack-plugin: 可以看到每個(gè) Loader 和 Plugin 執(zhí)行耗時(shí) (整個(gè)打包耗時(shí)、每個(gè) Plugin 和 Loader 耗時(shí))
  • webpack-bundle-analyzer: 可視化 Webpack 輸出文件的體積 (業(yè)務(wù)組件诵次、依賴第三方模塊)

Webpack 的熱更新原理是怎樣的账蓉?

Webpack 的熱更新又稱熱替換(Hot Module Replacement),縮寫為 HMR藻懒。 這個(gè)機(jī)制可以做到不用刷新瀏覽器而將新變更的模塊替換掉舊的模塊剔猿。

HMR 工作流程

  1. Webpack 通過 Watch 模式可以偵聽文件的變化,當(dāng)文件發(fā)生改變時(shí)嬉荆,會(huì)根據(jù)配置進(jìn)行重新編譯(Compile),并將編譯后的代碼保存在內(nèi)存中酷含。
  2. webpack-dev-server 也會(huì)對(duì)文件變化進(jìn)行監(jiān)控(需要配置 devServer.watchContentBase = true)鄙早,但不會(huì)進(jìn)行重新編譯,而是監(jiān)聽這些配置文件中靜態(tài)文件的變化椅亚,變化后會(huì)通知瀏覽器進(jìn)行直接刷新限番,而不是 HMR
  3. 在瀏覽器和服務(wù)端之間有一個(gè)通過 SocketJs 建立的 websocket 長連接呀舔。webpack-dev-server 會(huì)將 Webpack 編譯打包時(shí)的各個(gè)階段的狀態(tài)信息和 hash 值一并告知 webpack-dev-server/client(位于瀏覽器端)弥虐。
  4. 但是 webpack-dev-server/client 并不能夠請(qǐng)求更新的代碼扩灯,而是把這些工作交給了 webpack/hot/dev-serverwebpack/hot/dev-server 的工作就是根據(jù) webpack-dev-server/client 傳來的信息以及 dev-server 的配置決定是刷新瀏覽器還是 HMR霜瘪。
  5. HotModuleReplacement.runtime 是客戶端 HMR 的中樞珠插,它接收到 webpack/hot/dev-server 傳遞的新模塊的 hash 值,通過 JsonpMainTemplate.runtimewebpack-dev-server 發(fā)送 Ajax 請(qǐng)求獲取到返回的 Json颖对,該 Json 包含了所有要更新的模塊的 hash 值捻撑,之后通過 Jsonp 請(qǐng)求,獲取到最新的模塊代碼缤底。
  6. 接下來顾患,HotModulePlugin 將會(huì)對(duì)新舊模塊進(jìn)行對(duì)比,決定是否更新模塊个唧,在決定更新模塊后江解,檢查模塊之間的依賴關(guān)系,更新模塊的同時(shí)更新模塊間的依賴引用徙歼。
  7. 如果 HMR 失敗膘流,則通過刷新瀏覽器來獲取最新打包代碼。

  1. 關(guān)于webpack的面試題 ?

  2. 「吐血整理」再來一打Webpack面試題 ?

  3. Webpack揭秘 ?

  4. loaders ?

  5. plugins ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鲁沥,一起剝皮案震驚了整個(gè)濱河市呼股,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌画恰,老刑警劉巖彭谁,帶你破解...
    沈念sama閱讀 221,406評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異允扇,居然都是意外死亡缠局,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門考润,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狭园,“玉大人,你說我怎么就攤上這事糊治〕” “怎么了?”我有些...
    開封第一講書人閱讀 167,815評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵井辜,是天一觀的道長绎谦。 經(jīng)常有香客問我,道長粥脚,這世上最難降的妖魔是什么窃肠? 我笑而不...
    開封第一講書人閱讀 59,537評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮刷允,結(jié)果婚禮上冤留,老公的妹妹穿的比我還像新娘碧囊。我一直安慰自己,他們只是感情好纤怒,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,536評(píng)論 6 397
  • 文/花漫 我一把揭開白布糯而。 她就那樣靜靜地躺著,像睡著了一般肪跋。 火紅的嫁衣襯著肌膚如雪歧蒋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,184評(píng)論 1 308
  • 那天州既,我揣著相機(jī)與錄音谜洽,去河邊找鬼。 笑死吴叶,一個(gè)胖子當(dāng)著我的面吹牛阐虚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚌卤,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼实束,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了逊彭?” 一聲冷哼從身側(cè)響起咸灿,我...
    開封第一講書人閱讀 39,668評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侮叮,沒想到半個(gè)月后避矢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,212評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡囊榜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,299評(píng)論 3 340
  • 正文 我和宋清朗相戀三年审胸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卸勺。...
    茶點(diǎn)故事閱讀 40,438評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砂沛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出曙求,到底是詐尸還是另有隱情碍庵,我是刑警寧澤,帶...
    沈念sama閱讀 36,128評(píng)論 5 349
  • 正文 年R本政府宣布圆到,位于F島的核電站怎抛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏芽淡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,807評(píng)論 3 333
  • 文/蒙蒙 一豆赏、第九天 我趴在偏房一處隱蔽的房頂上張望挣菲。 院中可真熱鬧富稻,春花似錦、人聲如沸白胀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽或杠。三九已至哪怔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間向抢,已是汗流浹背认境。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挟鸠,地道東北人叉信。 一個(gè)月前我還...
    沈念sama閱讀 48,827評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像艘希,于是被迫代替她去往敵國和親硼身。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,446評(píng)論 2 359