一、概述
webpack is a tool to build JavaScript modules in your application. webpack simplifies your workflow by quickly constructing a dependency graph of your application and bundling them in the right order. webpack can be configured to customise optimisations to your code, to split vendor/css/js code for production, run a development server that hot-reloads your code without page refresh and many such cool features.
webpack是一款前端資源子產品化管理和打包的工具。它可以将子產品按照依賴和規則進行打包,還可以将按需加載的子產品進行代碼分離,實作異步加載。通過加載器,任何形式的資源都可以被看作成子產品。
Github位址
從一個主檔案開始,依次尋找項目的所有依賴檔案,通過加載器進行處理,最後打包成浏覽器能夠識别的JavaScript檔案。
二、特點
webpack和其他子產品化工具相比,具有如下特點:
-
代碼分離
webpack有兩種組織子產品依賴的方式:同步和異步。異步依賴會将代碼分離成不同的區塊,每一個區塊都作為一個檔案被打包。
-
加載器
webpack自身隻能處理原生的JavaScript子產品,通過加載器,可以将不同類型的資源轉換成JavaScript子產品。換句話說,任何資源都可以被webpack當成子產品來處理。
-
智能解析
webpack通過智能解析器,幾乎可以處理任何的第三方庫。并且在加載依賴的時候,允許使用動态表達式進行加載。
-
插件
webpack還提供了插件系統,大多數功能都是基于這個插件系統運作的。可以通過開發和使用webpack插件,滿足不同的需求。
-
運作效率
webpack通過異步I/O和多級緩存,大大提高了運作效率,能夠快速地實作增量編譯。
三、概念
為了能夠更好地了解和使用webpack,首先需要了解webpack的四大核心概念:
-
入口entry
webpack為應用程式的所有依賴建立了一個圖表,這個圖表的起始點被稱為入口點。入口點會告訴webpack從哪裡開始,并且根據依賴圖表,清楚哪些資源會被打包。
屬性用來定義入口點。entry
-
輸出output
一旦将資源打包在一起之後,需要告訴webpack将要把應用程式打包到何處。
屬性用來描述打封包件的位置。output
-
加載器loaders
當非JavaScript資源被添加到依賴圖表時,通過加載器将這些檔案轉換成子產品。
屬性用來定義要轉換的檔案類型。test
屬性指定加載器的類型。use
-
插件plugins
相對于加載器隻能基于每個檔案進行轉換,插件通常用來針對複雜應用執行操作和自定義功能。要想使用插件,首先需要使用require()方法引入插件子產品,然後在plugins數組中,建立一個該插件的執行個體。
四、安裝和配置
1、安裝Node.js
由于webpack需要使用npm進行安裝,是以應該首先安裝Node.js。
2、安裝webpack
通常不建議使用
$ npm install webpack -g
指令進行全局安裝。而是将webpack安裝到項目的依賴中,這樣,就可以使用項目本地版本的webpack。
進入到項目目錄,建立一個package.json檔案:
npm init
安裝webpack依賴:
npm install webpack --save-dev
也可以指定版本進行安裝:
npm install webpack@<version> --save-dev
如果需要使用webpack開發工具,需要單獨安裝:
$ npm install webpack-dev-server --save-dev
3、運作
如果采用非全局安裝,執行如下指令進行打包:
node_modules/.bin/webpack app/index.js public/bundle.js
其中,index.js是入口檔案,bundle.js是目标檔案。
4、配置
除了使用指令行運作webpack的方式,更好的方法是使用配置檔案
webpack.config.js
。它是一個node.js子產品,傳回一個json格式的配置資訊對象。也可以通過
--config
選項指定配置檔案。
module.exports = {
entry: __dirname + "/app/index.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
}
}
其中,
entry
屬性指向入口檔案,
output
屬性指定打包後檔案存放的位置,
__dirname
指向目前執行腳本所在的目錄。
此時,執行
node_modules/.bin/webpack
指令,會自動參考配置檔案中的配置選項打包項目。
還有一種更快捷的運作方式。在package.json中設定npm的腳本:
"scripts": {
"start": "webpack" // 将npm的start指令指向webpack指令
},
這樣,直接執行
npm start
指令,就會自動運作webpack進行打包。
五、用法
webpack很多強大的功能,都是通過一系列可供配置選項完成的。這裡主要介紹一些常用的選項。
1、開發工具devtool
開發工具主要用來友善調試,提高開發效率。通過打包之後的檔案,不太容易找到出現錯誤的地方對應的源碼位置。這時,可以使用Source Map來解決這個問題。
devtool: "source-map"
devtool
屬性有四種不同的選項值:
- source-map,在一個單獨的檔案中産生一個完整且功能完全的檔案。這個檔案具有良好的source map,但會降低打封包件的建構速度。
- cheap-module-source-map,在一個單獨的檔案中生成一個不帶列映射的map,能夠相應地提高建構速度,但不能對應到具體的列,會對調試造成不便。
- eval-source-map,使用eval打包源檔案子產品,在同一個檔案中生成幹淨且完整的source map,不會影響建構速度,但輸出的js檔案存在性能和安全隐患。建議在開發階段使用,一定不要在生産階段使用此選項。
- cheap-module-eval-source-map,能夠以最快的速度生成source map,生成的source map和打包後的js檔案同行顯示,沒有列映射。同樣建議隻在開發階段使用。
Tips:在開發階段使用eval-source-map選項。
2、本地伺服器devserver
開發過程中,希望浏覽器能夠監測到代碼的修改,并自動重新整理,顯示修改之後的結果。這時,可以配置devserver建構本地伺服器來完成這些功能。
devServer: {
contentBase: "./public",
inline: true,
colors: true,
historyApiFallback: true
}
因為本地伺服器是一個單獨元件,是以在配置之前需要單獨安裝:
npm install webpack-dev-server --save-dev
devserver
屬性有如下配置選項:
- contentBase,預設情況下,為根檔案夾提供本地伺服器。如果想為其他目錄提供本地伺服器,可以在此選項設定目錄。
- port,設定監聽端口,預設為8080。
- inline,設定為true時,當源檔案發生改變會自動重新整理頁面。
- colors,設定為true時,終端輸出的結果為彩色的。
- historyApiFallback,設定為true時,所有的跳轉都指向index.html,主要用于單頁面應用。
3、加載器loaders
Loaders是webpack最強大的功能之一。通過使用不同的loader,webpack調用外部的腳本或工具,可以對各種格式的檔案進行處理。
Loaders需要單獨安裝:
npm install json-loader --save-dev
并且需要在
modules
屬性下進行配置:
module: {
loaders: [
{
test: /.json$/,
loader: "json"
}
]
}
loaders
屬性有如下配置選項:
- test,比對loaders所處理檔案的擴充名的正規表達式(必須)。
- loader,loader的名稱(必須)。
- include,添加必須處理的檔案夾或檔案(可選)。
- exclude,屏蔽不需要處理的檔案夾或檔案(可選)。
- query,為loaders提供額外的設定選項(可選)。
webpack提供了很多有用的loader,如css-loader和style-loader,用來處理樣式表。css-loader能夠使用類似@import和url()的方法實作require()的功能,而style-loader則将所有計算後的樣式加到頁面中。
安裝:
npm install style-loader css-loader --save-dev
配置:
module: {
loaders: [
{
test: /.css$/,
loader: "style!css"
}
]
}
其中,“!"表示同一檔案能夠使用不同類型的loader。
Sass或Less之類的預處理器是對原生CSS的拓展,不同類型的預處理器也對應不同的loader。webpack還提供一個CSS處理平台PostCSS,可以使CSS能夠實作更多功能。使用PostCSS可以為CSS代碼自動添加适應不同浏覽器的CSS字首。
安裝:
npm install postcss-loader autoprefixer --save-dev
配置:
postcss: [
require('autoprefixer')
]
Babel是一個編譯JavaScript的平台,它支援下一代的JavaScript标準(如:ES6),以及基于JavaScript進行拓展的語言(如:JSX)。
安裝:
npm install babel-core babel-loader babel-preset-es2015 --save-dev
配置:
module: {
loaders: [
{
test: /.js$/,
exclude: /node_modules/,
loader: "babel",
query: {
presets: ['es2015']
}
}
]
}
4、插件plugins
webpack的另一個強大功能。在整個建構過程中,執行相關任務,拓展webpack功能。webpack有很多内置插件,同時也有很多第三方插件。
要想使用插件,首先需要安裝:
npm install html-webpack-plugin --save-dev
然後在
plugins
屬性中添加該插件的一個執行個體:
plugins: [
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html"
})
]
Hot Module Replacement(HMR)也是webpack中很實用的插件,允許在修改元件代碼後,自動重新整理實時預覽修改後的效果。
實作HMR隻需要進行如下幾項配置。
在plugins中添加HMR插件:
new webpack.HotModuleReplacementPlugin()
在devserver中添加hot屬性:
hot: true
在js子產品中執行webpack提供的API。
5、産品建構
雖然以上内容可以建構一個完整的開發環境,但在産品階段,可能還需要對打包的檔案進行額外的處理,如:優化、壓縮、緩存、代碼分離等。
- OccurenceOrderPlugin,為元件配置設定ID,webpack可以分析和優先考慮使用最多的子產品,并為其配置設定最小的ID。
- UglifyJsPlugin,壓縮js代碼
- ExtractTextPlugin,分離css和js檔案
使用緩存最好的方法是保證檔案名和檔案内容相比對。webpack可以把一個哈希值添加到打包的檔案名中。
output: {
path: __dirname + "/build",
filename: "[name]-[hash].js"
}
參考文章:
入門Webpack