webpack相關(guān)

1、什么是webpack

webpack是一個打包模塊化javascript的工具,在webpack里一切文件皆模塊,通過loader轉(zhuǎn)換文件,通過plugin注入鉤子,最后輸出由多個模塊組合成的文件,webpack專注構(gòu)建模塊化項目。

WebPack可以看做是模塊打包機:它做的事情是,分析你的項目結(jié)構(gòu),找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),并將其打包為合適的格式以供瀏覽器使用。

官網(wǎng)的圖片形象的展示了webpack的定義


2、幾個常見的loader

file-loader:把文件輸出到一個文件夾中,在代碼中通過相對 URL 去引用輸出的文件

url-loader:和 file-loader 類似,但是能在文件很小的情況下以 base64 的方式把文件內(nèi)容注入到代碼中去

source-map-loader:加載額外的 Source Map 文件,以方便斷點調(diào)試

image-loader:加載并且壓縮圖片文件

babel-loader:把 ES6 轉(zhuǎn)換成 ES5

css-loader:加載 CSS,支持模塊化、壓縮、文件導(dǎo)入等特性

style-loader:把 CSS 代碼注入到 JavaScript 中,通過 DOM 操作去加載 CSS。

eslint-loader:通過 ESLint 檢查 JavaScript 代碼


3、幾個常見的plugin

define-plugin:定義環(huán)境變量

terser-webpack-plugin:通過TerserPlugin壓縮ES6代碼

html-webpack-plugin 為html文件中引入的外部資源,可以生成創(chuàng)建html入口文件

mini-css-extract-plugin:分離css文件

clean-webpack-plugin:刪除打包文件

happypack:實現(xiàn)多線程加速編譯


4、webpack與grunt、gulp的不同?

Webpack與Gulp、Grunt沒有什么可比性,它可以看作模塊打包機,通過分析你的項目結(jié)構(gòu),找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),并將其轉(zhuǎn)換和打包為合適的格式供瀏覽器使用。Gulp/Grunt是一種能夠優(yōu)化前端的開發(fā)流程的工具,而WebPack是一種模塊化的解決方案,不過Webpack的優(yōu)點使得Webpack在很多場景下可以替代Gulp/Grunt類的工具。

他們的工作方式也有較大區(qū)別:

Grunt和Gulp的工作方式是:在一個配置文件中,指明對某些文件進行類似編譯,組合,壓縮等任務(wù)的具體步驟,工具之后可以自動替你完成這些任務(wù)。

Webpack的工作方式是:把你的項目當做一個整體,通過一個給定的主文件(如:index.js),Webpack將從這個文件開始找到你的項目的所有依賴文件,使用loaders處理它們,最后打包為一個(或多個)瀏覽器可識別的JavaScript文件。

三者都是前端構(gòu)建工具,grunt和gulp在早期比較流行,現(xiàn)在webpack相對來說比較主流,不過一些輕量化的任務(wù)還是會用gulp來處理,比如單獨打包CSS文件等。

grunt和gulp是基于任務(wù)和流(Task、Stream)的。類似jQuery,找到一個(或一類)文件,對其做一系列鏈式操作,更新流上的數(shù)據(jù), 整條鏈式操作構(gòu)成了一個任務(wù),多個任務(wù)就構(gòu)成了整個web的構(gòu)建流程。

webpack是基于入口的。webpack會自動地遞歸解析入口所需要加載的所有資源文件,然后用不同的Loader來處理不同的文件,用Plugin來擴展webpack功能。

所以總結(jié)一下:

從構(gòu)建思路來說

gulp和grunt需要開發(fā)者將整個前端構(gòu)建過程拆分成多個Task,并合理控制所有Task的調(diào)用關(guān)系

webpack需要開發(fā)者找到入口,并需要清楚對于不同的資源應(yīng)該使用什么Loader做何種解析和加工

對于知識背景來說

gulp更像后端開發(fā)者的思路,需要對于整個流程了如指掌 webpack更傾向于前端開發(fā)者的思路

webpack有哪些優(yōu)點

專注于處理模塊化的項目,能做到開箱即用,一步到位

可通過plugin擴展,完整好用又不失靈活

使用場景不局限于web開發(fā)

社區(qū)龐大活躍,經(jīng)常引入緊跟時代發(fā)展的新特性,能為大多數(shù)場景找到已有的開源擴展

良好的開發(fā)體驗


5、webpack的缺點

webpack的缺點是只能用于采用模塊化開發(fā)的項目


6、分別介紹bundle,chunk,module是什么

bundle:是由webpack打包出來的文件,

chunk:代碼塊,一個chunk由多個模塊組合而成,用于代碼的合并和分割。

module:是開發(fā)中的單個模塊,在webpack的世界,一切皆模塊,一個模塊對應(yīng)一個文件,webpack會從配置的entry中遞歸開始找出所有依賴的模塊。


7、分別介紹什么是loader?什么是plugin?

loader:模塊轉(zhuǎn)換器,用于將模塊的原內(nèi)容按照需要轉(zhuǎn)成你想要的內(nèi)容

plugin:在webpack構(gòu)建流程中的特定時機注入擴展邏輯,來改變構(gòu)建結(jié)果,是用來自定義webpack打包過程的方式,一個插件是含有apply方法的一個對象,通過這個方法可以參與到整個webpack打包的各個流程(生命周期)。


8、什么 是模塊熱更新?

模塊熱更新是webpack的一個功能,他可以使得代碼修改過后不用刷新瀏覽器就可以更新,是高級版的自動刷新瀏覽器。

devServer中通過hot屬性可以空時模塊的熱替換

1.通過配置文件

const webpack = require('webpack');
const path = require('path');
let env = process.env.NODE_ENV == "development" ? "development" : "production";
const config = {
? mode: env,
?devServer: {
???? hot:true
?}
}
? plugins: [
???? new webpack.HotModuleReplacementPlugin(), //熱加載插件
? ],
module.exports = config;

2.通過命令行

? "scripts": {
??? "test": "echo \"Error: no test specified\" && exit 1",
??? "start": "NODE_ENV=development? webpack-dev-server --config? webpack.develop.config.js --hot",
? },


9、什么是Tree-shaking

Tree-shaking可以用來剔除javascript中不用的死代碼,它依賴靜態(tài)的es6模塊化語法,例如通過哦import 和export 導(dǎo)入導(dǎo)出,Tree-shaking最先在rollup中出現(xiàn),webpack在2.0中將其引入,css中使用Tree-shaking需要引入Purify-CSS


10、通過webpack處理長緩存

瀏覽器在用戶訪問頁面的時候,為了加快加載速度,會對用戶訪問的靜態(tài)資源進行存儲,但是每一次代碼升級或是更新,都需要瀏覽器去下載新的代碼,最方便和簡單的更新方式就是引入新的文件名稱。在webpack中可以在output縱輸出的文件指定chunkhash,并且分離經(jīng)常更新的代碼和框架代碼。通過NameModulesPlugin或是HashedModuleIdsPlugin使再次打包文件名不變。


11、如何提高webpack的構(gòu)建速度

1、通過externals配置來提取常用庫

2、利用DllPlugin和DllReferencePlugin預(yù)編譯資源模塊 通過DllPlugin來對那些我們引用但是絕對不會修改的npm包來進行預(yù)編譯,再通過DllReferencePlugin將預(yù)編譯的模塊加載進來。

3、使用Happypack 實現(xiàn)多線程加速編譯

要注意的第一點是,它對file-loader和url-loader支持不好,所以這兩個loader就不需要換成happypack了,其他loader可以類似地換一下

4、使用Tree-shaking和Scope Hoisting來剔除多余代碼

5、使用fast-sass-loader代替sass-loader

6、babel-loader開啟緩存

babel-loader在執(zhí)行的時候,可能會產(chǎn)生一些運行期間重復(fù)的公共文件,造成代碼體積大冗余,同時也會減慢編譯效率

可以加上cacheDirectory參數(shù)或使用 transform-runtime 插件試試

// webpack.config.js
use: [{
??? loader: 'babel-loader',
??? options: {
??????? cacheDirectory: true
}]
// .bablerc
{
??? "presets": [
??????? "env",
??????? "react"
??? ],
??? "plugins": ["transform-runtime"]
}

7、不需要打包編譯的插件庫換成全局"script"標簽引入的方式

比如jQuery插件,react, react-dom等,代碼量是很多的,打包起來可能會很耗時可以直接用標簽引入,然后在webpack配置里使用 expose-loader? 或 externals 或 ProvidePlugin? 提供給模塊內(nèi)部使用相應(yīng)的變量

// @1
use: [{
??? loader: 'expose-loader',
??? options: '$'
??? }, {
??? loader: 'expose-loader',
??? options: 'jQuery'
??? }]
// @2
externals: {
??????? jquery: 'jQuery'
??? },
// @3
new webpack.ProvidePlugin({
??? $: 'jquery',
??? jQuery: 'jquery',
??? 'window.jQuery': 'jquery'
}),

8、優(yōu)化構(gòu)建時的搜索路徑

在webpack打包時,會有各種各樣的路徑要去查詢搜索,我們可以加上一些配置,讓它搜索地更快

比如說,方便改成絕對路徑的模塊路徑就改一下,以純模塊名來引入的可以加上一些目錄路徑

還可以善于用下resolve alias別名 這個字段來配置

還有exclude等的配置,避免多余查找的文件,比如使用babel別忘了剔除不需要遍歷的


12、如何利用webpack來優(yōu)化前端性能?(提高性能和體驗)

用webpack優(yōu)化前端性能是指優(yōu)化webpack的輸出結(jié)果,讓打包的最終結(jié)果在瀏覽器運行快速高效。

1.壓縮代碼。刪除多余的代碼、注釋、簡化代碼的寫法等等方式??梢岳脀ebpack的UglifyJsPlugin和ParallelUglifyPlugin來壓縮JS文件, 利用cssnano(css-loader?minimize)來壓縮css

2.利用CDN加速。在構(gòu)建過程中,將引用的靜態(tài)資源路徑修改為CDN上對應(yīng)的路徑??梢岳脀ebpack對于output參數(shù)和各loader的publicPath參數(shù)來修改資源路徑

3.刪除死代碼(Tree Shaking)。將代碼中永遠不會走到的片段刪除掉??梢酝ㄟ^在啟動webpack時追加參數(shù)--optimize-minimize來實現(xiàn)

4.提取公共代碼。


13、如何提高webpack的構(gòu)建速度?

1.多入口情況下,使用CommonsChunkPlugin來提取公共代碼

2.通過externals配置來提取常用庫

3.利用DllPlugin和DllReferencePlugin預(yù)編譯資源模塊 通過DllPlugin來對那些我們引用但是絕對不會修改的npm包來進行預(yù)編譯,再通過DllReferencePlugin將預(yù)編譯的模塊加載進來。

4.使用Happypack 實現(xiàn)多線程加速編譯

5.使用webpack-uglify-parallel來提升uglifyPlugin的壓縮速度。 原理上webpack-uglify-parallel采用了多核并行壓縮來提升壓縮速度

6.使用Tree-shaking和Scope Hoisting來剔除多余代碼


14、怎么配置單頁應(yīng)用?怎么配置多頁應(yīng)用?

單頁應(yīng)用可以理解為webpack的標準模式,直接在entry中指定單頁應(yīng)用的入口即可,這里不再贅述

多頁應(yīng)用的話,可以使用webpack的 AutoWebPlugin來完成簡單自動化的構(gòu)建,但是前提是項目的目錄結(jié)構(gòu)必須遵守他預(yù)設(shè)的規(guī)范。 多頁應(yīng)用中要注意的是:

1.每個頁面都有公共的代碼,可以將這些代碼抽離出來,避免重復(fù)的加載。比如,每個頁面都引用了同一套css樣式表

2.隨著業(yè)務(wù)的不斷擴展,頁面可能會不斷的追加,所以一定要讓入口的配置足夠靈活,避免每次添加新頁面還需要修改構(gòu)建配置


15、npm打包時需要注意哪些?如何利用webpack來更好的構(gòu)建?

Npm是目前最大的 JavaScript 模塊倉庫,里面有來自全世界開發(fā)者上傳的可復(fù)用模塊。你可能只是JS模塊的使用者,但是有些情況你也會去選擇上傳自己開發(fā)的模塊。 關(guān)于NPM模塊上傳的方法可以去官網(wǎng)上進行學(xué)習,這里只講解如何利用webpack來構(gòu)建。

NPM模塊需要注意以下問題:

1.要支持CommonJS模塊化規(guī)范,所以要求打包后的最后結(jié)果也遵守該規(guī)則。

2.Npm模塊使用者的環(huán)境是不確定的,很有可能并不支持ES6,所以打包的最后結(jié)果應(yīng)該是采用ES5編寫的。并且如果ES5是經(jīng)過轉(zhuǎn)換的,請最好連同SourceMap一同上傳。

3.Npm包大小應(yīng)該是盡量?。ㄓ行﹤}庫會限制包大小)

4.發(fā)布的模塊不能將依賴的模塊也一同打包,應(yīng)該讓用戶選擇性的去自行安裝。這樣可以避免模塊應(yīng)用者再次打包時出現(xiàn)底層模塊被重復(fù)打包的情況。

5.UI組件類的模塊應(yīng)該將依賴的其它資源文件,例如.css文件也需要包含在發(fā)布的模塊里。

基于以上需要注意的問題,我們可以對于webpack配置做以下擴展和優(yōu)化:

1.CommonJS模塊化規(guī)范的解決方案: 設(shè)置output.libraryTarget='commonjs2'使輸出的代碼符合CommonJS2 模塊化規(guī)范,以供給其它模塊導(dǎo)入使用

2.輸出ES5代碼的解決方案:使用babel-loader把 ES6 代碼轉(zhuǎn)換成 ES5 的代碼。再通過開啟devtool: 'source-map'輸出SourceMap以發(fā)布調(diào)試。

3.Npm包大小盡量小的解決方案:Babel 在把 ES6 代碼轉(zhuǎn)換成 ES5 代碼時會注入一些輔助函數(shù),最終導(dǎo)致每個輸出的文件中都包含這段輔助函數(shù)的代碼,造成了代碼的冗余。解決方法是修改.babelrc文件,為其加入transform-runtime插件

4.不能將依賴模塊打包到NPM模塊中的解決方案:使用externals配置項來告訴webpack哪些模塊不需要打包。

5.對于依賴的資源文件打包的解決方案:通過css-loader和extract-text-webpack-plugin來實現(xiàn),配置如下:


16、如何在vue項目中實現(xiàn)按需加載?

VueUI組件庫的按需加載 為了快速開發(fā)前端項目,經(jīng)常會引入現(xiàn)成的UI組件庫如ElementUI、iView等,但是他們的體積和他們所提供的功能一樣,是很龐大的。而通常情況下,我們僅僅需要少量的幾個組件就足夠了,但是我們卻將龐大的組件庫打包到我們的源碼中,造成了不必要的開銷。

不過很多組件庫已經(jīng)提供了現(xiàn)成的解決方案,如Element出品的babel-plugin-component和AntDesign出品的babel-plugin-import安裝以上插件后,在.babelrc配置中或babel-loader的參數(shù)中進行設(shè)置,即可實現(xiàn)組件按需加載了。

單頁應(yīng)用的按需加載 現(xiàn)在很多前端項目都是通過單頁應(yīng)用的方式開發(fā)的,但是隨著業(yè)務(wù)的不斷擴展,會面臨一個嚴峻的問題——首次加載的代碼量會越來越多,影響用戶的體驗。

通過import(*)語句來控制加載時機,webpack內(nèi)置了對于import(*)的解析,會將import(*)中引入的模塊作為一個新的入口在生成一個chunk。

當代碼執(zhí)行到import(*)語句時,會去加載Chunk對應(yīng)生成的文件。import()會返回一個Promise對象,所以為了讓瀏覽器支持,需要事先注入Promise polyfill

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容