一庆亡、什么是 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 以難以令人置信的速度 快速增量編譯
-
二丰介、安裝
-
全局安裝
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 是最好的選擇