面試官:請手寫一個 webpack 4.0 配置2018-07-24

確認過眼神慨亲,你還是沒有準備秋招的人鸳劳?時間倉促狰贯。自京東6月8號開啟管培生的招聘,就意味著秋招的開始赏廓。然而你還在等著秋天的到來涵紊?今年形勢應(yīng)該更為嚴峻,隨著各大技術(shù)(vue,webpack幔摸,react摸柄,微信小程序)生態(tài)越來越成熟,這也意味著我們要更加深入的去了解他們既忆,掌握他們驱负。比如你寫vue項目,知道vue-cli患雇。寫的項目也無以倫比跃脊,但是你是否又會去了解下vue-cli到底發(fā)生了什么?或許這就是面試官要問你的問題:請手寫一個webpack4.0的配置苛吱。

前言

機會總是留給有準備的人酪术,要想在這兵荒馬亂的求職季里出類拔萃,拿下你心中期待已久的offer翠储。那么你更因該知道很多別人不知道的東西绘雁,你的羽翼才能豐滿,才能翱翔于天際援所。鷹擊長空庐舟,靠的不是天生,而是年少時斷崖之險任斋。笨鳥先飛继阻,靠的不是智慧,而是孜孜不倦的努力废酷。

webpack詳解

webpack是一個打包工具瘟檩,他的宗旨是一切靜態(tài)資源即可打包。有人就會問為什么要webpack澈蟆?webpack是現(xiàn)代前端技術(shù)的基石墨辛,常規(guī)的開發(fā)方式,比如jquery,html,css靜態(tài)網(wǎng)頁開發(fā)已經(jīng)落后了∨糠現(xiàn)在是MVVM的時代睹簇,數(shù)據(jù)驅(qū)動界面奏赘。webpack將現(xiàn)代js開發(fā)中的各種新型有用的技術(shù),集合打包太惠。webpack的描述鋪天蓋地磨淌,我就不浪費大家的時間了。理解下這種圖就知道webpack的生態(tài)圈了:

webpack4.0的配置

const path = require('path'); //引入node的path模塊

const webpack = require('webpack'); //引入的webpack,使用lodash

const HtmlWebpackPlugin = require('html-webpack-plugin') //將html打包

const ExtractTextPlugin = require('extract-text-webpack-plugin') //打包的css拆分,將一部分抽離出來?

const CopyWebpackPlugin = require('copy-webpack-plugin')

// console.log(path.resolve(__dirname,'dist')); //物理地址拼接

module.exports = {

? ? entry: './src/index.js', //入口文件? 在vue-cli main.js

? ? output: { //webpack如何輸出

? ? ? ? path: path.resolve(__dirname, 'dist'), //定位凿渊,輸出文件的目標路徑

? ? ? ? filename: '[name].js'

},

module: { //模塊的相關(guān)配置

? ? ? ? rules: [ //根據(jù)文件的后綴提供一個loader,解析規(guī)則

{

? ? ? ? ? ? ? ? test: /.js$/, //es6 => es5

? ? ? ? ? ? ? ? include: [

? ? ? ? ? ? ? ? ? ? path.resolve(__dirname, 'src')

],

// exclude:[], 不匹配選項(優(yōu)先級高于test和include)

use: 'babel-loader'

},

{

? ? ? ? ? ? ? ? test: /.less$/,

use: ExtractTextPlugin.extract({

? ? ? ? ? ? ? ? ? ? fallback: 'style-loader',

use: [

'css-loader',

'less-loader'

]

})

},

{ //圖片loader

? ? ? ? ? ? ? ? test: /.(png|jpg|gif)$/,

use: [

{

? ? ? ? ? ? ? ? ? ? ? ? loader: 'file-loader' //根據(jù)文件地址加載文件

}

]

}

]

},

? ? resolve: { //解析模塊的可選項?

// modules: [ ]//模塊的查找目錄 配置其他的css等文件

? ? ? ? extensions: [".js", ".json", ".jsx",".less", ".css"], //用到文件的擴展名

alias: { //牧褐唬快別名列表

? ? ? ? ? ? utils: path.resolve(__dirname,'src/utils')

}

},

? ? plugins: [ //插進的引用, 壓縮,分離美化

new ExtractTextPlugin('[name].css'), //[name] 默認? 也可以自定義name? 聲明使用

new HtmlWebpackPlugin({ //將模板的頭部和尾部添加css和js模板,dist 目錄發(fā)布到服務(wù)器上埃脏,項目包搪锣。可以直接上線

? ? ? ? ? ? file: 'index.html', //打造單頁面運用 最后運行的不是這個

template: 'src/index.html' //vue-cli放在跟目錄下

}),

new CopyWebpackPlugin([ //src下其他的文件直接復(fù)制到dist目錄下

{ from:'src/assets/favicon.ico',to: 'favicon.ico' }

]),

new webpack.ProvidePlugin({ //引用框架 jquery? lodash工具庫是很多組件會復(fù)用的彩掐,省去了import

'_': 'lodash' //引用webpack

})

],

? ? devServer: { //服務(wù)于webpack-dev-server? 內(nèi)部封裝了一個express

? ? ? ? port: '8080',

? ? ? ? before(app) {

? ? ? ? ? ? app.get('/api/test.json', (req, res) => {

? ? ? ? ? ? ? ? res.json({

? ? ? ? ? ? ? ? ? ? code: 200,

? ? ? ? ? ? ? ? ? ? message: 'Hello World'

})

})

}

}

}

一构舟、前端環(huán)境搭建

我們使用npm或yarn來安裝webpack。

npm install webpack webpack-cli -g

# 或者

yarn global add webpack webpack-cli

為什么webpack會分為兩個文件呢堵幽?在webpack3中狗超,webpack本身和它的cli以前都是在同一個包中,但在第4版中谐檀,他們已經(jīng)將兩者分開來更好地管理它們抡谐。

新建一個webpack的文件夾,在其下新建一個try-webpack(防止init時項目名和安裝包同名)并初始化和配置webpack桐猬。

npm init -y? //-y 默認所有的配置

yarn add webpack webpack-cli -D? //-D webpack安裝在devDependencies環(huán)境中

二、部署webpack

在上面搭建好的環(huán)境項目中刽肠,我們來到package.json里配置我們的scripts溃肪。

"scripts": {

"build": "webpack --mode production" //我們在這里配置,就可以使用npm run build 啟動我們的webpack

},

"devDependencies": {

"webpack": "^4.16.0",

"webpack-cli": "^3.0.8"

}

配置好我們webpack的運行環(huán)境時音五,聯(lián)想下vue-cli惫撰。平時使用vue-cli會自動幫我們配置并生成項目。我們在src下進行項目的開發(fā)躺涝,最后npm run build 打包生成我們的dist的目錄厨钻。不知道你是否還記得,還是讓我們進入下一節(jié)讓我們感受下這其中的正個流程吧坚嗜。

三夯膀、npm run build 發(fā)生了什么

在我們的根項目下try-webpack新建一個src目錄。在src目錄下新建一個index.js文件苍蔬。在里面我們可以寫任意的代碼诱建,以案例為主:

const a = 1;

寫完之后我們在終端運行我們的命令: npm run build ,你就會發(fā)現(xiàn)新增了一個dist目錄碟绑,里面存放著webpack打包好的main.js文件俺猿。這和我們在vue-cli里操作是一樣的茎匠。

四、webpackp配置流程篇

我們在開發(fā)是一般會打包src下的什么文件呢押袍?我們可以回憶一下诵冒,其實vue-cli項目src下不就這幾點嘛:

發(fā)布時需要的html,css谊惭,js

css預(yù)編譯器stylus汽馋,less,sass

es6的高級語法

圖片資源.png午笛,.gif惭蟋,.ico,.jpg

文件間的require

別名@等修飾符

那么我將會分這幾點來講解webpack中webpack.config.js的配置药磺,跟著腳步告组,一步一步的來完成我們的流程線。

??Html在webpack中的配置

在項目的根目錄try-webpack下新建webpack.config.js文件癌佩,以commonJS模塊化機制向外輸出木缝,并且新建一個index.html。

module.exports = {}

配置我們的入口entry围辙,在vue-cli里相當于跟目錄下的main.js我碟,我們的出口output。我們可以把webpack理解為一個工廠姚建,進入相當于把各種各樣的原料放進我們的工廠了矫俺,然后工廠進行一系列的打包操作把打包好的東西,向外輸出掸冤,然后就可以去出售了(上線)厘托。

const path = require('path'); //引入我們的node模塊里的path

//測試下 console.log(path.resolve(__dirname,'dist')); //物理地址拼接

module.exports = {

? ? entry: './src/index.js', //入口文件? 在vue-cli main.js

? ? output: { //webpack如何向外輸出

? ? ? ? path: path.resolve(__dirname, 'dist'),//定位,輸出文件的目標路徑

? ? ? ? filename: '[name].js' //文件名[name].js默認稿湿,也可自行配置

},

HTML打包我們需要安裝引入html-webpack-plugin

yarn add html-webpack-plugin -D //在開發(fā)環(huán)境中安裝

const HtmlWebpackPlugin = require('html-webpack-plugin') //引入打包我們的HTML

在module.exports里配置我們的plugins(插件):

plugins: [ //插進的引用, 壓縮铅匹,分離美化

new HtmlWebpackPlugin({ //將模板的頭部和尾部添加css和js模板,dist 目錄發(fā)布到服務(wù)器上,項目包饺藤“撸可以直接上線

? ? ? ? ? ? file: 'index.html', //打造單頁面運用 最后運行的不是這個

template: 'src/index.html' //vue-cli放在跟目錄下

}),

],

配置好后,在終端輸入npm run dev后webpack將我們的html打包好并且自動將我們的js引進來了涕俗。

Hello World

live-sever我們的dist目錄罗丰,啟動一個8080端口,我們就可以看到我們的Hello World了咽袜。這就是我們上線版的頁面丸卷。

??css在webpack中的配置

在我們vue-cli里,我們可以使用css去寫我們的樣式询刹,也可以使用高級stylus谜嫉,less萎坷,sass等預(yù)編譯器。這里就以less為例沐兰,看看webpack怎么將他打包成一個css哆档。

.main {

? color: red;

}

在src目錄下新建我們的style.less文件,在配置之前我們需要npm我們的css-loader和sass-loader住闯,sass:

yarn add css-loader less less-loader style-loader-D

執(zhí)行完上述命令我們在packge.json里可以看到我們的配置文件:

"devDependencies": {

"css-loader": "^1.0.0",

"html-webpack-plugin": "^3.2.0",

"sass": "^1.9.0",

"sass-loader": "^7.0.3",

"webpack": "^4.16.0",

"webpack-cli": "^3.0.8"

}

安裝好后瓜浸,我們開始配置webpack.config.js文件。這里申明一下比原,我們的css在dist目錄下需要和我們的HTML分離插佛,這是還需引入我們的extract-text-webpack-plugin,先然我們安裝下:

yarn add extract-text-webpack-plugin-D

這里有一個坑量窘,extract-text-webpack-plugin在4.0并不支持這樣的安裝雇寇,大家可自行chrome。于是我們選擇換一種方式蚌铜,選擇4.00-beta.0版本的:

yarn add extract-text-webpack-plugin@last-D

來到我們的module.exports里锨侯,完成moudel的配置:

const ExtractTextPlugin = require('extract-text-webpack-plugin') //打包的css拆分,將一部分抽離出來?

module: { //模塊的相關(guān)配置

? ? ? ? rules: [ //根據(jù)文件的后綴提供一個loader,解析規(guī)則

{

? ? ? ? ? ? ? ? test: /.less$/, //正則匹配我們以.less結(jié)尾的文件

use: ExtractTextPlugin.extract({

? ? ? ? ? ? ? ? ? ? fallback: 'style-loader',

use: [

'css-loader',

'less-loader'

]

})

},

]},

? ? plugins:[

new ExtractTextPlugin('[name].css'), //[name] 默認? 也可以自定義name? 聲明使用

]

我們在執(zhí)行我們的 npm run build 之后并沒有我們的css,為什么呢冬殃?原來在webpack配置里css in js囚痴。意思是在打包是我們的css是打包在我們的js里的,所有我們引入了extract-text-webpack-plugin插件將css從里面剝離出來审葬。不過又一個問題深滚,require的機制?

在我們打包過程中涣觉,文件的引用require 按照順序來打包成箫,這就是文件依賴的機制。

打包好后我們在live-server旨枯,發(fā)現(xiàn)我們的樣式也上去了,并且css部分分離出來了混驰。

??js在webpack中的配置

現(xiàn)在隨著es6的普及攀隔,越來越多的代碼使用es6了,但是很多瀏覽器并不支持es6栖榨,比如async/awiat昆汹,const。因此需要我們引用babe來把我們es6的代碼編譯為es5婴栽。在跟目錄下新建.babelrc满粗,簡單配置下:

{"presets": ["env"]}

安裝我們的babel并在webpack.config.js里module/rules下進行配置:

yarn add babel-loader babel-core? abel-preset-env -D? //babel基本的三個文件

{

? ? test: /.js$/, //es6 => es5

? ? include: [

? ? ? ? path.resolve(__dirname, 'src')

],

// exclude:[], 不匹配選項(優(yōu)先級高于test和include)

use: 'babel-loader'

},

??圖片資源在webpack中的配置

在src目錄下新建一個assets文件,里面放置幾張圖片愚争。安裝file-loader根據(jù)文件地址加載文件:

yarn add file-loader -D

在webpack.config.js里module/rules:

{

? ? test: /.(png|jpg|gif)$/, //匹配所有格式的圖片資源

use: [

{

? ? ? ? ? ? loader: 'file-loader'

}

]

}

??別名(@)在webpack中的配置

在src/index.js里我們引入:

const format = require('utils/format') // utils ?? 沒有相對路徑? 回想@? => 別名

在src新建相應(yīng)的文件映皆。在format.js里接受一個參數(shù)并把它轉(zhuǎn)成大寫

module.exports = function format(chars) {

return chars.toUpperCase()

}

在webpack中如何配置我們的別名呢挤聘?在vue-cli中我們經(jīng)常@一個文件夾,其意思就是在src目錄下捅彻,現(xiàn)在我們?nèi)ヒ惶骄烤棺槿ァT趍odule下,注意跟rules同級步淹。

resolve: { //解析模塊的可選項?

// modules: [ ]//模塊的查找目錄 配置其他的css等文件

? ? ? ? extensions: [".js", ".json", ".jsx",".less", ".css"], //用到文件的擴展名

alias: { //拇勇。快別名列表

? ? ? ? ? ? utils: path.resolve(__dirname,'src/utils')

}

},

??其他一些靜態(tài)資源在webpack中的配置

src下其他的文件直接復(fù)制到dist目錄下,并不是每個文件都需要打包處理的缭裆,很多資源可能直接就可以復(fù)制過去。使用我們的 CopyWebpackPlugin插件

引用框架 jquery lodash工具庫是很多組件會復(fù)用的澈驼,省去了import辛燥。使用webpack.ProvidePlugin插件

五、npm run dev 發(fā)生了什么

在vue-cli中我們啟動監(jiān)聽npm run dev可以時時監(jiān)控我們src下文件的改動盅藻,那他到底發(fā)生了什么呢购桑。在webpack里其實創(chuàng)建了一個node進程,通過webpack-dev-server其內(nèi)部封裝了一個node的express模塊氏淑,其配置項如下:

"scripts": { //在package.json里聲明下使用腳本 npm run dev

"build": "webpack --mode production",

"start": "webpack-dev-server --mode development"

},

devServer: { //在webpack.config.js里配置port

? ? ? ? port: '8080',

? ? ? ? before(app) {

? ? ? ? ? ? app.get('/api/test.json', (req, res) => {

? ? ? ? ? ? ? ? res.json({

? ? ? ? ? ? ? ? ? ? code: 200,

? ? ? ? ? ? ? ? ? ? message: 'Hello World'

})

})

}

} //服務(wù)于webpack-dev-server? 內(nèi)部封裝了一個express

寄語

webpack里面博大精深勃蜘,這只是剛?cè)腴T。要研究其里面真正的東西假残,并非一朝一夕缭贡。tapable、webpack的生命周期等等辉懒。如果你想深入的理解webpack阳惹,推薦騰訊ivweb團隊關(guān)于webpack的深入研究。這也是我最近在看的眶俩,只有理解更多莹汤,你才能飛的更遠。夜深了颠印,時間過的很快纲岭。樓主也太困了,停筆于此线罕,望多多包涵止潮。

編輯:千鋒HTML5

作者:WsmDyj

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市钞楼,隨后出現(xiàn)的幾起案子喇闸,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燃乍,死亡現(xiàn)場離奇詭異唆樊,居然都是意外死亡,警方通過查閱死者的電腦和手機橘沥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門窗轩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人座咆,你說我怎么就攤上這事痢艺。” “怎么了介陶?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵堤舒,是天一觀的道長。 經(jīng)常有香客問我哺呜,道長舌缤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任某残,我火速辦了婚禮国撵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玻墅。我一直安慰自己介牙,他們只是感情好,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布澳厢。 她就那樣靜靜地躺著环础,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剩拢。 梳的紋絲不亂的頭發(fā)上线得,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機與錄音徐伐,去河邊找鬼贯钩。 笑死,一個胖子當著我的面吹牛办素,可吹牛的內(nèi)容都是我干的魏保。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼摸屠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粱哼?” 一聲冷哼從身側(cè)響起季二,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胯舷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刻蚯,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年桑嘶,在試婚紗的時候發(fā)現(xiàn)自己被綠了炊汹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡逃顶,死狀恐怖讨便,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情以政,我是刑警寧澤霸褒,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站盈蛮,受9級特大地震影響废菱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抖誉,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一殊轴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袒炉,春花似錦旁理、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至十性,卻和暖如春叛溢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劲适。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工楷掉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人霞势。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓烹植,卻偏偏與公主長得像,于是被迫代替她去往敵國和親愕贡。 傳聞我的和親對象是個殘疾皇子草雕,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容