一 概念javascript
1 入口(entry)css
入口起點(entry point)提示webpack 應該使用那個模塊,來做爲構建其內部依賴圖得開始。進入入口七點後,webpack 會找出那些模塊和庫是入口起點(直接和間接)依賴的。html
每一項依賴隨即被處理,最後輸出到稱之爲bundles的文件中,前端
能夠經過webpack配置中的配置entry屬性,來指指定一個入口起點(或多個入口起點)。默認值爲 ./src。java
webpack.config.文件中node
module.exports = { entry:'./path/to/my/entry/file.js' }
2 出口(output)webpack
output 屬性告訴webpack再哪裏輸出它所建立的bundles,以及如何命名這些文件,默認值爲 ./dist。基本上,整個應用程序結構,都會被編譯到你指定的輸出路徑的文件夾中,你能夠經過再配置中指定一個output字段,來配置這些處理過程:git
webpack.config.jsgithub
const path = require('path'); module.exports = { entry :'./path/to/my/entry/file.js', output:{ path:path.resolve(_dirname,'dist'), filename:'my_first_webpack.bundle.js' } }
在上面的示例中,咱們經過output.path和output.filename兩個屬性,來告訴webpack bundle的名稱以及咱們想要bundle生成web
(emit)到哪裏。可能你想要了解在代碼最上面導入的path模塊是什麼,它是一個node.js的核心模塊。用於操做文件路徑。
3 loader
loader 讓webpack可以處理那些非javascript文件(webpack自身只理解javascript)。loader能夠將全部類型的文件轉換爲webpacck可以處理的有效模塊,而後你就能夠利用webpack的打包能力,對他們進行處理。
本質上,webpack loader 將全部類型的文件,轉化爲應用程序的依賴圖(和最終的bundle)能夠直接引用的模塊。
注意 ,loader可以import導入任何類型的模塊(例如:.css文件)
在更高層面,在webpack的配置中loader有兩個目標:
1 test 屬性,用於標識出應該被對應的loader進行轉換的某個或某些文件
2 use 屬性, 標識進行轉換時,應該使用哪個loader
weback.config.js
const path = require('path'); const config = { output: { filename: 'my-first-webpack.bundle.js' }, module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] } }; module.exports = config;
以上配置中,對一個單獨的module對象定義了rules屬性,裏面包含了兩個必須屬性:test和use。這告訴webpack編譯器以下信息:
在require()/import 語句中被解析爲'.txt'的路徑時,在你對它進行打包以前,先使用raw-loader轉換一下。
4 插件(plugins)
loader被用於轉換某些類型的模塊,而插件則能夠用於執行範圍更廣的任務。插件的範圍包括,從打包優化和壓縮,一直到從新定義環境變量。插件接口功能及其強大,能夠用來處理各類各樣的任務。
想要使用一個插件,你只須要require()它,而後把他添加到plugins數組中。多數插件能夠經過選項(option)自定義。你也能夠在一個配置文件中由於不一樣目的而屢次使用同一個插件,這是須要經過使用new操做符來建立他的一個實例。
webpack.config.js
const Htmlwebpackplugin = require('html-webpack-plugin'); const webpack = require('webpack'); const config = { module:{ rules:[ { test : /\.txt$/,use : 'raw-loader' } ] }, plugins:{ new webpack .optimize.UglifyJsPlugin(), new Htmlwebpackplugin({ template: './src/index.html' }) } } module.exports = config;
5 模式
經過選擇development或production 之中的一個,來設置mode參數,你能夠啓用香英的模式下的webpack內置優化
module.export = { mode:'production' }
二 入口起點
1單個入口(簡寫)語法
用法entry:string|Array<string>
webpack.config.js
const config = { entry :'./path/to/my/entry/file.js' } module.exports = config;
entry 屬性的單個入口語法,是下面的簡寫:
const config = { entry :{ main:'./path/to/my/entry/file.js' } };
注意:
當你向 entry
傳入一個數組時會發生什麼?
向 entry
屬性傳入「文件路徑(file path)數組」將建立「多個主入口(multi-main entry)」。在你想要多個依賴文件一塊兒注入,而且將它們的依賴導向(graph)到一個「chunk」時,傳入數組的方式就頗有用。
使用此語法在擴展配置時有失靈活性。
2 對象語法
用法:entry :{ [ entryChunkName:string ] : string|Array<string> }
webpack.config.js
const config = { entry :{ app :'./src/app.js', vendors:'./src/vendors.js' } }
對象語法比較繁瑣,然而,這是應用程序中定義入口的最可擴展的方式。
注意:
「可擴展的 webpack 配置」是指,可重用而且能夠與其餘配置組合使用。這是一種流行的技術,用於將關注點(concern)從環境(environment)、構建目標(build target)、運行時(runtime)中分離。而後使用專門的工具(如 webpack-merge)將它們合併。
3 常見場景
分離應用程序app和第三方庫入口
webpack.config.js
const config = { entry :{ app:'./src/app.js', vendors:'./src/wendors.js' } }
這是什麼?告訴咱們webpack從app.js 和vendors.js開始建立依賴圖,這些依賴圖是彼此徹底分離,相互獨立的(每個bundle中都有一個webpack引導(bootstrap))。這種方式比較常見於,只有一個入口起點(不包含vendor)的單頁應用程序中。
爲何?此設置容許你使用CommonsChunkPlugin從應用程序bundle中提取vendor引用到vendor bundle ,而且把引用vendor的部分替換爲_webpack_require()調用。若是應用程序bundle中沒有vendor代碼,那麼你能夠在webpack中實現被稱爲長效緩存的通用模式
4 多頁面應用程序
webpack.config.js
const config = { entry :{ pageone:'./src/pagone/index.js', pagetwo:'./src/pagetwo/index.js', pagetree:'./src/pagetree/index.js', } }
爲何?告訴咱們webpack須要三個獨立分離的依賴圖
爲何?在多頁面應用程序中,(每當頁面跳轉時)服務器將會爲你從新獲取一個新的html文檔,頁面從新加載新文檔,而且資源從新下載,然而,這給了咱們特殊的機會去作不少事情
使用CommonsChunkPlugin 爲每一個頁面間的應用程序共享代碼建立bundle。因爲入口起點增多,多頁應用可以服用入口起點之間的大量代碼/模塊,從而能夠極大地從這些技術中受益
三 輸出 output
配置output 選項能夠控制webpack如何向硬盤寫入編譯文件。注意即便存在多個入口起點,但只指定一個輸出配置。
1 用法
在webpack中配置outpack屬性的最低要求是,將它的值設置爲一個對象,包括一下兩點:
filename:用於輸出文件的文件名;
目標輸出目錄path的絕對路徑;
webpack.config.js
const config={ output:{ filename:'bundle.js', path:'./home/proj/public/assets' } } module.export = config;
此配置將一個單獨的 bundle.js
文件輸出到 /home/proj/public/assets
目錄中。
2 多個入口起點
若是配置建立了多個單獨得chunk(例如:使用多個入口起點或者使用像CommonChunkPlugin這樣得插件),則應該使用佔位符來確保每一個文件具備惟一得名稱
{ entry: { app: './src/app.js', search: './src/search.js' }, output: { filename: '[name].js', path: __dirname + '/dist' } } // 寫入到硬盤:./dist/app.js, ./dist/search.js
3 高級進階
如下是使用 CDN 和資源 hash 的複雜示例:
config.js
output:{ path: "/home/proj/cdn/assets/[hash]", publicPath: "http://cdn.example.com/assets/[hash]/" }
在編譯時不知道最終輸出文件的 publicPath
的狀況下,publicPath
能夠留空,而且在入口起點文件運行時動態設置。若是你在編譯時不知道 publicPath
,你能夠先忽略它,而且在入口起點設置 __webpack_public_path__
。
__webpack_public_path__ = myRuntimePublicPath // 剩餘的應用程序入口
四 模式 mode
提供mode配置選項,告知webpack使用香英模式得內置優化。
string
1 用法
只在配置中提供mode選項:
module.exports = { mode:'production' }
或者從命令中傳參
wbpack --mode=production
支持一下字符串
選項 | 描述 |
development | 會將
|
production | 會將
|
// webpack.development.config.js module.exports = { + mode: 'development' - plugins: [ - new webpack.NamedModulesPlugin(), - new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }), - ] }
// webpack.production.config.js module.exports = { + mode: 'production', - plugins: [ - new UglifyJsPlugin(/* ... */), - new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }), - new webpack.optimize.ModuleConcatenationPlugin(), - new webpack.NoEmitOnErrorsPlugin() - ] }
五 loader
loader用於對模塊得源代碼進行轉換。loader可使你在import或‘加載’模塊時預處理文件。所以,loader 相似於其實他構建工具中‘任務task’,並提供了處理前端構建步驟得強大方法。loader能夠將文件從不一樣得語言(如:typeScript)轉換成javascript,或將內聯圖像轉換爲data url 。loader甚至容許你直接在javascript模塊中inport CSS文件!
1 示例
你可使用 loader 告訴 webpack 加載 CSS 文件,或者將 TypeScript 轉爲 JavaScript。爲此,首先安裝相對應的 loader:
npm install --save-dev css-loader
npm install --save-dev ts-loader
而後指示 webpack 對每一個 .css
使用 css-loader
,以及對全部 .ts
文件使用 ts-loader:
webpack.config.js
module.exports = { module :{ rules:[ {test:/\.css$/,use:'css-loader'}, {test:/.\ts$/,use:'ts-loader'} ] } }
在你的應用程序中,有三種使用 loader 的方式:
配置:在 webpack.config.js 文件中指定 loader。
內聯:在每一個 import
語句中顯式指定 loader。
CLI:在 shell 命令中指定它們。
3 配置
module.rules容許你在webpack中指定多個loader。這是展現loader得一種簡明方式。而且有助於使代碼變得更加簡潔,同時讓你對各個loader有個全局得概覽:
module: { rules: [ { test: /\.css$/, use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true } } ] } ] }
4 內聯
能夠在import語句或者任何等效於 import 語句的方式中指定loader。使用!將資源中的loader分開,分開的每一個部分都至關於當前目錄解析,
import Styles from 'style-loader!css-loader?modules!./styles.css';
經過前置全部規則及使用 !。能夠對應覆蓋到配置中的任意loader。
選項能夠傳遞查詢參數,例如 ?key=value&foo=bar
,或者一個 JSON 對象,例如 ?{"key":"value","foo":"bar"}
。
注意 : 儘量使用 module.rules
,由於這樣能夠減小源碼中的代碼量,而且能夠在出錯時,更快地調試和定位 loader 中的問題。
5 CLI
經過CLI來使用loader
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
這會對 .jade文件使用 jade-loader 對.css文件使用style-loader和css-loader
6 loader特性
loader 經過(loader)預處理函數,爲 JavaScript 生態系統提供了更多能力。 用戶如今能夠更加靈活地引入細粒度邏輯,例如壓縮、打包、語言翻譯和其餘更多。
7 解析loader
loader 遵循標準的模塊解析。多數狀況下,loader 將從模塊路徑(一般將模塊路徑認爲是 npm install
, node_modules
)解析。
loader 模塊須要導出爲一個函數,而且使用 Node.js 兼容的 JavaScript 編寫。一般使用 npm 進行管理,可是也能夠將自定義 loader 做爲應用程序中的文件。按照約定,loader 一般被命名爲 xxx-loader
(例如 json-loader
)
六 插件 plugin
插件得目的用於解決loader沒法實現得其餘事.
1 剖析
webpack插件是一個具備apply屬性得JavaScript對象。apply屬性會被webpack compiler 調用,而且comipler對象能夠在整個編譯生命週期訪問。
ConsoleLogOnBuildWebpackPlugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin'; class ConsoleLogOnBuildWebpackPlugin { apply(compiler){ compiler.hook.run.tap(pulginName,compilation =>{ console.log("webpack 構建過程開始!"); }) } }
注意:compiler hook 的 tap 方法的第一個參數,應該是駝峯式命名的插件名稱。建議爲此使用一個常量,以便它能夠在全部 hook 中複用。
2 用法
因爲插件能夠攜帶參數/選項,你必須在 webpack 配置中,向 plugins
屬性傳入 new
實例。
3 配置
webpack.config.js
const config = { entry :'./path/to/my/entry/first.js', output:{ filename:'my-first-webpack.bundle.js', path:path.resolve(_dirname,'dist'), }, module:{ rules:[ { test:/.\(js|jsx)$/, use:'babel-loader' } ] }, plugins:[ new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({template:'./src/index.js'}) ] }; module.exports = config;
4 Node API
注意:即使使用 Node API,用戶也應該在配置中傳入 plugins
屬性。compiler.apply
並非推薦的使用方式。
const webpack = require('webpack'); //訪問 webpack 運行時(runtime) const configuration = require('./webpack.config.js'); let compiler = webpack(configuration); compiler.apply(new webpack.ProgressPlugin()); compiler.run(function(err, stats) { // ... });
七 配置
webpack 的配置文件,是導出一個對象的 JavaScript 文件。此對象,由 webpack 根據對象定義的屬性進行解析。
由於 webpack 配置是標準的 Node.js CommonJS 模塊,你能夠作到如下事情:
require(...)
導入其餘文件require(...)
使用 npm 的工具函數?:
操做符請在合適的時機使用這些特性。
雖然技術上可行,但應避免如下作法:
--env
)時,訪問命令行接口(CLI)參數1 基本配置
webpack.config.js
var path = require('path'); module.exports = { mode: 'development', entry: './foo.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'foo.bundle.js' } };
八 模塊
1 什麼是webpack模塊?
對比node.js模塊,webpack 模塊 可以以各類方式表達它們得依賴關係,以下幾個例子:
require()
語句。define
和 require
語句。url(...)
)或 HTML 文件(<img src=...>
)中的圖片連接(image url)。2 支持模塊類型
webpack 經過 loader 能夠支持各類語言和預處理器編寫模塊。loader 描述了 webpack 如何處理 非 JavaScript(non-JavaScript) _模塊_,而且在bundle中引入這些_依賴_。 webpack 社區已經爲各類流行語言和語言處理器構建了 loader,包括:
九 模塊解析
resolver是一個庫,用於幫助找到模塊得絕對路徑。幫助webpack找到bundle中須要引入得模塊代碼,這些代碼在包含在每一個require/import語句中。當打包模塊時,webpack使用enhanced-resolve來解析文件路徑。
1 webpack中的解析規則
使用enhanced-resolve能夠解析三種文件路徑:
2 絕對路徑
不須要作進一步解析
import "/home/me/file";
import "C:\\User\\me\\file";
3 相對路徑
import "../src/file1";
import "./file2"
在這種狀況下,使用 import
或 require
的資源文件(resource file)所在的目錄被認爲是上下文目錄(context directory)。在 import/require
中給定的相對路徑,會添加此上下文路徑(context path),以產生模塊的絕對路徑(absolute path)。
4 模塊路徑
import "module";
import "module/lib/file";
模塊將會在resolve.modules中指定的全部目錄內搜索,你能夠替換初始模塊路徑,次替換路徑經過使用resolve.alias配置一個別名。
一旦根據上述規則解析路徑後,解析器將檢查路徑是否指向文件或目錄。若是隻想一個文件:
若是路徑指向一個文件夾,則採起一下步驟找到具備正確擴展名的正確文件:
webpack根據構建目標爲這些選項採用合理的默認配置。
5 解析loader 【Resolving Loaders】
Loader解析遵循與文件解析器指定的規則相同的規則。可是resolveLoader 配置選項能夠用來爲Loader提供獨立解析規則。
6 緩存
每一個文件系統訪問都被緩存,以便更快觸發對同一文件的多個並行或串行請求。在觀察模式下,只有修改過的文件會從緩存中摘出。若是關閉觀察模式,在每次編譯前清理緩存。
十 依賴圖 【dependency graph】
任什麼時候候,一個文件依賴於另外一個文件,webpack 就把此視爲文件之間有依賴關係。這使得 webpack 能夠接收非代碼資源(non-code asset)(例如圖像或 web 字體),而且能夠把它們做爲_依賴_提供給你的應用程序。
webpack 從命令行或配置文件中定義的一個模塊列表開始,處理你的應用程序。 從這些入口起點開始,webpack 遞歸地構建一個依賴圖,這個依賴圖包含着應用程序所需的每一個模塊,而後將全部這些模塊打包爲少許的 bundle- 一般只有一個 - 可由瀏覽器加載。
十一 構建目標
1 用法
在webpack配置中設置target的值
webpack.config.js
module.exports={ target:'node' }
在上面例子中,使用node webpack 會編譯爲用於[相似Node.js]環境(使用Node.js的require,而不是使用任意的內置模塊(如 fs或path)來加載chunk)。
每一個target 都有各類部署/環境特定的附加項,以支持知足其需求。
2 多個target
webpack不支持向傳入多個字符串,你能夠經過打包兩份分離配置來建立同構的庫:
webpack.config.js
var path = require('path'); var serverConfig = { target: 'node', output:{ path:path.rsolve(_dirname,dist); fileName:'lib.nade.js' } …… }; var clientConfig = { target:'web', // 默認值是 ‘web’ ,可省略 output:{ path:path.resolve(_dirname,'dist'), filename:'lib.js' } …… }; module.exports=[serverConfig ,clientConfig ];
上面的例子將在你的 dist
文件夾下建立 lib.js
和 lib.node.js
文件。
十二 模塊熱替換
模塊熱替換功能會在應用程序過程當中替換,添加或刪除模塊,而無需從新加載整個頁面。主要是經過如下幾種方式,來顯著加快開發速度。