Entry
:入口,Webpack 執行構建的第一步將從 Entry 開始。Module
:模塊,在 Webpack 裏一切皆模塊,一個模塊對應着一個文件。Webpack 會從配置的 Entry 開始遞歸找出全部依賴的模塊。Chunk
:代碼塊,一個chunk由多個模塊組合而成,用於代碼合併與分割。Loader
:模塊轉換器,用於將模塊的原內容按照需求轉換成新內容。Plugin
:插件,在 Webpack 構建流程中的特定時機會廣播出對應的事件,插件能夠監聽這些事件的發生,在特定時機作對應的事情。初始化參數
——> 開始編譯
——> 肯定入口
——> 編譯模塊
——> 完成模塊編譯
——> 輸出資源
——> 輸出完成
javascript
Compiler
對象,加載全部配置的插件Plugin
,經過執行對象的run方法開始執行編譯entry
找出全部的入口文件Loader
對模塊進行編譯,再找出該模塊依賴的模塊,再遞歸本步驟直到全部入口依賴的文件都通過處理chunk
,再將每一個chunk轉換成一個單獨的文件加入輸出列表中,這是能夠修改輸出內容的最後機會寫入文件系統中
(fs)總結一下,Webpack的構建流程能夠分爲如下三大階段
:java
bundle.js
實際上是一個當即執行函數,bundle.js
能直接運行在瀏覽器中的緣由在於輸出的文件中經過__webpack_require__
函數定義了一個能夠在瀏覽器中執行的加載函數來模擬Node.js中的require語句。 並且Webpack 作了緩存優化,執行加載過的模塊不會再執行第二次,執行結果會緩存在內存中,當某個模塊第二次被訪問時會直接去內存中讀取被緩存的返回值。node
(function(modules){
//模擬require語句
function __webpack_require__(){}
//執行存放全部模塊數組中的第0個模塊(main.js)
__webpack_require_[0]
})([/*存放全部模塊的數組*/])
複製代碼
優化Loader
:優化 Loader 的文件搜索範圍(exclude掉node_modules)、將Babel編譯過的文件緩存起來(loader: 'babel-loader?cacheDirectory=true')。 對於 Loader 來講,影響打包效率首當其衝必屬 Babel 了。由於 Babel 會將代碼轉爲字符串生成 AST,而後對 AST 繼續進行轉變最後再生成新的代碼
,項目越大,轉換代碼越多,效率就越低。HappyPack
: 能夠將Loader的同步執行轉換爲並行的。module: {
loaders: [
{
test: /\.js$/,
include: [resolve('src')],
exclude: /node_modules/,
// id 後面的內容對應下面
loader: 'happypack/loader?id=happybabel'
}
]
},
plugins: [
new HappyPack({
id: 'happybabel',
loaders: ['babel-loader?cacheDirectory'],
// 開啓 4 個線程
threads: 4
})
]
複製代碼
DllPlugin
: 能夠將特定的類庫提早打包而後引入。極大的減小打包類庫的次數,只有當類庫更新版本纔有須要從新打包。// 單獨配置在一個文件中
// webpack.dll.conf.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: {
// 想統一打包的類庫
vendor: ['react']
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].dll.js',
library: '[name]-[hash]'
},
plugins: [
new webpack.DllPlugin({
// name 必須和 output.library 一致
name: '[name]-[hash]',
// 該屬性須要與 DllReferencePlugin 中一致
context: __dirname,
path: path.join(__dirname, 'dist', '[name]-manifest.json')
})
]
}
// 使用 DllReferencePlugin 將依賴文件引入項目中
// webpack.conf.js
module.exports = {
// ...省略其餘配置
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
// manifest 就是以前打包出來的 json 文件
manifest: require('./dist/vendor-manifest.json'),
})
]
}
複製代碼
代碼壓縮
:webpack3中使用 webpack-parallel-uglify-plugin
來並行運行 UglifyJS
(單線程),webpack4中將mode
設置爲production
則默認開啓壓縮。按需加載
:每一個路由頁面單獨打包爲一個文件、loadash
這種大型類庫一樣能夠使用這個功能。Scope Hoisting
: 會分析出模塊之間的依賴關係,儘量的把打包出來的模塊合併到一個函數中去。Webpack4 中開啓這個功能,只須要啓用 optimization.concatenateModules
。// test.js
export const a = 1
// index.js
import { a } from './test.js'
複製代碼
打包上面兩個文件後,生成代碼相似這樣:react
[
/* 0 */
function (module, exports, require) {
//...
},
/* 1 */
function (module, exports, require) {
//...
}
]
複製代碼
若是使用Scope Hositing,會生成這樣的相似代碼:webpack
[
/* 0 */
function (module, exports, require) {
//...
}
]
複製代碼
Tree Shaking
:能夠實現刪除項目中未被引用的代碼。Webpack4的生產環境默認開啓這個功能。// test.js
export const a = 1
export const b = 2
// index.js
import { a } from './test.js'
複製代碼
test 文件中的變量 b 若是沒有在項目中使用到的話,就不會被打包到文件中。web