前面的話
在webpack出現之前,市面上已經存在的模塊管理和打包工具并不適合大型的項目,尤其單頁面 Web 應用程序。最緊迫的原因是如何在一個大規模的代碼庫中,維護各種模塊資源的分割和存放,維護它們之間的依賴關系,并且無縫的將它們整合到一起生成適合瀏覽器端請求加載的靜態資源。webpack是當下最熱門的前端資源模塊化管理和打包工具。它可以將許多松散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還可以將按需加載的模塊進行代碼分隔,等到實際需要的時候再異步加載
webpack的內容豐富且雜亂,對于新手并不友好。本文以一個實例的形式,對webpack的重要概念進行介紹,并著重說明如何使用webpack
概述
webpack是一個模塊打包器。
【特點】
webpack有以下特點
代碼拆分
webpack 有兩種組織模塊依賴的方式,同步和異步。異步依賴作為分割點,形成一個新的塊。在優化了依賴樹后,每一個異步區塊都作為一個文件被打包。
Loader
Webpack 本身只能處理原生的 JavaScript 模塊,但是 loader 轉換器可以將各種類型的資源轉換成 JavaScript 模塊。這樣,任何資源都可以成為 Webpack 可以處理的模塊。
智能解析
Webpack 有一個智能解析器,幾乎可以處理任何第三方庫,無論它們的模塊形式是 CommonJS、 AMD 還是普通的 JS 文件。甚至在加載依賴的時候,允許使用動態表達式 require("./templates/" + name + ".jade")。
插件系統
Webpack 還有一個功能豐富的插件系統。大多數內容功能都是基于這個插件系統運行的,還可以開發和使用開源的 Webpack 插件,來滿足各式各樣的需求。
快速運行
Webpack 使用異步 I/O 和多級緩存提高運行效率,這使得 Webpack 能夠以令人難以置信的速度快速增量編譯
【安裝】
用 npm 安裝 Webpack
$ npm install webpack
一個常見的問題是:安裝webpack后,無法使用webpack命令
這是因為只進行了本地安裝,沒有全局安裝,輸入如下代碼進行全局安裝后即可運行
$ npm install webpack -g
使用
首先創建一個靜態頁面index.html和一個JS入口文件entry.js
<!-- index.html --> <html> <head> <meta charset="utf-8"> </head> <body> <script src="bundle.js"></script> </body> </html>
// entry.js document.write('It works.')
然后編譯 entry.js 并打包到 bundle.js:
$ webpack entry.js bundle.js
打包過程會顯示日志:
Hash: f47511e706e3de8f2417 Version: webpack 2.6.1 Time: 47ms Asset Size Chunks Chunk Names bundle.js 2.66 kB 0 [emitted] main [0] ./entry.js 27 bytes {0} [built]
用瀏覽器打開 index.html
將會看到 It works.

接下來添加一個模塊 module.js
并修改入口 entry.js
:
// module.js module.exports = 'It works from module.js.'
// entry.js document.write('It works.') document.write(require('./module.js')) // 添加模塊
重新打包 webpack entry.js bundle.js
后刷新頁面看到變化 It works.It works from module.js.

Hash: 09733456f2c5b24a4845 Version: webpack 2.6.1 Time: 61ms Asset Size Chunks Chunk Names bundle.js 2.83 kB 0 [emitted] main [0] ./module.js 43 bytes {0} [built] [1] ./entry.js 75 bytes {0} [built]
Webpack會分析入口文件,解析包含依賴關系的各個文件。這些文件(模塊)都打包到 bundle.js 。Webpack 會給每個模塊分配一個唯一的 id 并通過這個 id 索引和訪問模塊。在頁面啟動時,會先執行 entry.js 中的代碼,其它模塊會在運行 require
的時候再執行
Loader
Webpack 本身只能處理 JavaScript 模塊,如果要處理其他類型的文件,就需要使用 loader 進行轉換。
Loader 可以理解為是模塊和資源的轉換器,它本身是一個函數,接受源文件作為參數,返回轉換的結果。詳細信息移步至此
接上面的例子,我們要在頁面中引入一個CSS文件style.css,要使用require("!style-loader!css-loader!./style.css")代碼,代碼讀取順序從右向左,表示首頁將 style.css 也看成是一個模塊,先加載style.css,然后用 css-loader
來讀取它,再用 style-loader
把它插入到頁面中
/* style.css */ body { background: yellow; }
修改 entry.js:
require("style-loader!css-loader!./style.css")
document.write('It works.')
document.write(require('./module.js'))
安裝 loader:
npm install css-loader style-loader
重新編譯打包,刷新頁面,就可以看到黃色的頁面背景了
如果每次 require
CSS 文件的時候都要寫 loader 前綴,是一件很繁瑣的事情。我們可以根據模塊類型(擴展名)來自動綁定需要的 loader。
將 entry.js 中的 require("!style-loader!css-loader!./style.css")
修改為 require("./style.css")
,然后執行
$ webpack entry.js bundle.js --module-bind 'css=style-loader!css-loader'
顯然,這兩種使用 loader 的方式,效果是一樣的

配置
Webpack 在執行的時候,除了在命令行傳入參數,還可以通過指定的配置文件來執行。默認情況下,會搜索當前目錄的 webpack.config.js
文件,這個文件是一個 node.js 模塊,返回一個 json 格式的配置信息對象,或者通過 --config
選項來指定配置文件。
繼續我們的案例,在根目錄創建 package.json
來添加 webpack 需要的依賴:
{ "name": "project", "version": "1.0.0", "devDependencies": { "css-loader": "^0.28.4", "style-loader": "^0.18.2", "webpack": "^2.6.1" } }
別忘了運行 npm install
。然后創建一個配置文件 webpack.config.js
,在下面的配置中,對一個單獨的module對象定義了rules屬性,里面包含兩個必須屬性:test和use。相當于告訴webpack compiler,碰到「在require()/import語句中被解析為'.css'的路徑」時,在把它們添加并打包之前,要先使用css-loader后使用style-loader去轉換
var webpack = require('webpack'); module.exports = { entry: './entry.js', //入口文件 output: { path: __dirname,//出口路徑 filename: 'bundle.js'//出口名稱 }, module: { rules: [ {test: /\.css$/,use: [ 'style-loader', 'css-loader' ]} ] } }
同時簡化 entry.js
中的 style.css
加載方式:
require('./style.css');
最后運行 webpack
,可以看到 webpack 通過配置文件執行的結果和上一節通過命令行 webpack entry.js bundle.js --module-bind 'css=style!css'
執行的結果是一樣的
如果配置文件并不叫做默認的webpack.config.js,而是其他的名稱,如test.js,則需要設置如下命令進行打包
webpack --config test.js
插件
插件可以完成更多 loader 不能完成的功能。插件的使用一般是在 webpack 的配置信息 plugins
選項中指定。Webpack 本身內置了一些常用的插件,還可以通過 npm 安裝第三方插件。詳細信息移步至此
想要使用一個插件,只需要require()它,然后把它添加到plugins數組中。內置插件則不需要require,直接使用即可
接下來,我們利用一個最簡單的 BannerPlugin
內置插件來實踐插件的配置和運行,這個插件的作用是給輸出的文件頭部添加注釋信息。
修改 webpack.config.js
,添加 plugins
:
var webpack = require('webpack'); module.exports = { entry: './entry.js', //入口文件 output: { path: __dirname,//出口路徑 filename: 'bundle.js'//出口名稱 }, module: { rules: [ {test: /\.css$/,use: [ 'style-loader', 'css-loader' ]} ] }, plugins: [ new webpack.BannerPlugin('This file is created by xiaohuochai') ] }
然后運行 webpack
,打開 bundle.js
,可以看到文件頭部出現了我們指定的注釋信息:
/*! This file is created by xiaohuochai */ /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; // 后面代碼省略
開發環境
當項目逐漸變大,webpack 的編譯時間會變長,可以通過參數讓編譯的輸出內容帶有進度和顏色
$ webpack --progress --colors
如果不想每次修改模塊后都重新編譯,那么可以啟動監聽模式。開啟監聽模式后,沒有變化的模塊會在編譯后緩存到內存中,而不會每次都被重新編譯,所以監聽模式的整體速度是很快的
$ webpack --progress --colors --watch
比如,執行以上命令后,修改'style.css'的body的背景顏色為紅色,不用重新編譯,刷新頁面后,頁面即發生改變

當然,使用 webpack-dev-server
開發服務是一個更好的選擇。它將在 localhost:8080 啟動一個 express 靜態資源 web 服務器,并且會以監聽模式自動運行 webpack,在瀏覽器打開 http://localhost:8080/ 或 http://localhost:8080/webpack-dev-server/ 可以瀏覽項目中的頁面和編譯后的資源輸出,并且通過一個 socket.io 服務實時監聽它們的變化并自動刷新頁面
# 安裝 $ npm install webpack-dev-server -g # 運行 $ webpack-dev-server --progress --colors
比如,執行以上命令后,修改'style.css'的body的背景顏色為藍色,不用重新編譯,也不用刷新頁面,頁面即發生改變

文章列表