Webpack使用指南
Webpack 是當下最熱門的前端資源模塊化管理和打包工具。
什么是webpack
Webpack 是當下最熱門的前端資源模塊化管理和打包工具。它可以將許多松散的模塊按照依賴和規則打包成符合生產環境部署的前端資源。還可以將按需加載的模塊進行代碼分隔,等到實際需要的時候再異步加載。通過 loader 的轉換,任何形式的資源都可以視作模塊,比如 CommonJs 模塊、 AMD 模塊、 ES6 模塊、CSS、圖片、 JSON、Coffeescript、 LESS 等。
Webpack 的特點
Webpack 和其他模塊化工具有什么區別呢?
- 代碼拆分
Webpack 有兩種組織模塊依賴的方式,同步和異步。異步依賴作為分割點,形成一個新的塊。在優化了依賴樹后,每一個異步區塊都作為一個文件被打包。 - Loader
Webpack 本身只能處理原生的 JavaScript 模塊,但是 loader 轉換器可以將各種類型的資源轉換成 JavaScript 模塊。這樣,任何資源都可以成為 Webpack 可以處理的模塊。 - 智能解析
Webpack 有一個智能解析器,幾乎可以處理任何第三方庫,無論它們的模塊形式是 CommonJS、 AMD 還是普通的 JS 文件。甚至在加載依賴的時候,允許使用動態表達式 require("./templates/" + name + ".jade")。 - 插件系統
Webpack 還有一個功能豐富的插件系統。大多數內容功能都是基于這個插件系統運行的,還可以開發和使用開源的 Webpack 插件,來滿足各式各樣的需求。 - 快速運行
Webpack 使用異步 I/O 和多級緩存提高運行效率,這使得 Webpack 能夠以令人難以置信的速度快速增量編譯。
開始使用
安裝
首先要安裝 Node.js, Node.js 自帶了軟件包管理器 npm,Webpack可以通過npm去安裝。
用 npm 安裝 Webpack:
$ npm install webpack -g此時 Webpack 已經安裝到了全局環境下,可以通過命令行 webpack -h 試試。
通常我們會將 Webpack 安裝到項目的依賴中,這樣就可以使用項目本地版本的 Webpack。
# 進入項目目錄 # 確定已經有 package.json,沒有就通過 npm init 創建 # 安裝 webpack 依賴 $ npm install webpack --save-dev查看webpack
# 查看 webpack 版本信息 $ npm info webpack安裝指定版本的 webpack
$ npm install webpack@1.12.x --save-dev如果需要使用 Webpack 開發工具,要單獨安裝:
$ npm install webpack-dev-server --save-dev使用
首先創建一個靜態頁面 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: e964f90ec65eb2c29bb9 Version: webpack 1.12.2 Time: 54msAsset Size Chunks Chunk Names bundle.js 1.42 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: 279c7601d5d08396e751 Version: webpack 1.12.2 Time: 63msAsset Size Chunks Chunk Names bundle.js 1.57 kB 0 [emitted] main[0] ./entry.js 66 bytes {0} [built][1] ./module.js 43 bytes {0} [built]Webpack 會分析入口文件,解析包含依賴關系的各個文件。這些文件(模塊)都打包到 bundle.js 。Webpack 會給每個模塊分配一個唯一的 id 并通過這個 id 索引和訪問模塊。在頁面啟動時,會先執行 entry.js 中的代碼,其它模塊會在運行 require 的時候再執行。
Loader
Webpack 本身只能處理 JavaScript 模塊,如果要處理其他類型的文件,就需要使用 loader 進行轉換。
Loader 可以理解為是模塊和資源的轉換器,它本身是一個函數,接受源文件作為參數,返回轉換的結果。這樣,我們就可以通過 require 來加載任何類型的模塊或文件,比如 CoffeeScript、 JSX、 LESS 或圖片。
先來看看 loader 有哪些特性?
- Loader 可以通過管道方式鏈式調用,每個 loader 可以把資源轉換成任意格式并傳遞給下一個 loader ,但是最后一個 loader 必須返回 JavaScript。
- Loader 可以同步或異步執行。
- Loader 運行在 node.js 環境中,所以可以做任何可能的事情。
- Loader 可以接受參數,以此來傳遞配置項給 loader。
- Loader 可以通過文件擴展名(或正則表達式)綁定給不同類型的文件。
- Loader 可以通過 npm 發布和安裝。
- 除了通過 package.json 的 main 指定,通常的模塊也可以導出一個 loader 來使用。
- Loader 可以訪問配置。
- 插件可以讓 loader 擁有更多特性。
- Loader 可以分發出附加的任意文件。
loader 一般以?xxx-loader?的方式命名,xxx 代表了這個 loader 要做的轉換功能,比如?json-loader。
Loader 可以在 require() 引用模塊的時候添加,也可以在 webpack 全局配置中進行綁定,還可以通過命令行的方式使用。
接上一節的例子,我們要在頁面中引入一個 CSS 文件 style.css,首頁將 style.css 也看成是一個模塊,然后用 css-loader 來讀取它,再用 style-loader 把它插入到頁面中。
/* style.css */ body { background: yellow; }修改 entry.js:
require("!style-loader!css-loader!./style.css") // 載入 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!css' # 有些環境下可能需要使用雙引號 $ webpack entry.js bundle.js --module-bind "css=style!css"顯然,這兩種使用 loader 的方式,效果是一樣的。
配置文件
Webpack 在執行的時候,除了在命令行傳入參數,還可以通過指定的配置文件來執行。默認情況下,會搜索當前目錄的 webpack.config.js 文件,這個文件是一個 node.js 模塊,返回一個 json 格式的配置信息對象,或者通過 --config 選項來指定配置文件。
示例
創建一個配置文件 webpack.config.js:
var webpack = require('webpack')module.exports = {entry: './entry.js',output: {path: __dirname,filename: 'bundle.js'},module: {loaders: [{test: /\.css$/,loader: 'style-loader!css-loader'}]} }webpack.config.js參數詳解
webpack.config.js文件通常放在項目的根目錄中,它本身也是一個標準的Commonjs規范的模塊。在導出的配置對象中有幾個關鍵的參數:
entry
entry參數定義了打包后的入口文件,有三種寫法,每個入口稱為一個chunk:
| 字符串 | entry: "./index/index.js" | 配置模塊會被解析為模塊,并在啟動時加載。 chunk名為默認為main, 具體打包文件名視output配置而定。? |
| 數組 | entry: ['./src/mod1.js', [...,] './src/index.js'] | 所有的模塊會在啟動時?按照配置順序? 加載,合并到最后一個模塊會被導出。chunk名默認為main |
| 對象 | entry:{index: '...', login : [...]} | 如果傳入Object,則會生成多個入口打包文件 key是chunk名,value可以是字符串,也可是數組。 |
該段代碼最終會生成一個 page1.bundle.js 和 page2.bundle.js,并存放到 ./dist/js/page 文件夾下
output
output參數是個對象,定義了輸出文件的位置及名字:
output: {path: "dist/js/page",publicPath: "/output/",filename: "[name].bundle.js"}- path: 打包文件存放的絕對路徑
- publicPath: 網站運行時的訪問路徑
- filename:打包后的文件名
當我們在entry中定義構建多個文件時,filename可以對應的更改為[name].js用于定義不同文件構建后的名字。
module
在webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,圖片等靜態文件都是模塊,不同模塊的加載是通過模塊加載器(webpack-loader)來統一管理的。loaders之間是可以串聯的,一個加載器的輸出可以作為下一個加載器的輸入,最終返回到JavaScript上: loader使用需要先安裝再加入到配置下中。
Loaders需要單獨安裝并且需要在webpack.config.js下的modules關鍵字下進行配置,Loaders的配置選項包括以下幾方面:
- test:一個匹配loaders所處理的文件的拓展名的正則表達式(必須)
- loader:loader的名稱(必須)
- include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不需要處理的文件(文件夾)(可選);
- query:為loaders提供額外的設置選項(可選)
loaders之 預處理
- css-loader 處理css中路徑引用等問題
- style-loader 動態把樣式寫入css
- sass-loader scss編譯器
- less-loader less編譯器
- postcss-loader scss再處理?
loaders之 react處理
babel-loader?babel官網
// npm一次性安裝多個依賴模塊,模塊之間用空格隔開 npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react module: {loaders: [{test:/\.jsx?$/,exclude:/node_modules/,loader:'babel',query:{presets:['react','es2015']}}] }loaders之 es6轉化處理
- babel-loader 以及 babel-preset-es2015
- 安裝 以上兩個插件 npm install babel-loader --save-devnpm install babel-preset-es2015 --save-dev
- 創建bable的配置文件
loaders之 圖片處理
- url-loader
對于上面的配置,如果圖片資源小于10kb就會轉化成 base64 格式的 dataUrl,其他的圖片會存放在build/images文件夾下。
loaders之 文件處理
- file-loader?
示例
module: {//加載器配置loaders: [//.css 文件使用 style-loader 和 css-loader 來處理{ test: /\.css$/, loader: 'style-loader!css-loader' },//.scss 文件使用 style-loader、css-loader 和 sass-loader 來編譯處理{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},//圖片文件使用 url-loader 來處理,小于8kb的直接轉為base64{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}]}插件(Plugins)
插件(Plugins)是用來拓展Webpack功能的,它們會在整個構建過程中生效,執行相關的任務。
Webpack有很多內置插件,同時也有很多第三方插件,可以讓我們完成更加豐富的功能。
使用插件的方法
要使用某個插件,我們需要通過npm安裝它,然后要做的就是在webpack配置中的plugins關鍵字部分添加該插件的一個實例(plugins是一個數組)繼續看例子,我們添加了一個實現版權聲明的插件。
module.exports = {plugins: [new webpack.BannerPlugin("Copyright Nico inc.")//在這個數組中new一個就可以了] }HtmlWebpackPlugin
這個插件的作用是依據一個簡單的模板,幫你生成最終的HTML5文件,這個文件中自動引用了你打包后的JS文件。每次編譯都在文件名中插入一個不同的哈希值。
安裝
npm install --save-dev html-webpack-plugin這個插件自動完成了我們之前手動做的一些事情,在正式使用之前需要對一直以來的項目結構做一些改變:
在app目錄下,創建一個Html文件模板,這個模板包含title等其它你需要的元素,在編譯過程中,本插件會依據此模板生成最終的html頁面,會自動添加所依賴的 css, js,favicon等文件,在本例中我們命名模板文件名稱為index.tmpl.html,模板源代碼如下
index.tmpl.html
<!DOCTYPE html> <html lang="en"><head><meta charset="utf-8"><title>Webpack</title></head><body><div id='box'></div></body> </html>webpack.config.js
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = {plugins: [new HtmlWebpackPlugin({template: __dirname + "/app/index.tmpl.html"//new 一個這個插件的實例,并傳入相關的參數})] }ExtractTextPlugin
分離CSS和JS文件
安裝
npm install --save-dev extract-text-webpack-pluginwebpack.config.js
var webpack = require('webpack'); var ExtractTextPlugin = require('extract-text-webpack-plugin');...plugins: [new HtmlWebpackPlugin({template: __dirname + "/app/index.tmpl.html"}),new webpack.optimize.OccurenceOrderPlugin(),new webpack.optimize.UglifyJsPlugin(),new ExtractTextPlugin("style.css")] }合并公共代碼
項目中,對于一些常用的組件,站點公用模塊經常需要與其他邏輯分開,然后合并到同一個文件,以便于長時間的緩存。要實現這一功能,配置參照:
var webpack = require('webpack'); var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;··· entry: {a: './index/a.js',b: './idnex/b.js',c: './index/c.js',d: './index/d.js' }, ··· plugins: [new CommonsChunkPlugin('part.js', ['a', 'b']),new CommonsChunkPlugin('common.js', ['part1', 'c']) ] ···代碼壓縮
webpack 自帶了一個壓縮插件 UglifyJsPlugin,只需要在配置文件中引入即可。
{plugins: [new webpack.optimize.UglifyJsPlugin({compress: {warnings: false}})] }加入了這個插件之后,編譯的速度會明顯變慢,所以一般只在生產環境啟用。
其他用法
緩存
緩存無處不在,使用緩存的最好方法是保證你的文件名和文件內容是匹配的(內容改變,名稱相應改變) webpack可以把一個哈希值添加到打包的文件名中,使用方法如下,添加特殊的字符串混合體([name], [id] and [hash])到輸出文件名前
var webpack = require('webpack'); var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin');module.exports = {entry: __dirname + "/app/main.js",output: {path: __dirname + "/build",filename: "[name]-[hash].js"},module: {},plugins: [new HtmlWebpackPlugin({template: __dirname + "/app/index.tmpl.html"}),new webpack.optimize.OccurenceOrderPlugin(),new webpack.optimize.UglifyJsPlugin(),new ExtractTextPlugin("[name]-[hash].css")] }去除多個文件中的頻繁依賴
當我們經常使用React、jQuery等外部第三方庫的時候,通常在每個業務邏輯JS中都會遇到這些庫。? 如我們需要在各個文件中都是有jQuery的$對象,因此我們需要在每個用到jQuery的JS文件的頭部通過require('jquery')來依賴jQuery。 這樣做非常繁瑣且重復,因此webpack提供了我們一種比較高效的方法,我們可以通過在配置文件中配置使用到的變量名,那么webpack會自動分析,并且在編譯時幫我們完成這些依賴的引入。
webpack.config.js中
var webpack = require('webpack');... plugins: [new webpack.ProvidePlugin({'Moment': 'moment',"$": "jquery","jQuery": "jquery","window.jQuery": "jquery","React": "react"}) ] ...設置環境命令
要告訴webpack我們希望當前是什么環境,只需要在命令中寫入?BUILD_DEV=1 webpck?那么webpack通過配置,就會將所有我們引用到的__DEV__變量設置為true。
我們可以在package.json中事先定義好命令:
"scripts": {"dev": "BUILD_DEV=1 webpack-dev-server --progress --colors","build": "BUILD_PRERELEASE=1 webpack -p" }那么就可以避免輸入冗長的命令了:
開發時輸入:
npm run dev發布時輸入:
npm run build常用命令
?webpack的使用和browserify有些類似,下面列舉幾個常用命令:
webpack 最基本的啟動webpack命令 webpack -w 提供watch方法,實時進行打包更新 webpack -p 對打包后的文件進行壓縮 webpack -d 提供SourceMaps,方便調試 webpack --colors 輸出結果帶彩色,比如:會用紅色顯示耗時較長的步驟 webpack --profile 輸出性能數據,可以看到每一步的耗時 webpack --display-modules 默認情況下 node_modules 下的模塊會被隱藏,加上這個參數可以顯示這些被隱藏的模塊目錄結構
/├── shell/ 腳本│├── conf/ 工程配置│├── src/ 開發目錄│ ├── components/ 組件│ ├── pages/ 頁面│ ├──├── dist/ 自動生成│├── test/ 測試│├── node_modules/ 自動生成,包含.Node 依賴以及開發依賴│├── static/ 庫文件等,不會被webpack的loader處理,手動管理│└── etc完整的目錄結構:
projectTemplate/ ├── shell/ node腳本 │ ├──│ ├── dev-server.js 本地開發服務器│ ├── build.js 打包腳本│ ├── utils.js 工具函數│ ├── ├── conf/ 工程配置 │ ├──│ ├── index.js 基礎配置文件,在此可簡單的修改webpack相關配置│ ├── webpack.base.js webpack的基礎配置,主要是loader、resolve的配置│ ├── webpack.dev.js webpack開發配置,主要是eslint、livereload、hot module replacement及相關的插件│ ├── webpack.prod.js webpack生產配置,主要是代碼的壓縮混淆,圖片壓縮,加hash│ ├── karma.conf.js 測試配置│ ├──├── src/ 開發目錄│ ├── components/ 組件│ ├── pages/ 頁面(頁面下的項目目錄需要遵循一定的規范以便創建webpack的入口文件,不過這些規范是可以調整的;以下只是推薦)│ ├── index/ 首頁│ ├── images/ 圖片資源│ ├── page.css 樣式文件,文件名稱可以按照自己意愿命名│ ├── page.js 腳本文件及webpack的入口文件,文件名稱可以在/conf/index.js配置│ ├── template.html 模板文件及要撰寫的html文件,文件名稱可以在/conf/index.js配置│ ├──│ ├── dist/ 自動生成│ ├── test/ 測試(目錄可以意愿來創建,但是測試文件名稱必須遵循*_test.js的命名規范,可在/conf/karma.conf.js修改配置)│ ├── node_modules/ 自動生成,包含node依賴以及開發依賴│ ├── static/ 庫文件等,不會被webpack的loader處理,手動管理│ └── etc使用webpack構建本地服務器
想不想讓你的瀏覽器監測你都代碼的修改,并自動刷新修改后的結果,其實Webpack提供一個可選的本地開發服務器,這個本地服務器基于node.js構建,可以實現你想要的這些功能,不過它是一個單獨的組件,在webpack中進行配置之前需要單獨安裝它作為項目依賴
npm install --save-dev webpack-dev-serverdevserver作為webpack配置選項中的一項,具有以下配置選項
| contentBase | 默認webpack-dev-server會為根文件夾提供本地服務器, 如果想為另外一個目錄下的文件提供本地服務器, 應該在這里設置其所在目錄(本例設置到“public"目錄) |
| port | 設置默認監聽端口,如果省略,默認為”8080“ |
| inline | 設置為true,當源文件改變時會自動刷新頁面 |
| colors | 設置為true,使終端輸出的文件為彩色的 |
| historyApiFallback | 在開發單頁應用時非常有用,它依賴于HTML5 history API, 如果設置為true,所有的跳轉將指向index.html |
如下配置:
module.exports = {...devServer: {contentBase: "./public",//本地服務器所加載的頁面所在的目錄colors: true,//終端中輸出結果為彩色historyApiFallback: true,//不跳轉inline: true//實時刷新} }轉載于:https://www.cnblogs.com/zhangruiqi/p/7656206.html
總結
以上是生活随笔為你收集整理的Webpack使用指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怀孕没有梦到蛇预示着什么
- 下一篇: 程序猿值得看的几个技术网站(记录)