隨着現代前端開發的複雜度和規模愈來愈龐大,已經不能拋開工程化來獨立開發了,如react的jsx代碼必須編譯後才能在瀏覽器中使用;又如sass和less的代碼瀏覽器也是不支持的。 而若是摒棄了這些開發框架,那麼開發的效率將大幅降低。在衆多前端工程化工具中,webpack
脫穎而出成爲了當今最流行的前端構建工具。 然而大多數的使用者都只是單純的會使用
,而並不知道其深層的原理。但願經過如下的面試題總結能夠幫助你們溫故知新、查缺補漏,知其然而又知其因此然。css
三者都是前端構建工具,grunt和gulp在早期比較流行,如今webpack相對來講比較主流,不過一些輕量化的任務仍是會用gulp來處理,好比單獨打包CSS文件等。前端
grunt和gulp是基於任務和流(Task、Stream)的。相似jQuery,找到一個(或一類)文件,對其作一系列鏈式操做,更新流上的數據, 整條鏈式操做構成了一個任務,多個任務就構成了整個web的構建流程。vue
webpack是基於入口的。webpack會自動地遞歸解析入口所須要加載的全部資源文件,而後用不一樣的Loader來處理不一樣的文件,用Plugin來擴展webpack功能。react
因此總結一下:webpack
gulp和grunt須要開發者將整個前端構建過程拆分紅多個`Task`,併合理控制全部`Task`的調用關係
webpack須要開發者找到入口,並須要清楚對於不一樣的資源應該使用什麼Loader作何種解析和加工複製代碼
一樣是基於入口的打包工具還有如下幾個主流的:git
從應用場景上來看:github
因爲parcel在打包過程當中給出的調試信息十分有限,因此一旦打包出錯難以調試,因此不建議複雜的項目使用parcel
UglifyES
壓縮ES6
代碼不一樣的做用web
loader
。 因此Loader的做用是讓webpack擁有了加載和解析非JavaScript文件的能力。不一樣的用法面試
module.rules
中配置,也就是說他做爲模塊的解析規則而存在。 類型爲數組,每一項都是一個Object
,裏面描述了對於什麼類型的文件(test
),使用什麼加載(loader
)和使用的參數(options
)plugins
中單獨配置。 類型爲數組,每一項是一個plugin
的實例,參數都經過構造函數傳入。Webpack 的運行流程是一個串行的過程,從啓動到結束會依次執行如下流程:npm
在以上過程當中,Webpack 會在特定的時間點廣播出特定的事件,插件在監聽到感興趣的事件後會執行特定的邏輯,而且插件能夠調用 Webpack 提供的 API 改變 Webpack 的運行結果。
Loader像一個"翻譯官"把讀到的源文件內容轉義成新的文件內容,而且每一個Loader經過鏈式操做,將源文件一步步翻譯成想要的樣子。
編寫Loader時要遵循單一原則,每一個Loader只作一種"轉義"工做。 每一個Loader的拿到的是源文件內容(source
),能夠經過返回值的方式將處理後的內容輸出,也能夠調用this.callback()
方法,將內容返回給webpack。 還能夠經過 this.async()
生成一個callback
函數,再用這個callback將處理後的內容輸出出去。 此外webpack
還爲開發者準備了開發loader的工具函數集——loader-utils
。
相對於Loader而言,Plugin的編寫就靈活了許多。 webpack在運行的生命週期中會廣播出許多事件,Plugin 能夠監聽這些事件,在合適的時機經過 Webpack 提供的 API 改變輸出結果。
webpack的熱更新又稱熱替換(Hot Module Replacement),縮寫爲HMR。 這個機制能夠作到不用刷新瀏覽器而將新變動的模塊替換掉舊的模塊。
原理:
首先要知道server端和client端都作了處理工做
用webpack優化前端性能是指優化webpack的輸出結果,讓打包的最終結果在瀏覽器運行快速高效。
UglifyJsPlugin
和ParallelUglifyPlugin
來壓縮JS文件, 利用cssnano
(css-loader?minimize)來壓縮cssoutput
參數和各loader的publicPath
參數來修改資源路徑--optimize-minimize
來實現CommonsChunkPlugin
來提取公共代碼externals
配置來提取經常使用庫DllPlugin
和DllReferencePlugin
預編譯資源模塊 經過DllPlugin
來對那些咱們引用可是絕對不會修改的npm包來進行預編譯,再經過DllReferencePlugin
將預編譯的模塊加載進來。Happypack
實現多線程加速編譯webpack-uglify-parallel
來提高uglifyPlugin
的壓縮速度。 原理上webpack-uglify-parallel
採用了多核並行壓縮來提高壓縮速度Tree-shaking
和Scope Hoisting
來剔除多餘代碼單頁應用能夠理解爲webpack的標準模式,直接在entry
中指定單頁應用的入口便可,這裏再也不贅述
多頁應用的話,可使用webpack的 AutoWebPlugin
來完成簡單自動化的構建,可是前提是項目的目錄結構必須遵照他預設的規範。 多頁應用中要注意的是:
Npm
是目前最大的 JavaScript 模塊倉庫,裏面有來自全世界開發者上傳的可複用模塊。你可能只是JS模塊的使用者,可是有些狀況你也會去選擇上傳本身開發的模塊。 關於NPM模塊上傳的方法能夠去官網上進行學習,這裏只講解如何利用webpack來構建。
NPM模塊須要注意如下問題:
.css
文件也須要包含在發佈的模塊裏。基於以上須要注意的問題,咱們能夠對於webpack配置作如下擴展和優化:
output.libraryTarget='commonjs2'
使輸出的代碼符合CommonJS2 模塊化規範,以供給其它模塊導入使用babel-loader
把 ES6 代碼轉換成 ES5 的代碼。再經過開啓devtool: 'source-map'
輸出SourceMap以發佈調試。.babelrc
文件,爲其加入transform-runtime
插件externals
配置項來告訴webpack哪些模塊不須要打包。css-loader
和extract-text-webpack-plugin
來實現,配置以下:const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
// 增長對 CSS 文件的支持
test: /\.css/,
// 提取出 Chunk 中的 CSS 代碼到單獨的文件中
use: ExtractTextPlugin.extract({
use: ['css-loader']
}),
},
]
},
plugins: [
new ExtractTextPlugin({
// 輸出的 CSS 文件名稱
filename: 'index.css',
}),
],
};
複製代碼
Vue UI組件庫的按需加載 爲了快速開發前端項目,常常會引入現成的UI組件庫如ElementUI、iView等,可是他們的體積和他們所提供的功能同樣,是很龐大的。 而一般狀況下,咱們僅僅須要少許的幾個組件就足夠了,可是咱們卻將龐大的組件庫打包到咱們的源碼中,形成了沒必要要的開銷。
不過不少組件庫已經提供了現成的解決方案,如Element出品的babel-plugin-component
和AntDesign出品的babel-plugin-import
安裝以上插件後,在.babelrc
配置中或babel-loader
的參數中進行設置,便可實現組件按需加載了。
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
複製代碼
單頁應用的按需加載 如今不少前端項目都是經過單頁應用的方式開發的,可是隨着業務的不斷擴展,會面臨一個嚴峻的問題——首次加載的代碼量會愈來愈多,影響用戶的體驗。
經過import(*)
語句來控制加載時機,webpack內置了對於import(*)
的解析,會將import(*)
中引入的模塊做爲一個新的入口在生成一個chunk。 當代碼執行到import(*)
語句時,會去加載Chunk對應生成的文件。import()
會返回一個Promise對象,因此爲了讓瀏覽器支持,須要事先注入Promise polyfill