查看全部文檔頁面: 全棧開發,獲取更多信息。原文連接:第2章 配置,原文廣告模態框遮擋,閱讀體驗很差,因此整理成本文,方便查找。css
配置 Webpack 的方式有兩種:html
webpack.config.js
文件裏的配置;webpack --devtool source-map
。這兩種方式能夠相互搭配,例如執行 Webpack 時經過命令 webpack --config webpack-dev.config.js
指定配置文件,再去 webpack-dev.config.js
文件裏描述部分配置。node
按照配置所影響的功能來劃分,可分爲:react
Webpack 在尋找相對路徑的文件時會以 context 爲根目錄,context 默認爲執行啓動 Webpack 時所在的當前工做目錄。jquery
若是想改變 context 的默認配置,能夠在配置文件裏設置:webpack
module.exports = { context: path.resolve(__dirname, 'app') }
注意, context 必須是一個絕對路徑的字符串。 除此以外,還能夠經過在啓動 Webpack 時帶上參數 webpack --context
來設置 context。web
Webpack 會爲每一個生成的 Chunk 取一個名稱,Chunk 的名稱和 Entry 的配置有關:正則表達式
string
或 array
,就只會生成一個 Chunk,這時 Chunk 的名稱是 main
;object
,就可能會出現多個 Chunk,這時 Chunk 的名稱是 object
鍵值對裏鍵的名稱。假如項目裏有多個頁面須要爲每一個頁面的入口配置一個 Entry ,但這些頁面的數量可能會不斷增加,則這時 Entry 的配置會受到到其餘因素的影響致使不能寫成靜態的值。其解決方法是把 Entry 設置成一個函數去動態返回上面所說的配置,代碼以下:npm
// 同步函數 entry: () => { return { a:'./pages/a', b:'./pages/b', } }; // 異步函數 entry: () => { return new Promise((resolve)=>{ resolve({ a:'./pages/a', b:'./pages/b', }); }); };
output
配置如何輸出最終想要的代碼。output
是一個 object
,裏面包含一系列配置項:json
output.filename
配置輸出文件的名稱,爲 string 類型。 若是隻有一個輸出文件,則能夠把它寫成靜態不變的:
filename: 'bundle.js'
可是在有多個 Chunk 要輸出時,就須要藉助模版和變量了。前面說到 Webpack 會爲每一個 Chunk取一個名稱,能夠根據 Chunk 的名稱來區分輸出的文件名:
filename: '[name].js'
代碼裏的 [name]
表明用內置的 name
變量去替換[name]
,這時你能夠把它看做一個字符串模塊函數, 每一個要輸出的 Chunk 都會經過這個函數去拼接出輸出的文件名稱。
變量名 | 含義 |
---|---|
id | Chunk 的惟一標識,從0開始 |
name | Chunk 的名稱 |
hash | Chunk 的惟一標識的 Hash 值 |
chunkhash | Chunk 內容的 Hash 值 |
其中 hash
和 chunkhash
的長度是可指定的,[hash:8]
表明取8位 Hash 值,默認是20位。
注意 ExtractTextWebpackPlugin 插件是使用contenthash
來表明哈希值而不是chunkhash
, 緣由在於 ExtractTextWebpackPlugin 提取出來的內容是代碼內容自己而不是由一組模塊組成的 Chunk。
output.chunkFilename
配置無入口的 Chunk 在輸出時的文件名稱。 chunkFilename
和上面的 filename
很是相似,但 chunkFilename 只用於指定在運行過程當中生成的 Chunk 在輸出時的文件名稱。 常見的會在運行時生成 Chunk 場景有在使用 CommonChunkPlugin
、使用 import('path/to/module')
動態加載等時。 chunkFilename 支持和 filename 一致的內置變量。
path
output.path
配置輸出文件存放在本地的目錄,必須是 string 類型的絕對路徑。一般經過 Node.js 的 path
模塊去獲取絕對路徑:
path: path.resolve(__dirname, 'dist_[hash]')
在複雜的項目裏可能會有一些構建出的資源須要異步加載,加載這些異步資源須要對應的 URL 地址。
output.publicPath
配置發佈到線上資源的 URL 前綴,爲string 類型。 默認值是空字符串 ''
,即便用相對路徑。
把構建出的資源文件上傳到 CDN 服務上,以利於加快頁面的打開速度。配置代碼以下:
filename:'[name]_[chunkhash:8].js' publicPath: 'https://cdn.example.com/assets/'
這時發佈到線上的 HTML 在引入 JavaScript 文件時就須要:
<script src='https://cdn.example.com/assets/a_12345678.js'></script>
使用該配置項時要當心,稍有不慎將致使資源加載404錯誤。
output.path
和 output.publicPath
都支持字符串模版,內置變量只有一個:hash
表明一次編譯操做的 Hash 值。
Webpack 輸出的部分代碼塊可能須要異步加載,而異步加載是經過 JSONP
方式實現的。 JSONP
的原理是動態地向 HTML 中插入一個 <script src="url"></script>
標籤去加載異步資源。
output.crossOriginLoading
則是用於配置這個異步插入的標籤的 crossorigin
值。
script 標籤的 crossorigin
屬性能夠取如下值:
false
(默認) 在加載此腳本資源時不會帶上用戶的 Cookies;use-credentials
在加載此腳本資源時會帶上用戶的 Cookies。一般用設置 crossorigin
來獲取異步加載的腳本執行時的詳細錯誤信息。
當用 Webpack 去構建一個能夠被其餘模塊導入使用的庫時須要用到它們。
output.libraryTarget
配置以何種方式導出庫。output.library
配置導出庫的名稱。假如配置了 output.library='LibraryName'
,則輸出和使用的代碼以下:
// Webpack 輸出的代碼 var LibraryName = lib_code; // 使用庫的方法 LibraryName.doSomething();
假如 output.library
爲空,則將直接輸出:lib_code
其中
lib_code
代指導出庫的代碼內容,是有返回值的一個自執行函數。
它們一般搭配在一塊兒使用。
output.libraryTarget
是字符串的枚舉類型,支持如下配置。
編寫的庫將經過 var
被賦值給經過 library
指定名稱的變量。
編寫的庫將經過 CommonJS2 規範導出,輸出和使用的代碼以下:
// Webpack 輸出的代碼 module.exports = lib_code; // 使用庫的方法 require('library-name-in-npm').doSomething();
CommonJS2 和 CommonJS 規範很類似,差異在於 CommonJS 只能用exports
導出,而 CommonJS2 在 CommonJS 的基礎上增長了module.exports
的導出方式。
在 output.libraryTarget
爲 commonjs2 時,配置 output.library
將沒有意義。
編寫的庫將經過 this
被賦值給經過 library
指定的名稱,輸出和使用的代碼以下:
// Webpack 輸出的代碼
this['LibraryName'] = lib_code;
// 使用庫的方法
this.LibraryName.doSomething();
編寫的庫將經過 window
被賦值給經過 library
指定的名稱,即把庫掛載到 window
上,輸出和使用的代碼以下:
// Webpack 輸出的代碼 window['LibraryName'] = lib_code; // 使用庫的方法 window.LibraryName.doSomething();
編寫的庫將經過 global
被賦值給經過 library
指定的名稱,即把庫掛載到 global
上,輸出和使用的代碼以下:
// Webpack 輸出的代碼 global['LibraryName'] = lib_code; // 使用庫的方法 global.LibraryName.doSomething();
output.libraryExport
配置要導出的模塊中哪些子模塊須要被導出。 它只有在 output.libraryTarget
被設置成 commonjs
或者 commonjs2
時使用纔有意義。
假如要導出的模塊源代碼是:
export const a=1; export default b=2;
如今想讓構建輸出的代碼只導出其中的 a
,能夠把 output.libraryExport
設置成 a
,那麼構建輸出的代碼和使用方法將變成以下:
// Webpack 輸出的代碼 module.exports = lib_code['a']; // 使用庫的方法 require('library-name-in-npm')===1;
rules
配置模塊的讀取和解析規則,一般用來配置 Loader
。其類型是一個數組,數組裏每一項都描述瞭如何去處理部分文件。 配置一項 rules
時大體經過如下方式:
test
、 include
、 exclude
三個配置項來命中 Loader 要應用規則的文件。use
配置項來應用 Loader,能夠只應用一個 Loader 或者按照從後往前的順序應用一組 Loader,同時還能夠分別給 Loader 傳入參數。enforce
選項可讓其中一個 Loader 的執行順序放到最前或者最後。module: { rules: [ { // 命中 JavaScript 文件 test: /\.js$/, // 用 babel-loader 轉換 JavaScript 文件 // ?cacheDirectory 表示傳給 babel-loader 的參數,用於緩存 babel 編譯結果加快從新編譯速度 use: ['babel-loader?cacheDirectory'], // 只命中src目錄裏的js文件,加快 Webpack 搜索速度 include: path.resolve(__dirname, 'src') }, { // 命中 SCSS 文件 test: /\.scss$/, // 使用一組 Loader 去處理 SCSS 文件。 // 處理順序爲從後到前,即先交給 sass-loader 處理,再把結果交給 css-loader 最後再給 style-loader。 use: ['style-loader', 'css-loader', 'sass-loader'], // 排除 node_modules 目錄下的文件 exclude: path.resolve(__dirname, 'node_modules'), }, { // 對非文本文件採用 file-loader 加載 test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/, use: ['file-loader'], }, ] }
在 Loader 須要傳入不少參數時,你還能夠經過一個 Object
來描述,例如在上面的 babel-loader
配置中有以下代碼:
use: [ { loader:'babel-loader', options:{ cacheDirectory:true, }, // enforce:'post' 的含義是把該 Loader 的執行順序放到最後 // enforce 的值還能夠是 pre,表明把 Loader 的執行順序放到最前面 enforce:'post' }, // 省略其它 Loader ]
上面的例子中 test include exclude
這三個命中文件的配置項只傳入了一個字符串或正則,其實它們還都支持數組類型,使用以下:
{ test:[ /\.jsx?$/, /\.tsx?$/ ], include:[ path.resolve(__dirname, 'src'), path.resolve(__dirname, 'tests'), ], exclude:[ path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, 'bower_modules'), ] }
數組裏的每項之間是或的關係,即文件路徑符合數組中的任何一個條件就會被命中。
noParse
配置項可讓 Webpack 忽略對部分沒采用模塊化的文件的遞歸解析和處理,這樣作的好處是能提升構建性能。 緣由是一些庫例如 jQuery 、ChartJS 它們龐大又沒有采用模塊化標準,讓 Webpack 去解析這些文件耗時又沒有意義。
noParse
是可選配置項,類型須要是 RegExp
、[RegExp]
、function
其中一個。
例如想要忽略掉 jQuery 、ChartJS,可使用以下代碼:
// 使用正則表達式 noParse: /jquery|chartjs/ // 使用函數,從 Webpack 3.0.0 開始支持 noParse: (content)=> { // content 表明一個模塊的文件路徑 // 返回 true or false return /jquery|chartjs/.test(content); }
注意被忽略掉的文件裏不該該包含import
、require
、define
等模塊化語句,否則會致使構建出的代碼中包含沒法在瀏覽器環境下執行的模塊化語句。
由於 Webpack 是以模塊化的 JavaScript 文件爲入口,因此內置了對模塊化 JavaScript 的解析功能,支持 AMD
、CommonJS
、SystemJS
、ES6
。
parser
屬性能夠更細粒度的配置哪些模塊語法要解析哪些不解析,和 noParse
配置項的區別在於 parser
能夠精確到語法層面, 而 noParse
只能控制哪些文件不被解析。 parser
使用以下:
module: { rules: [ { test: /\.js$/, use: ['babel-loader'], parser: { amd: false, // 禁用 AMD commonjs: false, // 禁用 CommonJS system: false, // 禁用 SystemJS harmony: false, // 禁用 ES6 import/export requireInclude: false, // 禁用 require.include requireEnsure: false, // 禁用 require.ensure requireContext: false, // 禁用 require.context browserify: false, // 禁用 browserify requireJs: false, // 禁用 requirejs } }, ] }
Webpack 在啓動後會從配置的入口模塊出發找出全部依賴的模塊,Resolve
配置 Webpack 如何尋找模塊所對應的文件。 Webpack 內置 JavaScript 模塊化語法解析功能,默認會採用模塊化標準里約定好的規則去尋找,但你也能夠根據本身的須要修改默認的規則。
resolve.alias
配置項經過別名來把原導入路徑映射成一個新的導入路徑。例如使用如下配置:
// Webpack alias 配置 resolve:{ alias:{ components: './src/components/' } }
當你經過 import Button from 'components/button'
導入時,實際上被 alias
等價替換成了 import Button from './src/components/button'
。
以上 alias
配置的含義是把導入語句裏的 components
關鍵字替換成 ./src/components/
。
這樣作可能會命中太多的導入語句,alias
還支持 $
符號來縮小範圍到只命中以關鍵字結尾的導入語句:
resolve:{ alias:{ 'react$': '/path/to/react.min.js' } }
react$
只會命中以 react
結尾的導入語句,即只會把 import 'react'
關鍵字替換成 import '/path/to/react.min.js'
。
有一些第三方模塊會針對不一樣環境提供幾分代碼。 例如分別提供採用 ES5 和 ES6 的2份代碼,這2份代碼的位置寫在 package.json
文件裏,以下:
{ "jsnext:main": "es/index.js",// 採用 ES6 語法的代碼入口文件 "main": "lib/index.js" // 採用 ES5 語法的代碼入口文件 }
Webpack 會根據 mainFields
的配置去決定優先採用哪份代碼,mainFields
默認以下:
mainFields: ['browser', 'main']
Webpack 會按照數組裏的順序去 package.json
文件裏尋找,只會使用找到的第一個。
假如你想優先採用 ES6 的那份代碼,能夠這樣配置:
mainFields: ['jsnext:main', 'browser', 'main']
在導入語句沒帶文件後綴時,Webpack 會自動帶上後綴後去嘗試訪問文件是否存在。 resolve.extensions
用於配置在嘗試過程當中用到的後綴列表,默認是:
extensions: ['.js', '.json']
resolve.modules
配置 Webpack 去哪些目錄下尋找第三方模塊,默認是隻會去 node_modules
目錄下尋找。
有時你的項目裏會有一些模塊會大量被其它模塊依賴和導入,因爲其它模塊的位置分佈不定,針對不一樣的文件都要去計算被導入模塊文件的相對路徑, 這個路徑有時候會很長,就像這樣 import '../../../components/button'
這時你能夠利用 modules
配置項優化,假如那些被大量導入的模塊都在 ./src/components
目錄下,把 modules
配置成:
modules:['./src/components','node_modules']
後,你能夠簡單經過 import 'button'
導入。
resolve.descriptionFiles
配置描述第三方模塊的文件名稱,也就是 package.json
文件。默認以下:
descriptionFiles: ['package.json']
resolve.enforceExtension
若是配置爲 true
全部導入語句都必需要帶文件後綴, 例如開啓前 import './foo'
能正常工做,開啓後就必須寫成 import './foo.js'
。
enforceModuleExtension
和 enforceExtension
做用相似,但 enforceModuleExtension
只對 node_modules
下的模塊生效。
enforceModuleExtension
一般搭配 enforceExtension
使用,在 enforceExtension:true
時,由於安裝的第三方模塊中大多數導入語句沒帶文件後綴, 因此這時經過配置 enforceModuleExtension:false
來兼容第三方模塊。
Plugin 用於擴展 Webpack 功能,各類各樣的 Plugin 幾乎讓 Webpack 能夠作任何構建相關的事情。
Plugin 的配置很簡單,plugins
配置項接受一個數組,數組裏每一項都是一個要使用的 Plugin 的實例,Plugin 須要的參數經過構造函數傳入。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin'); module.exports = { plugins: [ // 全部頁面都會用到的公共代碼提取到 common 代碼塊中 new CommonsChunkPlugin({ name: 'common', chunks: ['a', 'b'] }), ] };
使用 Plugin 的難點在於掌握 Plugin 自己提供的配置項,而不是如何在 Webpack 中接入 Plugin。
要配置 DevServer ,除了在配置文件裏經過 devServer
傳入參數外,還能夠經過命令行參數傳入。 注意只有在經過 DevServer
去啓動 Webpack 時配置文件裏 devServer
纔會生效,由於這些參數所對應的功能都是 DevServer 提供的,Webpack 自己並不認識 devServer
配置項。
devServer.hot
配置是否啓用模塊熱替換功能。
DevServer
默認的行爲是在發現源代碼被更新後會經過自動刷新整個頁面來作到實時預覽,開啓模塊熱替換功能後將在不刷新整個頁面的狀況下經過用新模塊替換老模塊來作到實時預覽。
DevServer 的實時預覽功能依賴一個注入到頁面裏的代理客戶端去接受來自 DevServer 的命令和負責刷新網頁的工做。
devServer.inline
用於配置是否自動注入這個代理客戶端到將運行在頁面裏的 Chunk 裏去,默認是會自動注入。 DevServer 會根據你是否開啓 inline
來調整它的自動刷新策略:
inline
,DevServer 會在構建完變化後的代碼時經過代理客戶端控制網頁刷新。inline
,DevServer 將沒法直接控制要開發的網頁。這時它會經過 iframe
的方式去運行要開發的網頁,當構建完變化後的代碼時經過刷新 iframe
來實現實時預覽。若是你想使用 DevServer 去自動刷新網頁實現實時預覽,最方便的方法是直接開啓 inline
。
devServer.historyApiFallback
用於方便的開發使用了 HTML5 History API 的單頁應用。
這類單頁應用要求服務器在針對任何命中的路由時都返回一個對應的 HTML 文件,例如在訪問 http://localhost/user
和 http://localhost/home
時都返回 index.html
文件, 瀏覽器端的 JavaScript 代碼會從 URL 裏解析出當前頁面的狀態,顯示出對應的界面。
配置 historyApiFallback
最簡單的作法是:
historyApiFallback: true
這會致使任何請求都會返回 index.html
文件,這隻能用於只有一個 HTML 文件的應用。
若是你的應用由多個單頁應用組成,這就須要 DevServer 根據不一樣的請求來返回不一樣的 HTML 文件,配置以下:
historyApiFallback: { // 使用正則匹配命中路由 rewrites: [ // /user 開頭的都返回 user.html { from: /^\/user/, to: '/user.html' }, { from: /^\/game/, to: '/game.html' }, // 其它的都返回 index.html { from: /./, to: '/index.html' }, ] }
devServer.contentBase
配置 DevServer HTTP 服務器的文件根目錄。 默認狀況下爲當前執行目錄,一般是項目根目錄,全部通常狀況下你沒必要設置它,除非你有額外的文件須要被 DevServer 服務。 例如你想把項目根目錄下的 public
目錄設置成 DevServer 服務器的文件根目錄,你能夠這樣配置:
devServer:{ contentBase: path.join(__dirname, 'public') }
這裏須要指出可能會讓你疑惑的地方,DevServer 服務器經過 HTTP 服務暴露出的文件分爲兩類:
contentBase
只能用來配置暴露本地文件的規則,你能夠經過 contentBase:false
來關閉暴露本地文件。
devServer.headers
配置項能夠在 HTTP 響應中注入一些 HTTP 響應頭,使用以下:
devServer:{ headers: { 'X-foo':'bar' } }
devServer.host
配置項用於配置 DevServer 服務監聽的地址。
例如你想要局域網中的其它設備訪問你本地的服務,能夠在啓動 DevServer 時帶上 --host 0.0.0.0
。 host
的默認值是 127.0.0.1
即只有本地能夠訪問 DevServer 的 HTTP 服務。
devServer.port
配置項用於配置 DevServer 服務監聽的端口,默認使用 8080
端口。 若是 8080
端口已經被其它程序佔有就使用 8081
,若是 8081
仍是被佔用就使用 8082
,以此類推。
devServer.allowedHosts
配置一個白名單列表,只有 HTTP 請求的 HOST 在列表裏才正常返回,使用以下:
allowedHosts: [ // 匹配單個域名 'host.com', 'sub.host.com', // host2.com 和全部的子域名 *.host2.com 都將匹配 '.host2.com' ]
devServer.disableHostCheck
配置項用於配置是否關閉用於 DNS 重綁定的 HTTP 請求的 HOST 檢查。
DevServer 默認只接受來自本地的請求,關閉後能夠接受來自任何 HOST 的請求。 它一般用於搭配 --host 0.0.0.0
使用,由於你想要其它設備訪問你本地的服務,但訪問時是直接經過 IP 地址訪問而不是 HOST 訪問,因此須要關閉 HOST 檢查。
DevServer 默認使用 HTTP 協議服務,它也能經過 HTTPS 協議服務。 有些狀況下你必須使用 HTTPS,例如 HTTP2 和 Service Worker 就必須運行在 HTTPS 之上。 要切換成 HTTPS 服務,最簡單的方式是:
devServer:{ https: true }
DevServer 會自動的爲你生成一份 HTTPS 證書。
若是你想用本身的證書能夠這樣配置:
devServer:{ https: { key: fs.readFileSync('path/to/server.key'), cert: fs.readFileSync('path/to/server.crt'), ca: fs.readFileSync('path/to/ca.pem') } }
devServer.clientLogLevel
配置在客戶端的日誌等級,這會影響到你在瀏覽器開發者工具控制檯裏看到的日誌內容。
clientLogLevel
是枚舉類型,可取以下之一的值 none | error | warning | info
。 默認爲 info
級別,即輸出全部類型的日誌,設置成 none
能夠不輸出任何日誌。
devServer.compress
配置是否啓用 gzip 壓縮。boolean
爲類型,默認爲 false
。
devServer.open
用於在 DevServer 啓動且第一次構建完時自動用你係統上默認的瀏覽器去打開要開發的網頁。 同時還提供 devServer.openPage
配置項用於打開指定 URL 的網頁。
target
配置項可讓 Webpack 構建出針對不一樣運行環境的代碼。 target 能夠是如下之一:
target值 | 描述 |
---|---|
web | 針對瀏覽器 (默認),全部代碼都集中在一個文件裏 |
node | 針對 Node.js,使用 require 語句加載 Chunk 代碼 |
async-node | 針對 Node.js,異步加載 Chunk 代碼 |
webworker | 針對 WebWorker |
electron-main | 針對 Electron 主線程 |
electron-renderer | 針對 Electron 渲染線程 |
例如當你設置 target:'node'
時,源代碼中導入 Node.js 原生模塊的語句 require('fs')
將會被保留,fs
模塊的內容不會打包進 Chunk 裏。
devtool
配置 Webpack 如何生成 Source Map,默認值是 false
即不生成 Source Map,想爲構建出的代碼生成 Source Map 以方便調試,能夠這樣配置:
module.export = { devtool: 'source-map' }
前面介紹過 Webpack 的監聽模式,它支持監聽文件更新,在文件發生變化時從新編譯。在使用 Webpack 時監聽模式默認是關閉的,想打開須要以下配置:
module.export = { watch: true }
在使用 DevServer 時,監聽模式默認是開啓的。
除此以外,Webpack 還提供了 watchOptions
配置項去更靈活的控制監聽模式,使用以下:
module.export = { // 只有在開啓監聽模式時,watchOptions 纔有意義 // 默認爲 false,也就是不開啓 watch: true, // 監聽模式運行時的參數 // 在開啓監聽模式時,纔有意義 watchOptions: { // 不監聽的文件或文件夾,支持正則匹配 // 默認爲空 ignored: /node_modules/, // 監聽到變化發生後會等300ms再去執行動做,防止文件更新太快致使從新編譯頻率過高 // 默認爲 300ms aggregateTimeout: 300, // 判斷文件是否發生變化是經過不停的去詢問系統指定文件有沒有變化實現的 // 默認每1000豪秒去問1次 poll: 1000 } }
Externals 用來告訴 Webpack 要構建的代碼中使用了哪些不用被打包的模塊,也就是說這些模版是外部環境提供的,Webpack 在打包時能夠忽略它們。
有些 JavaScript 運行環境可能內置了一些全局變量或者模塊,例如在你的 HTML HEAD 標籤裏經過如下代碼:
<script src="path/to/jquery.js"></script>
引入 jQuery 後,全局變量 jQuery
就會被注入到網頁的 JavaScript 運行環境裏。
若是想在使用模塊化的源代碼裏導入和使用 jQuery,可能須要這樣:
import $ from 'jquery'; $('.my-element');
構建後你會發現輸出的 Chunk 裏包含的 jQuery 庫的內容,這致使 jQuery 庫出現了2次,浪費加載流量,最好是 Chunk 裏不會包含 jQuery 庫的內容。
Externals 配置項就是爲了解決這個問題。
經過 externals
能夠告訴 Webpack JavaScript 運行環境已經內置了那些全局變量,針對這些全局變量不用打包進代碼中而是直接使用全局變量。 要解決以上問題,能夠這樣配置 externals
:
module.export = { externals: { // 把導入語句裏的 jquery 替換成運行環境裏的全局變量 jQuery jquery: 'jQuery' } }
ResolveLoader 用來告訴 Webpack 如何去尋找 Loader,由於在使用 Loader 時是經過其包名稱去引用的, Webpack 須要根據配置的 Loader 包名去找到 Loader 的實際代碼,以調用 Loader 去處理源文件。
ResolveLoader 的默認配置以下:
module.exports = { resolveLoader:{ // 去哪一個目錄下尋找 Loader modules: ['node_modules'], // 入口文件的後綴 extensions: ['.js', '.json'], // 指明入口文件位置的字段 mainFields: ['loader', 'main'] } }
該配置項經常使用於加載本地的 Loader。
以前的章節分別講述了每一個配置項的具體含義,但沒有描述它們所處的位置和數據結構,下面經過一份代碼來描述清楚:
const path = require('path'); module.exports = { // entry 表示 入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。 // 類型能夠是 string | object | array entry: './app/entry', // 只有1個入口,入口只有1個文件 entry: ['./app/entry1', './app/entry2'], // 只有1個入口,入口有2個文件 entry: { // 有2個入口 a: './app/entry-a', b: ['./app/entry-b1', './app/entry-b2'] }, // 如何輸出結果:在 Webpack 通過一系列處理後,如何輸出最終想要的代碼。 output: { // 輸出文件存放的目錄,必須是 string 類型的絕對路徑。 path: path.resolve(__dirname, 'dist'), // 輸出文件的名稱 filename: 'bundle.js', // 完整的名稱 filename: '[name].js', // 當配置了多個 entry 時,經過名稱模版爲不一樣的 entry 生成不一樣的文件名稱 filename: '[chunkhash].js', // 根據文件內容 hash 值生成文件名稱,用於瀏覽器長時間緩存文件 // 發佈到線上的全部資源的 URL 前綴,string 類型 publicPath: '/assets/', // 放到指定目錄下 publicPath: '', // 放到根目錄下 publicPath: 'https://cdn.example.com/', // 放到 CDN 上去 // 導出庫的名稱,string 類型 // 不填它時,默認輸出格式是匿名的當即執行函數 library: 'MyLibrary', // 導出庫的類型,枚舉類型,默認是 var // 能夠是 umd | umd2 | commonjs2 | commonjs | amd | this | var | assign | window | global | jsonp , libraryTarget: 'umd', // 是否包含有用的文件路徑信息到生成的代碼裏去,boolean 類型 pathinfo: true, // 附加 Chunk 的文件名稱 chunkFilename: '[id].js', chunkFilename: '[chunkhash].js', // JSONP 異步加載資源時的回調函數名稱,須要和服務端搭配使用 jsonpFunction: 'myWebpackJsonp', // 生成的 Source Map 文件名稱 sourceMapFilename: '[file].map', // 瀏覽器開發者工具裏顯示的源碼模塊名稱 devtoolModuleFilenameTemplate: 'webpack:///[resource-path]', // 異步加載跨域的資源時使用的方式 crossOriginLoading: 'use-credentials', crossOriginLoading: 'anonymous', crossOriginLoading: false, }, // 配置模塊相關 module: { rules: [ // 配置 Loader { test: /\.jsx?$/, // 正則匹配命中要使用 Loader 的文件 include: [ // 只會命中這裏面的文件 path.resolve(__dirname, 'app') ], exclude: [ // 忽略這裏面的文件 path.resolve(__dirname, 'app/demo-files') ], use: [ // 使用那些 Loader,有前後次序,從後往前執行 'style-loader', // 直接使用 Loader 的名稱 { loader: 'css-loader', options: { // 給 html-loader 傳一些參數 } } ] }, ], noParse: [ // 不用解析和處理的模塊 /special-library\.js$/ // 用正則匹配 ], }, // 配置插件 plugins: [], // 配置尋找模塊的規則 resolve: { modules: [ // 尋找模塊的根目錄,array 類型,默認以 node_modules 爲根目錄 'node_modules', path.resolve(__dirname, 'app') ], extensions: ['.js', '.json', '.jsx', '.css'], // 模塊的後綴名 alias: { // 模塊別名配置,用於映射模塊 // 把 'module' 映射 'new-module',一樣的 'module/path/file' 也會被映射成 'new-module/path/file' 'module': 'new-module', // 使用結尾符號 $ 後,把 'only-module' 映射成 'new-module', // 可是不像上面的,'module/path/file' 不會被映射成 'new-module/path/file' 'only-module$': 'new-module', }, alias: [ // alias 還支持使用數組來更詳細的配置 { name: 'module', // 老的模塊 alias: 'new-module', // 新的模塊 // 是不是隻映射模塊,若是是 true 只有 'module' 會被映射,若是是 false 'module/inner/path' 也會被映射 onlyModule: true, } ], symlinks: true, // 是否跟隨文件軟連接去搜尋模塊的路徑 descriptionFiles: ['package.json'], // 模塊的描述文件 mainFields: ['main'], // 模塊的描述文件裏的描述入口的文件的字段名稱 enforceExtension: false, // 是否強制導入語句必需要寫明文件後綴 }, // 輸出文件性能檢查配置 performance: { hints: 'warning', // 有性能問題時輸出警告 hints: 'error', // 有性能問題時輸出錯誤 hints: false, // 關閉性能檢查 maxAssetSize: 200000, // 最大文件大小 (單位 bytes) maxEntrypointSize: 400000, // 最大入口文件大小 (單位 bytes) assetFilter: function (assetFilename) { // 過濾要檢查的文件 return assetFilename.endsWith('.css') || assetFilename.endsWith('.js'); } }, devtool: 'source-map', // 配置 source-map 類型 context: __dirname, // Webpack 使用的根目錄,string 類型必須是絕對路徑 // 配置輸出代碼的運行環境 target: 'web', // 瀏覽器,默認 target: 'webworker', // WebWorker target: 'node', // Node.js,使用 `require` 語句加載 Chunk 代碼 target: 'async-node', // Node.js,異步加載 Chunk 代碼 target: 'node-webkit', // nw.js target: 'electron-main', // electron, 主線程 target: 'electron-renderer', // electron, 渲染線程 externals: { // 使用來自 JavaScript 運行環境提供的全局變量 jquery: 'jQuery' }, stats: { // 控制檯輸出日誌控制 assets: true, colors: true, errors: true, errorDetails: true, hash: true, }, devServer: { // DevServer 相關的配置 proxy: { // 代理到後端服務接口 '/api': 'http://localhost:3000' }, contentBase: path.join(__dirname, 'public'), // 配置 DevServer HTTP 服務器的文件根目錄 compress: true, // 是否開啓 gzip 壓縮 historyApiFallback: true, // 是否開發 HTML5 History API 網頁 hot: true, // 是否開啓模塊熱替換功能 https: false, // 是否開啓 HTTPS 模式 }, profile: true, // 是否捕捉 Webpack 構建的性能信息,用於分析什麼緣由致使構建性能不佳 cache: false, // 是否啓用緩存提高構建速度 watch: true, // 是否開始 watchOptions: { // 監聽模式選項 // 不監聽的文件或文件夾,支持正則匹配。默認爲空 ignored: /node_modules/, // 監聽到變化發生後會等300ms再去執行動做,防止文件更新太快致使從新編譯頻率過高 // 默認爲300ms aggregateTimeout: 300, // 判斷文件是否發生變化是不停的去詢問系統指定文件有沒有變化,默認每秒問 1000 次 poll: 1000 }, };
除了經過導出一個 Object 來描述 Webpack 所需的配置外,還有其它更靈活的方式,以簡化不一樣場景的配置。
在大多數時候你須要從同一份源代碼中構建出多份代碼,例如一份用於開發時,一份用於發佈到線上。
若是採用導出一個 Object 來描述 Webpack 所需的配置的方法,須要寫兩個文件。 一個用於開發環境,一個用於線上環境。再在啓動時經過 webpack --config webpack.config.js
指定使用哪一個配置文件。
採用導出一個 Function 的方式,能經過 JavaScript 靈活的控制配置,作到只寫一個配置文件就能完成以上要求。
導出一個 Function 的使用方式以下:
const path = require('path'); const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin'); module.exports = function (env = {}, argv) { const plugins = []; const isProduction = env['production']; // 在生成環境才壓縮 if (isProduction) { plugins.push( // 壓縮輸出的 JS 代碼 new UglifyJsPlugin() ) } return { plugins: plugins, // 在生成環境不輸出 Source Map devtool: isProduction ? undefined : 'source-map', }; };
在運行 Webpack 時,會給這個函數傳入2個參數,分別是:
env
:當前運行時的 Webpack 專屬環境變量,env
是一個 Object。讀取時直接訪問 Object 的屬性,設置它須要在啓動 Webpack 時帶上參數。例如啓動命令是 webpack --env.production --env.bao=foo
時,則 env
的值是 {"production":"true","bao":"foo"}
。argv
:表明在啓動 Webpack 時全部經過命令行傳入的參數,例如 --config、--env、--devtool
,能夠經過 webpack -h
列出全部 Webpack 支持的命令行參數。就以上配置文件而言,在開發時執行命令 webpack 構建出方便調試的代碼,在須要構建出發佈到線上的代碼時執行 webpack --env.production
構建出壓縮的代碼。
在有些狀況下你不能以同步的方式返回一個描述配置的 Object,Webpack 還支持導出一個返回 Promise 的函數,使用以下:
module.exports = function(env = {}, argv) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ // ... }) }, 5000) }) }
除了只導出一份配置外,Webpack 還支持導出一個數組,數組中能夠包含每份配置,而且每份配置都會執行一遍構建。
使用以下:
module.exports = [ // 採用 Object 描述的一份配置 { // ... }, // 採用函數描述的一份配置 function() { return { // ... } }, // 採用異步函數描述的一份配置 function() { return Promise(); } ]
以上配置會致使 Webpack 針對這三份配置執行三次不一樣的構建。
這特別適合於用 Webpack 構建一個要上傳到 Npm 倉庫的庫,由於庫中可能須要包含多種模塊化格式的代碼,例如 CommonJS、UMD。
從前面的配置看來選項不少,Webpack 內置了不少功能。
你沒必要都記住它們,只須要大概明白 Webpack 原理和核心概念去判斷選項大體屬於哪一個大模塊下,再去查詳細的使用文檔。
一般你可用以下經驗去判斷如何配置 Webpack:
entry
。output
。resolve
。module
,一般是配置 module.rules
裏的 Loader。plugin
。