module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader?minimize']
}
]
}
一、入門
loader可以看作是翻譯員,配置module.rules數組里的規則,告訴webpack遇到哪些文件使用哪些loader去加載和轉換。
如上的話就是告訴webpack當遇到.css文件后先采用css-loader,再由style-loader將css的內容注入javascript里,是由后往前的。
每個loader都可以通過URL querystring的方式傳入參數,'css-loader?minimize'就是告訴css-loader要開啟css壓縮。
其中向loader傳入的屬性可以通過querystring實現,還可以通過Object實現。
use: [
'style-loader',
{
loader: 'css-loader',
options: {
minimize: true }
}
]
除了在webpack.config.js配置文件中配置loader,還可以在代碼中指定用什么loader處理文件。例如
require (’style-loader! css-loader?minimize! ./main.css ’);
這樣就能指定對./main.css這個文件先采用css-loader再采用style-loader進行轉換。
module: {
rules: [
{
test: /\.css$/,
loaders: ExtractTextPlugin.extract({
use: ['css-loader']
})
}
]
},
plugin
是用來擴展webpack功能的。
extract-text-webpack-plugin就是用來提取css文件,使之不適用style的方式放在dom元素上、
DevServer是啟動http服務器監聽在8080端口,這時不會再./dist下面生成靜態文件,原因是devServer會把構建的文件保存在內存中,需要通過http訪問,由于DevServer不會理會webpack.config.js里配置的output.path屬性,所以要獲取bundle.js正確的url是http://localhost:8080/bundle.js,在index.html中就是src="bundle.js"
實時預覽:修改main.js、main.css、show.js中任意的文件,保存會發現瀏覽器熱更新。
webpack在啟動時開啟監聽模式,會監聽本地文件系統的變化,在發生變化時重新進行構建,然后通知DevServer,DevServer會讓webpack在構建出的javascript代碼里注入一個代理客戶端用于控制網頁,網頁和devserver質檢通過websocket協議通信,以方便devserver制度當向客戶端發送命令。
修改index.html不會觸發熱更新,因為webpack啟動時會以配置里entry為入口區遞歸解析出entry所依賴的文件,只有entry本身和依賴的文件才會被監聽。
source map
在瀏覽器中運行的都是編譯后的代碼,可讀性很差,如果遇到不知原因的bug,則需要打斷點調試。調試工具可以通過source map映射代碼,讓我們在源代碼上斷點調試。
webpack的幾個核心概念:
entry: webpack執行構建的第一步從entry開始。
module: 模塊,在webpack里一切皆模塊,一個模塊對應一個文件。
chunk: 代碼塊,一個chunk由多個模塊組合而成,用于代碼合并和分割
loader: 模塊轉換器,用于將模塊的原內容按照需求轉換成新內容。
plugin: 擴展插件
output: 輸出結果
resolve: 配置尋找模塊的規則
DevServer: 配置DevServer
webpack在啟動后會從entry里配置的module開始,遞歸解析entry依賴的所有module,沒找到一個module,就會根據配置的loader去找對應的轉換規則,對module進行轉換后,再解析出當前module依賴的module。這些模塊會以entry為單位進行分組,一個entry及其所有的依賴的module被分到一個組也就是一個chunk。最后webpack會將所有的chunk轉換成文件輸出。
二、配置
entry: 配置入口, webpack構建的起點,entry配置必填,不填或填錯會報錯。
entry類型可以是以下三種中的一種或者相互組合:
類型例子含義
string'./app/entry'入口模塊的文件路徑,可以是相對路徑
array['./app/entry1','./app/entry2']入口模塊的文件路徑,可以是相對路徑
object{a:'./app/entry-a',b:['./app/entry-b1','./app/entry-b2']配置多個入口,每個入口生成一個chunk
如果是array類型,在搭配output.library配置項使用時,只有數組里的最后一個入口文件的模塊會被導出。
chunk的名稱:
webpack會為每個生成的chunk去一個名稱,chunk的名稱和entry的配置有關。
如果entry是一個string或array,就只會生成一個chunk,這時chunk的名稱是main
如果entry是一個object,就可能出現多個chunk,這時chunk的名稱是object鍵值對中鍵的名稱。
配置動態的entry
加入項目里有很多個頁面需要為每個頁面的入口配置一個entry,但是這些頁面爽可能會剬增長,這時entry不能寫成靜態的值,其解決辦法是將entry設置成一個動態函數返回上面所說的配置。
entry: () => {
return {
a: '/pages/a',
b: 'pages/b'
}
}
entry: () => {
returnnewPromise((resolve) => {
resolve({
a: '/pages/a',
b: 'pages/b' })
})
}
context:
webpack在尋找相對路徑的文件時會以context為根目錄,context默認執行啟動webpack時所在的當前工作目錄。若想改變context的默認配置,可以這樣設置:
context: path.resolve(__dirname, 'app')
注意:context必須是一個絕對路徑的字符串。
除此之外還可通過在啟動webpack時帶上參數webpack --context 來設置context。
Output:
output配置如何輸出最終想要的代碼。output是一個對象,里面包含很多配置項:
filename: 配置輸出文件名,string類型,如果只輸出一個文件,則可以將它寫成靜態不變的。但是如果有多個chunk要輸出時,就需要借助模板和變量了。
filename: '[name].js'
代碼里的[name]代表用內置的name變量替換[name],這時我們可以將它看做一個字符串模塊函數,每個要輸出的chunk都會通過這個函數去拼接輸出的文件名稱。
內置變量列表:
變量名含義
idchunk唯一標識,從0開始
namechunk名稱
hashchunk唯一標識的hash值
chunkhashchunk內容的hash值
其中,hash和chunkhash的長度是可以指定的, [hash:8]代表8位hash值,默認是20位。
注意: ExtractTextPlugin插件使用contenthash二不是chunkhash來代表哈希值,原因在于ExtractTextPlugin提取出來的內容是代碼本身,而不是一組模塊組成的chunk。
chunkFilename: 配置無入口的chunk在輸出時的文件的名稱,和filename非常類似,反chunkFilename只用于指定在運行過程中生成的chunk在輸出時的文件名稱。會在運行時生成chunk的常見場景包括:使用commonchunkplugin使用import('path/to/module')動態加載等。
path: 配置輸出文件存放的本地目錄,必須是string類型的絕對路徑。通常用__diename去獲取:path: path.resolve(__dirname, 'dist_[hash]')
publicPath: 在復雜的項目里可能會有一些構建出的資源需要異步加載,加載這些異步資源需要對應的URL地址。
crossOriginLoading: webpack輸出的部分代碼可能需異步加載,而異步加載時通過JSONP方式實現的,JSONP的原理是動態向HTML插入一個標簽去加載異步資源。crossOriginLoading則是配置這個異步插入的標簽的crossorigin值。
script標簽的crossorign屬性可以取以下值:
anonymous(默認),在加載此腳本資源時不會帶上用戶的cookies
use-credentials: 帶上用戶的cookie,
通常用來獲取異步加載的腳本執行時的詳細錯誤信息。
libraryTarget和library
當webpack去構建一個可以被其他模塊導入的庫時,則需要libraryTarget和library。
libraryTarget配置以何種方式導出庫
library配置導出庫的名稱
libraryTarget是字符串的枚舉類型,支持以下配置:
1. var (默認),編寫的庫將通過var被賦值給通過library指定的名稱的變量。
2.commonjs, 編寫的庫通過CommonJS規范導出
3.commonjs2, 編寫的庫通過CommonJS2規范導出
4.this, 編寫的庫通過this被賦值給通過library指定的名稱
5. window,編寫的庫通過this被賦值給通過window指定的名稱
6. global,編寫的庫通過this被賦值給通過global指定的名稱
libraryExport
配置要導出的模塊中哪些子模塊需要被導出,只有在libraryTarget被設置成commonjs或者commonjs2時使用才有意義。
Module
配置處理模塊的規則。
配置loader
rules
配置模塊的讀取和解析規則,通常用來噢誒之loader,其類型是一個數組,數組里每一項都描述了如何處理部分文件。配置一項rules大致可通過以下方式愛完成。
條件匹配: 通過test、include、exclude三個配置項來選中loader要應用規則的文件。
應用規則: 通過use配置項來應用loader,可以只應用一個loader或者按照從后往前的順序應用一組loader,同時可分別向loader傳入參數
重置順序: 一組loader的執行順序默認是從右到左執行的,通過enforce選項可以將其中一個loader的執行順序放到最前或最后
module: { rules: [
{
//命中javascript文件test: /\.js$/,
//用babel-loader轉換javascript文件//?cacheDirectory表示傳給babel-loader的參數,用于緩存babel的編譯結果,加快重新編譯的速度use: ['babel-loader?cacheDirectory'],
//只命中src目錄里的javascript文件,加快webpack搜索速度include: path.resolve(__dirname, 'src')
},
{
//命中scss文件test: /\.scss$/,
//使用一組loader去處理scss文件//處理順序從后到前,先交給sass-loader處理,再將結果交給css-loader,最后交給style-loaderuse: ['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: 'pre' },
//省略其余的loader ]
},
//test也支持數組類型 {
test: [/\.jsx?$/,/\.tsx?$/]
}
]
}
noParse
這個配置項可以讓webpack忽略對部分沒采用模塊化的文件的遞歸解析和處理,這樣做的好處是能提高構建性能,原因是一些庫如jquery,chartjs龐大又誒呦采用模塊化標準,讓webpack去解析這些文件耗時又沒有意義。
noParse是可選配置項,類型需要 RegExp、[RegExp]、function中的一種。例如,忽略jquery,chartjs:
//正則noParse:/jquery|chartjs/,
//使用函數,webpack3.0.0后支持noParse: (content) => {
//content代表一個模塊的路徑return/jquery|chartjs/.test(content);
}
parser
因為webpack是以模塊化的javascript文件為入口的,所以內置了對模塊化javascript的解析功能,支持AMD、CommonJS,SystemJS,ES6。parser屬性可以更細粒的配置那些模塊預發被解析,哪些不被解析。parser可以精確到語法層面。
test: /\.js$/ use: [ ’babel-loader’],
parser: {
amd: false //禁用AMD
commonjs : false , //禁用CommonJS
system : false, //禁用SystemJS
harmony: false//禁用ES6 import/exportrequireinclude: false //禁用require.include
requireEnsure: false //禁用require.ensure
requireContext: false //禁用require.context
browserify: false, //禁用browserfiry
requireJs :false, //禁用requirejs
Resolve
webpack在啟動后會從配置的入口模塊觸發找出所有依賴的模塊,resolve配置webpack如何尋找模塊所對應的文件。webpack內置javascript模塊化預發解析功能,默認會采用模塊化標準里約定的規則去尋找。也可以根據自己的需要修改默認的規則。
alias
resolve.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'
mainFields
有些第三方模塊會針對不同的環境提供幾份代碼。webpack會根據mainFields的配置去決定優先采用哪部分代碼。
mainFields: ['browser', 'main'] 默認
extensions
導入語句沒帶文件后綴時,webpack會自動帶上后綴去嘗試訪問文件是否存在。
extensions用于配置嘗試過程中用到的后綴列表,默認是:
extensions: ['.js', '.json']。比如如果我們要優先選擇TypeScript文件,則可以這樣配置: extensions : ['.ts', '.js', '.json']
modules
resolve.modules配置webpack去哪些目錄下尋找第三方模塊,默認只會去node_modules目錄下尋找。比如被大量導入的模塊都在./src/components目錄下,則將modules配置成modules: ['./src/components'. 'node_modules']后,則可以簡單的使用import 'button'導入
descriptionFiles
配置描述第三方模塊的文件名稱,也就是package.json文件。默認descriptionFiles: ['package.json']
enforceExtension
如果配置為true,所有導入語句必須帶文件后綴名,不然會報錯。
enforceModuleExtension
和enforceExtension作用相似,只對node_modules下的模塊生效。通常配合enforceExtension使用,因為配置enforceExtension:true后,第三方模塊的大多數導入語句都沒有后綴,此時配置enforceModuleExtension:false來兼容。
Plugin
plugin用于擴展webpack功能。
plugins配置項接收一個數組,數組的每一項都是一個呀使用的plugin實例,plugin需要的參數通過構造函數傳入。
DevServer
hot
配置是否啟用熱替換功能,默認行為是在發現源代碼被更新后通過自動刷新整個頁面來做到實時預覽,開啟熱替換功能后,將在不刷新整個頁面的情況下通過用新模塊替換老模塊來做到實時預覽。
inline
配置是否將這個代理客戶端自動注入將運行在頁面中的chunk里,默認自動注入。
· 開啟inline,devserver會在構建變化后的代碼時通過代理客戶端控制網頁刷新
· 如果關閉inine,devserver無法直接控制要開發的網頁,通過iframe方式去運行開發的網頁。代碼變化去刷新iframe,這時需要去http://localhost:8080/webpack-dev-server/實時預覽網頁
最方便的方法是開啟inline
historyApiFallback
用于方便開發html5 history api的單頁應用。這類單頁應用要求服務器在針對任何命中的路由時,都返回一個對應的index.html文件。
最簡單的做法是:
historyApiFallback: true
這會導致任何請求都會返回index.html文件。
如果我們的應用由多個單頁應用組成,則需要devserver根據不同的請求返回不同的html文件,配置如下:
historyApiFallback: {
rewrites: [
//user開頭返回的是user.html{from: /^\/user/, to: '/user.html'},
{from: /^\/user/, to: '/game.html'}
]
}
contentBase
配置devserver http服務器文件根目錄。在默認情況下為當前的執行目錄,通常是項目根目錄,一般不用設置它。
headers
可以在http響應中注入一些http響應頭。
host
配置devserver服務監聽地址
port
端口
allowHosts
配置一個白名單列表,只有http請求的host在列表里才正常返回。
disableHostCheck
用于配置是否關閉用于DNS重新綁定的http請求的host檢查。默認只接收來自本地的請求,關閉后可以接受來自任意host的請求。
https
默認使用http服務,在某些情況下必須使用https
devServer: {
https: true
}
如果想要配置證書:
devServer: {
key: fs.readFileSync('path/to/server.key'),
cert: fs.readFileSync('path/to/server.crt'),
ca: fs.readFileSync('path/to/ca.pem')
}
clientLogLevel
日至等級
compress
是否啟用Gzip壓縮,為boolean型,默認為false。
open
是否自動打開瀏覽器
其他配置項
Target
js應用場景越來越多,從瀏覽器到node.js,這些運行在不同環境的js代碼存在一些差異。target配置項可以讓webpack構建出針對不同運行環境的代碼。
target值: web, node, async-node, webworker, electron-main, electron-reanderer
Devtool
配置webpack如何生成source map,默認值是false,不生成source map,若想構建出的代碼生成source-map:
devtool: 'source-map'
watch和watchOptions
支持文件監聽,文件發生變化時重新編譯。
watchOptions 配置項更靈活地控制監聽模式。
Externals
用來告訴webpack要構建的代碼中使用了哪些不用背打包的模塊,也就是說這些模板是外部環境提供,webpack在打包時可以忽略它們。
ResolveLoader
告訴webpack如何去尋找loader