Webpack是一個打包模塊化JavaScript的工具,在Webpack裏一切文件皆模塊,經過Loader轉換文件,經過Plugin注入鉤子,最後輸出由多個模塊組合成的文件。Webpack專一於構建模塊化項目,稱爲模塊打包機。css
入口,Webpack執行構建的第一步將從entry開始,可抽象成輸入;html
module.exports = { entry: './main.js' }; 複製代碼
輸出結果,在Webpack通過一系列處理並獲得最終想要的代碼後輸出結果;vue
module.exports = { entry: './main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, './dist'); } }; 複製代碼
模塊轉換器,用於將模塊的原內容按照需求轉換成新內容;node
module.exports = { entry: './main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, './dist'); }, module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader?minimize'], } ] } }; 複製代碼
擴展插件,在Webpack構建流程中的特定時機注入擴展邏輯,來改變構建結果或咱們想作的事情;react
module.exports = { entry: './main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, './dist'); }, module: { rules: [ { test: /\.css$/, loaders: ExtractTextPlugin.extract({ use: ['css-loader'] }) } ] }, plugins: [ new ExtractTextPlugin({ fliename: `[name]_[contenthash:8].css`, }) ] }; 複製代碼
模塊,在Webpack裏一切皆模塊,一個模塊對應一個文件。Webpack會從配置的entry開始遞歸找出全部依賴的模塊;jquery
代碼塊,一個chunk由多個模塊組合而成,用於代碼合併與分割;webpack
總結: Webpack在啓動後會從Entry裏配置的Module開始,遞歸解析Entry依賴的全部Module。每找到一個Module,就會根據配置的Loader去找出對應的轉換規則,對Module進行轉換後,再解析出當前Module依賴的Module。這些模塊會以Entry爲單位進行分組,一個Entry及其全部依賴的Module被分到一個組也就是一個Chunk。最後Webpack會將全部Chunk轉換成文件輸出,在整個流程中,Webpack會在恰當的時機執行Plugin裏定義的邏輯。git
Webpack在尋找相對路徑的文件時會以context爲根目錄,context默認爲當前所在的工做目錄,注意context必須是一個絕對路徑的字符串。github
module.exports = { context: path.resolve(__dirname, 'app'), }; 複製代碼
類型 | 例子 | 含義 |
---|---|---|
String | './main.js' | 入口模塊的文件路徑,能夠是相對路徑 |
Array | ['./main.js', './app.js'] | 入口模塊的文件路徑,能夠是相對路徑 |
Object | {a: './main.js', b: './app.js'} | 配置多個入口,每一個入口生成一個chunk |
chunk的名稱和entry的配置有關,若是entry是一個String或Array,只會生成一個chunk;若是entry是一個Object,就會生成多個chunk,名稱爲Object中的key。web
若是不肯定有多少個頁面入口,能夠設置爲一個函數動態的返回entry配置;
// 同步函數 entry: () => { return { a: './page1/index', b: './page2/index' } } // 異步函數 entry: () => { return new Promise( (resolve) => { resolve({ a: './page1/index', b: './page2/index' }) }) } 複製代碼
filename是配置輸出的文件名稱,爲string類型,若是隻有一個輸出文件能夠寫死爲bundle.js,可是有多個輸出時能夠藉助模板變量[name].js
,經常使用的變量包括:
變量名稱 | 含義 |
---|---|
id | Chunk的惟一標識,默認從0開始 |
name | Chunk的名稱 |
hash | Chunk的惟一標識的Hash值,[hash:8]表明取8位Hash值,默認是20位 |
chunkhash | Chunk內容的Hash值,取值同上 |
用於指定在運行過程當中生成的Chunk在輸出時的文件名稱,常見場景爲使用CommonChunkPlugin;支持和filename一致的內置變量;
配置輸出文件的本地目錄,爲string類型的絕對路徑,支持字符串模板,內置變量只有一個Hash;
module.exports = { output: { path: path.resolve(__dirname, 'dist_[hash]') } }; 複製代碼
配置發佈到線上資源的URL前綴,爲string類型的相對路徑,默認爲'',也支持字符串模板,內置變量只有一個Hash;
module.exports = { output: { filename: '[name]_[chunkhash:8].js', publicPath: 'https://XX.cdn.com/static/' } }; 複製代碼
Webpcak輸出的部分代碼塊可能須要異步加載,是經過JSONP方式實現的,因此能夠在<script>
標籤中設置crossorigin屬性,經常使用來獲取異步加載的腳本執行時的詳細錯誤信息。
crossorigin屬性值 | 含義 |
---|---|
anonymous(默認) | 在加載此腳本資源時不會帶上用戶的cookie |
use-credentials | 在加載此腳本資源時會帶上用戶的cookie |
當用Webpack去構建一個能夠被其餘模塊導入使用的庫時,須要用到LibraryTarget和library,它們一般搭配在一塊兒使用,推薦使用Rollup來構建基礎庫;
LibraryTarget配置以何種方式導出庫,經常使用的有var/this/commonjs/window/global等;
Library配置導出庫的名稱,配合LibraryTarget一塊兒使用;
複製代碼
配置爲要導出的模塊中哪些子模塊須要被導出,它只有在output.libraryTarget被設置爲commonjs或者commonjs2時使用纔有意義;
// 某模塊源代碼 export const a = 1; export default b = 2; // 若是在output.libraryExport設置爲a;那麼將構建輸出的代碼和使用方法將變成如下內容: // Webpack輸出的代碼 module.export = lib_code['a']; // 使用庫的方法 require('library-name') === 1; 複製代碼
rules配置模塊的讀取和解析規則,一般用來配置Loader。類型爲數組,數組裏的每一項都描述瞭如何處理部分文件,每一項大體有以下三種方式來完成;
module.exports = { module: { rules: [ { test: /\.js$/, use: [{ loader: 'babel-loader', options: { cacheDirectory: true }, enforce: 'post' }], include: path.resolve(__dirname, 'src'), }, { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'], exclude: path.resolve(__dirname, 'node_modules') } ] } }; 複製代碼
該可選配置項可讓Webpack忽略對部分沒采用模塊化的文件的遞歸解析和處理,從而提升構建性能,類型爲RegExp、[RegExp]、Function中的一種,注意被忽略的文件裏不能包含import、require、define等模塊化語句,否則會致使在瀏覽器中沒法執行該模塊化語句;
// 正則形式 noParse: /jquery|chartjs/ // 函數形式 noParse: (content) => { return /jquery|chartjs/.test(content); } 複製代碼
該配置項能夠精確到語法層面,讓Webpack只解析對應的模塊化文件;
module.exports = { module: { rules: [ { test: /\.js$/, use: ['babel-loader'], include: path.resolve(__dirname, 'src'), parser: { amd: false, commonjs: true, requirejs: false, harmony: true } } ] } }; 複製代碼
該配置項經過別名來將原導入路徑映射成一個新的導入路徑;
module.exports = { resolve: { alias: { @components: './src/common/components', @assets: './src/common/assets' } } }; 複製代碼
有一些第三方模塊會針對不一樣的環境提供幾份代碼,例如分別提供ES5和ES6兩份代碼,Webpack會根據mainFields的配置去決定優先採用哪份代碼,若是想優先採用ES6的代碼,則能夠這樣配置:
mainFields: ['jsnext:main', 'browser', 'main'], 複製代碼
在導入語句沒帶文件後綴時,Webpack會自動帶上後綴嘗試訪問文件是否存在,默認是:
extensions: ['.js', '.json'], 複製代碼
若是咱們想讓Webpack優先使用typescript文件,則能夠這樣配置:
extensions: ['.ts', '.js', '.json'] 複製代碼
配置Webpack去哪些目錄下尋找第三方模塊,有時候咱們項目中的大量模塊會放在common下面,則能夠這樣去配置:
modules: ['./src/common', 'node_modules'] 複製代碼
該配置項是描述第三方模塊的文件名稱,也就是package.json文件,默認以下:
descriptionFiles: ['package.json'] 複製代碼
若是resolve.enforceExtension爲true,則全部導入語句都必須帶後綴,如import './main.js';
和resolve.enforceExtension做用相似,專門針對node_modules下的模塊生效,由於第三方模塊大部分是不帶後綴的,若是resolve.enforceExtension設置爲true了,須要把resolve.enforceModuleExtension設爲false來兼容第三方模塊;
Plugin的配置很簡單,plugins接收一個數組,數組中的每一項都是一個Plugin的實例,Plugin的參數經過構造函數傳入;
module.exports = { plugins: [ new CommonChunkPlugin({ name: 'common', chunks: ['a', 'b'] }) ] }; 複製代碼
開啓模塊熱替換功能,在不刷新整個頁面的狀況下,經過用新模塊替換老模塊來作到實時預覽;
用於配置是否將這個代理客戶端自動注入將運行在頁面中的chunk裏,默認自動注入;
-- 若是開啓inline,則devserver會在構建變化後的代碼時經過代理客戶端控制網頁刷新;
-- 若是關閉inline,則devserver會經過iframe的方式去運行要開發的網頁,在構建完變化後的代碼時,會經過刷新iframe來實現實時預覽,這時須要去http://localhost:8080/webpack-dev-server/ 實時預覽本身的網頁;
用於方便的開發使用了HTML5的History API的單頁應用,老是返回同一個html文件,瀏覽器會從URL裏解析出當前頁面的狀態,從而顯示對應的界面;
用來配置devserver HTTP服務器的文件根目錄,在默認狀況下爲當前的執行目錄,一般是項目的根目錄,因此在通常狀況下沒必要設置;
能夠在http響應中注入一些http響應頭,使用以下:
module.exports = { devServer: { headers: { 'x-cookie': 12345 } } }; 複製代碼
用於配置devServer服務監聽的地址,若是想讓局域網的其餘設備訪問本身的本地服務,則能夠在啓動devserver時帶上參數--host 0.0.0.0;
用於配置devServer服務監聽的端口,默認使用8080端口,若是80端口被其餘程序佔用則依次+1類推;
配置一個白名單列表,只有http請求的host在該列表中才會正常返回;
配置是否關閉用於DNS從新綁定的http請求的host檢查,devserver默認只接受本地的請求,關閉後能夠接收來自任意host的請求;
devsever默認使用http服務,在某些狀況下須要使用https服務時,能夠開啓此配置,此時devsever會自動爲咱們在本地生成一份https證書,這時須要重啓服務,如HTTP2和Service Worker就必須運行在https上;
配置客戶端的日誌等級,會影響咱們在瀏覽器控制檯裏看到的內容,默認爲info級別,即輸出因此類型(none/error/warning/info)的日誌;
配置是否啓用Gzip壓縮,爲Boolean類型,默認爲false;
用於在devserver啓動且第一次構建完成時,自動用系統默認瀏覽器打開咱們開發的頁面,還提供了openPage配置項來打開指定URL的頁面;
target配置可讓Webpack構建除針對不一樣運行環境的代碼,常見的有:
target值 | 含義 |
---|---|
web | 針對瀏覽器(默認),全部代碼都集中在一個文件裏 |
node | 針對nodejs,使用require語句加載chunk代碼 |
async-node | 針對nodejs,異步加載chunk代碼 |
webworker | 針對webworker |
electron-mian | 針對Electron主線程 |
electron-render | 針對Electron渲染線程 |
配置Webpack如何生成Source Map,默認值是false即不生成,若想構建出的代碼生成Source Map方便調試,則能夠這樣配置:
module.exports = { devtool: 'source-map' }; 複製代碼
Webpack支持監聽文件更新,在文件發生變化時從新編譯,監聽模式默認是關閉的,如想打開則配置爲:
module.exports = { watch: true }; 複製代碼
在使用devserver時,監聽模式默認開啓;除此以外,還能夠靈活的控制監聽模式;
module.exports = { watch: true, watchOptions: { // 不監聽的文件或文件夾,支持正則匹配 ignored: /node_modules/, // 監聽到變化後會等300ms再去執行,防抖 // 默認是300ms aggregateTimeout: 300, // 判斷文件是否發生變化經過不停地詢問系統指定文件有沒有變化 // 默認每秒詢問1000次 poll: 1000 } }; 複製代碼
用於告訴Webpack要構建的代碼中使用了哪些不用被打包的模塊,也就是說這些模版是外部環境提供的,Webpack在打包時能夠忽略它們;
module.exports = { externals: { jquery: 'jQuery' } }; 複製代碼
用來告訴Webapck如何去尋找Loader,該配置項經常使用來加載本地的Loader,默認配置以下:
module.exports = { resolveLoader: { modules: ['node_modules'], extensions: ['js', 'json'], mainFields: ['loader', 'main'] } }; 複製代碼
Loader名稱 | 功能描述 |
---|---|
raw-loader |
加載文件原始內容(utf-8) |
val-loader |
將代碼做爲模塊執行,並將 exports 轉爲 JS 代碼 |
url-loader |
像 file loader 同樣工做,但若是文件小於限制,能夠返回 data URL |
file-loader |
將文件發送到輸出文件夾,並返回(相對)URL |
Loader名稱 | 功能描述 |
---|---|
json-loader |
加載 JSON文件(默認包含) |
json5-loader |
加載和轉譯 JSON 5文件 |
Loader名稱 | 功能描述 |
---|---|
script-loader |
在全局上下文中執行一次 JavaScript 文件(如在 script 標籤),不須要解析 |
babel-loader |
加載 ES2015+ 代碼,而後使用 Babel 轉譯爲 ES5 |
buble-loader |
使用 Bublé 加載 ES2015+ 代碼,而且將代碼轉譯爲 ES5 |
traceur-loader |
加載 ES2015+ 代碼,而後使用 Traceur轉譯爲 ES5 |
ts-loader 或 awesome-typescript-loader |
像 JavaScript 同樣加載 TypeScript2.0+ |
coffee-loader |
像 JavaScript 同樣加載 CoffeeScript |
Loader名稱 | 功能描述 |
---|---|
html-loader |
導出 HTML 爲字符串,須要引用靜態資源 |
pug-loader |
加載 Pug 模板並返回一個函數 |
jade-loader |
加載 Jade 模板並返回一個函數 |
markdown-loader |
將 Markdown 轉譯爲 HTML |
react-markdown-loader |
使用 markdown-parse parser(解析器) 將 Markdown 編譯爲 React 組件 |
posthtml-loader |
使用 PostHTML 加載並轉換 HTML 文件 |
handlebars-loader |
將 Handlebars 轉移爲 HTML |
markup-inline-loader |
將內聯的 SVG/MathML 文件轉換爲 HTML。在應用於圖標字體,或將 CSS 動畫應用於 SVG 時很是有用。 |
Loader名稱 | 功能描述 |
---|---|
style-loader |
將模塊的導出做爲樣式添加到 DOM 中 |
css-loader |
解析 CSS 文件後,使用 import 加載,而且返回 CSS 代碼 |
less-loader |
加載和轉譯 LESS 文件 |
sass-loader |
加載和轉譯 SASS/SCSS 文件 |
postcss-loader |
使用 PostCSS加載和轉譯 CSS/SSS 文件 |
stylus-loader |
加載和轉譯 Stylus 文件 |
Loader名稱 | 功能描述 |
---|---|
mocha-loader |
使用 mocha 測試(瀏覽器/NodeJS) |
eslint-loader |
PreLoader,使用 ESLint 清理代碼 |
jshint-loader |
PreLoader,使用 JSHint 清理代碼 |
coverjs-loader |
PreLoader,使用 CoverJS 肯定測試覆蓋率 |
Loader名稱 | 功能描述 |
---|---|
vue-loader |
加載和轉譯 Vue 組件 |
polymer-loader |
使用選擇預處理器(preprocessor)處理,而且 require() 相似一等模塊(first-class)的 Web 組件 |
angular2-template-loader |
加載和轉譯 Angular 組件 |
Plugin名稱 | 功能描述 |
---|---|
AggressiveSplittingPlugin |
將原來的 chunk 分紅更小的 chunk |
BabelMinifyWebpackPlugin |
使用 babel-minify進行壓縮 |
BannerPlugin |
在每一個生成的 chunk 頂部添加 banner |
CommonsChunkPlugin |
提取 chunks 之間共享的通用模塊 |
CompressionWebpackPlugin |
預先準備的資源壓縮版本,使用 Content-Encoding 提供訪問服務 |
ContextReplacementPlugin |
重寫 require 表達式的推斷上下文 |
CopyWebpackPlugin |
將單個文件或整個目錄複製到構建目錄 |
DefinePlugin |
容許在編譯時(compile time)配置的全局常量 |
DllPlugin |
爲了極大減小構建時間,進行分離打包 |
EnvironmentPlugin |
DefinePlugin 中 process.env 鍵的簡寫方式。 |
ExtractTextWebpackPlugin |
從 bundle 中提取文本(CSS)到單獨的文件 |
HotModuleReplacementPlugin |
啓用模塊熱替換(Enable Hot Module Replacement - HMR) |
HtmlWebpackPlugin |
簡單建立 HTML 文件,用於服務器訪問 |
I18nWebpackPlugin |
爲 bundle 增長國際化支持 |
IgnorePlugin |
從 bundle 中排除某些模塊 |
LimitChunkCountPlugin |
設置 chunk 的最小/最大限制,以微調和控制 chunk |
LoaderOptionsPlugin |
用於從 webpack 1 遷移到 webpack 2 |
MinChunkSizePlugin |
確保 chunk 大小超過指定限制 |
NoEmitOnErrorsPlugin |
在輸出階段時,遇到編譯錯誤跳過 |
NormalModuleReplacementPlugin |
替換與正則表達式匹配的資源 |
NpmInstallWebpackPlugin |
在開發時自動安裝缺乏的依賴 |
ProvidePlugin |
沒必要經過 import/require 使用模塊 |
SourceMapDevToolPlugin |
對 source map 進行更細粒度的控制 |
EvalSourceMapDevToolPlugin |
對 eval source map 進行更細粒度的控制 |
UglifyjsWebpackPlugin |
能夠控制項目中 UglifyJS 的版本 |
ZopfliWebpackPlugin |
經過 node-zopfli 將資源預先壓縮的版本 |
更多第三方Loader和Plugin,查看 awesome-webpack 列表。
本文整理於【深刻淺出Webpack】,若有錯誤,敬請雅正😄
更多精彩內容歡迎關注個人公衆號【天道酬勤Lewis】