關於Webpack前兩篇跟大家分享的主要是Webpack的一些基本的配置,今天開始我們詳細瞭解一下有關Webpack的各種配置,今天主要跟大家分享的是Webpack的資源入口和資源出口的配置。
如果想了解前兩篇的文章請訪問下面的地址:
Webpack實戰(一):Webpack打包工具安裝及參數配置
Webpack實戰(二):webpack-dev-server的介紹與用法
資源入口配置
資源入口配置是Webpack配置中不可缺少的一個環節,Webpack通過context和entry這兩個配置項來共同決定入口文件的路徑。從英文翻譯過來的字面的意思可以瞭解到context是上下文的意思,entry是入口,在配置入口的時候其實做了兩件事情:
- 確定入口模塊位置,告訴Webpack從哪裏開始進行打包。
- 定義chunk name。如果工程只有一個入口,那麼默認其chunk name爲“main”;如果工程有多個入口,我們需要爲每個入口定義chunk name,來作爲該chunk的唯一標識。
context可以理解爲資源入口的路徑前綴,在配置時要求必須使用絕對路徑的形式,配置代碼例子如下:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src')
entry: './index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'development',
"devServer": {
"publicPath": './dist',
"port": 3000
}
}
其實context 的配置相當於引入前綴‘src’,如果不用context,可以配置成
entry: './src/index.js'
context這個配置可以省略,配置context的主要目的是讓entry的編寫更加簡潔,尤其是在多入口的情況下。
entry的配置可以有多種形式:字符串、數組、對象、函數。可以根據不同的需求場景來選擇。
- 字符串類型入口
直接傳入路徑入口,如下
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
},
mode: 'development',
"devServer": {
"publicPath": './dist',
"port": 3000
}
}
- 數組類型入口
傳入一個數組的作用是將多個資源預先合併,在打包時Webpack會將數組中的最後一個元素作爲實際的入口路徑。如:
module.exports = {
entry: ['./add.js', './index.js'],
output: {
filename: 'bundle.js'
}
}
其實這種做法相當於字符串引入的一種,就如
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
}
}
// index.js 文件引入add文件
import './add'
數組類型入口其實數組裏的js文件最後還是合併到一個文件bundle.js上
- 對象類型入口
如果想要定義多入口,則必須使用對象的形式。對象的屬性名(key)是chunk name,屬性值(value)是入口路徑。如
module.exports = {
entry: {
index: './src/index.js', // chunk name 爲 index
add: './src/add.js' // chunk name 爲 add
},
output: {
filename: 'bundle.js'
}
}
注意:對象的屬性值也可以爲字符串或數組。
module.exports = {
entry: {
index: ['./add2.js', './index.js'] // chunk name 爲 index
add: './src/add.js' // chunk name 爲 add
},
output: {
filename: 'bundle.js'
}
}
- 函數類型入口
用函數定義入口時,只要返回上面介紹的任何配置形式即可,如:
// 返回字符串形式的入口
module.exports = {
entry: () => './src/index.js',
output: {
filename: 'bundle.js'
}
}
// 返回對象形式的入口
module.exports = {
entry: () => ({
index: ['./add2.js', './index.js'] // chunk name 爲 index
add: './src/add.js' // chunk name 爲 add
}),
output: {
filename: 'bundle.js'
}
}
用函數作爲一個入口的好處是我們可以在函數體裏添加一些動態的邏輯來獲取項目的入口,另外,函數也支持返回一個Promise對象來進行異步操作。例子如下:
module.exports = {
entry: () => new Promise((resolve) => {
// 模擬異步操作
setTimeout(()=> {
resolve('./src/index.js')
}, 1000)
}),
output: {
filename: 'bundle.js'
}
}
資源出口配置
接下來,讓我們詳細去了解一下資源出口的配置,資源出口配置的參數大部分都在output裏面,這裏先了解一下幾個常用的配置參數。
- filename
filename是控制輸出資源的文件名,是字符串形式
如:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: './index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'development',
"devServer": {
"publicPath": './dist',
"port": 3000
}
}
打包效果如下
filename不僅可以是文件名,也可以是路徑,如下:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: './index.js',
output: {
filename: './dist/bundle.js'
},
mode: 'development'
}
在多入口的場景中,如果需要爲對應產生的每個bundle指定不同的名字,Webpack支持使用一種類似模板語言的形式動態地生成文件名,如:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js', //chunk name 爲index
index2: './index2.js' //chunk name 爲index2
},
output: {
filename: '[name].js'
},
mode: 'development'
}
在資源輸出時,上面配置的filename中的[name]會被替換爲chunk name,因此最後項目中實際生成的資源是index.js與index2.js
在我們做實際項目中,使用比較多的是[name],它與chunk是一一對應的關係,並且可讀性較高。如果要控制客戶端緩存,最好還要加上[chunkhash],因爲每個chunk所產生的[chunkhash]只與自身內容有關,單個chunk內容的改變不會影響其他資源,可以最精確地讓客戶端緩存得到更新。
如下:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js',
index2: './index2.js'
},
output: {
filename: '[name]@[chunkhash].js'
},
mode: 'development'
}
打包的效果如下:
這個[chunkhash] 更新緩存配置一般只在生產環境中配置,不在開發環境中配置
- path參數
path可以指定資源輸出的位置,要求值必須爲絕對路徑。如:
const path = require('path')
module.exports = {
context: path.join(__dirname, './src'),
entry: {
index: './index.js',
index2: './index2.js'
},
output: {
path: path.join(__dirname, 'dist')
filename: '[name]@[chunkhash].js'
},
mode: 'development'
}
在Webpack 4之後,output.path已經默認爲dist目錄,除非我們需要更改它,否則不必單獨配置。
- publicPath
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
},
mode: 'development',
"devServer": {
"publicPath": './dist',
"port": 3000
}
}
publicPath跟path有很大的區別:path用來指定資源的輸出位置,而publicPath則用來指定資源的請求位置的。
- 輸出位置:打包完成後資源產生的目錄,一般將其指定爲項目中的dist目錄。
- 請求位置:由JS或CSS所請求的間接資源路徑。頁面中的資源分爲兩種,一種是由HTML頁面直接請求的,比如通過script標籤加載的JS;另一種是由JS或CSS請求的,如異步加載的JS、從CSS請求的圖片字體等。publicPath的作用就是指定這部分間接資源的請求位置。
webpack-dev-server的配置中也有一個publicPath,但是,這個publicPath與Webpack中的配置項含義不同,它的作用是指定webpack-dev-server的靜態資源服務路徑。詳情請查看《Webpack實戰(二):webpack-dev-server的介紹與用法》
爲了避免開發環境和生產環境產生不一致而造成開發者的疑惑,我們可以將webpack-dev-server的publicPath與Webpack中的output.path保持一致,這樣在任何環境下資源輸出的目錄都是相同的
總結
有關Webpack資源入口和資源出口的配置就暫時分析到這裏,這僅代表個人觀點,歡迎拍磚,如想了解更多請掃描下面: