webpack筆記三:版本的差異性

前言

webpack和gulp最大的區(qū)別在于它是一個(gè)打包工具挽霉,它串聯(lián)起了整個(gè)前端工程化
的每一項(xiàng)內(nèi)容樱调。我非常慶幸的是經(jīng)歷過webpack1到2的升級胸完,也經(jīng)歷了2到3的升級公条,打包的相關(guān)內(nèi)容也越來越多。如今webpack從3變成4硅急,很多人抱怨webpack的配置太過于復(fù)雜覆享,在webpack4以后它的配置會變得越來越簡單,對于開發(fā)者來說营袜,entry撒顿,output,loader连茧,plugin四大板塊是必須要清楚的核蘸。

  • entry 輸入
  • output 輸出
  • loader 打包規(guī)則
  • plugin 插件生態(tài)

當(dāng)你了解了上面的這些內(nèi)容,還不夠啸驯。你需要了解各個(gè)版本間的差異性客扎,這樣你才能充分利用它所有的功能。Webpack1到2最大的升級是tree-shaking罚斗,其次是配置文件的對象化徙鱼,再其次包括插件的寫法優(yōu)化。Webpack2到3的最大升級是scope-hoisting针姿。3到4簡化了整個(gè)打包配置操作袱吆。

code-spliting

code-spliting(代碼分割)應(yīng)該是所有前端人都知道的優(yōu)化點(diǎn)。當(dāng)你單頁面做越做越大的時(shí)候距淫,非首屏的頁面就會考慮到不優(yōu)先加載绞绒。但是怎么去劃分懶加載的包,最高效的方法就是路由懶加載榕暇。

舉個(gè)栗子蓬衡,在你使用vue路由的時(shí)候,你可能會考慮到除了第一頁的內(nèi)容彤枢,不會預(yù)先加載狰晚,會延時(shí)加載后面幾頁的功能。這七個(gè)頁面會從 app.js 中拆分成為7個(gè)js包缴啡。這樣的代碼分割壁晒,在大型的單頁面應(yīng)用中,我們必須使用到因?yàn)楹竺娴捻撁嫖覀儾恍枰崆凹虞d业栅。

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    component: resolve => require(['../views/Map'], resolve),
  },
  {
    path: '/setting',
    component: resolve => require(['../views/Setting'], resolve),
  },
  {
    path: '/cities',
    component: resolve => require(['../views/Cities'], resolve),
  },
  {
    path: '/discovery',
    component: resolve => require(['../views/Discovery'], resolve),
  },
  {
    path: '/about',
    component: resolve => require(['../views/About'], resolve),
  },
  {
    path: '/more',
    component: resolve => require(['../views/More'], resolve),
  },
  {
    path: '/weather',
    component: resolve => require(['../views/Weather'], resolve),
  },
];
const router = new VueRouter({ mode: 'history', base: '/app/', routes });

隨著webpack2語法的進(jìn)化秒咐,上面的代碼也可以被寫成這樣子。

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    component:() => import('../views/Map'),
  },
  {
    path: '/setting',
    component: () => import('../views/Setting'),
  },
  {
    path: '/cities',
    component: () => import('../views/Cities'),
  },
  {
    path: '/discovery',
    component: () => import('../views/Discovery'),
  },
  {
    path: '/about',
    component: () => import('../views/About'),
  },
  {
    path: '/more',
    component: () =>import('../views/More'),
  },
  {
    path: '/weather',
    component: () => import('../views/Weather'),
  },
];
const router = new VueRouter({ mode: 'history', base: '/app/', routes });

每個(gè)懶加載的背后都附送一個(gè)鉤子碘裕。使用了code-splitting反镇,webpack會根據(jù)你可以將一些首屏不顯示的內(nèi)容額外打包成為一個(gè)獨(dú)立的js。webpack2中懶加載打包會連同樣式以內(nèi)聯(lián)的形式一起打入JS中娘汞,這樣的好處在于公共樣式也被細(xì)化抽離歹茶,但是可能會造成樣式冗余。webpack3則提供了ExtractTextPlugin中提供了抽取公共樣式的方法你弦,公共樣式可以額外抽離惊豺。

tree-shaking

tree-shaking是rollup提出的一款技術(shù),反哺到了webpack2的升級版本中禽作。這可以說一個(gè)非常難以理解的概念尸昧,就像lodash這樣的公共方法,在項(xiàng)目編寫會積累的越來越多旷偿,但是我們不希望將這些方法全部打包入一個(gè)js文件當(dāng)中烹俗。常見的方法有:

  1. 項(xiàng)目解耦爆侣,將一個(gè)大型項(xiàng)目拆分成幾個(gè)小型項(xiàng)目
  2. 使用tree-shaking,它只打包有用的方法幢妄,沒有用的方法則不會進(jìn)行打包

tree-shaking默認(rèn)是不會觸發(fā)的兔仰。在webpack3,你需要配置babel蕉鸳,uglifyjs-webpack-plugin等才能觸發(fā)乎赴。在webpack4,production模式默認(rèn)觸發(fā)潮尝。首先榕吼,如果在編寫代碼過程中必須使用得當(dāng),純函數(shù)對于tree項(xiàng)目打包有相當(dāng)大的優(yōu)勢勉失,也就是你的變量盡量要保持函數(shù)間的干凈羹蚣,不要相互污染。

情景一:最簡單的例子

index.js引入另一個(gè)js中的兩個(gè)方法乱凿,webpack4的打包結(jié)果是只會存在console.log(1)度宦。而console.log(2)已不會進(jìn)入打包的范圍當(dāng)中。

//core.js
export function test1() {
    console.log(1)
}

export function test2() {
    console.log(2)
}
//index.js
import {test1} from './core'
test1()

情景二:存在一個(gè)常量或者變量

當(dāng)core.js有個(gè)全局變量a=2告匠,這個(gè)變量可能會在別的函數(shù)中改變戈抄,webpack會檢查該函數(shù)是否在打包范圍內(nèi)。不會在該范圍內(nèi)的后专,如test1划鸽,則不會被打包。

//core.js
let a = 2;

export function test1() {
    a = 1;
    console.log(a);
}

export function test2() {
    console.log(a);
}
//index.js
import {test2} from './core'
test2()

情景三:存在一個(gè)對象

如果你輸出的是一個(gè)對象戚哎,你只需要其中的一個(gè)方法裸诽,此時(shí)你同樣結(jié)構(gòu)只需要一個(gè)方法test2,別的方法是不會被打包進(jìn)去型凳。

//core.js
let a = 2;

function test1() {
    a = 1;
    console.log(a);
}

function test2() {
    console.log(a);
}

function test3() {
    console.log(3)
}

function test4() {
    console.log(4)
}

export {
  test1,
  test2,
  test3,
  test4
}

情景四:存在prototype或者class

其實(shí)結(jié)果很明顯丈冬,由于別的方法會在實(shí)例化的時(shí)候聲明,由于被實(shí)例化的新的對象相互間是有聯(lián)系的甘畅,這也注定了它會被打包進(jìn)去埂蕊。

scope-hoisting

它的中文名就是作用域提升,這個(gè)名字非常熟悉疏唾。說到底蓄氧,javascript的模塊化就是通過閉包來實(shí)現(xiàn)作用域的隔離,但是當(dāng)我們模塊化程度達(dá)到一定程度之后槐脏,過多閉包會讓某些變量沒法銷毀喉童,造成性能劣勢。作用域提升即是把兩個(gè)閉包合成一個(gè)閉包顿天。

通過Scope Hoisting優(yōu)化Webpack輸出里面講了最最基礎(chǔ)的一個(gè)作用域提升的例子堂氯,我在這里借用這個(gè)例子蔑担。首先寫兩個(gè)js,它們相互之間是引用關(guān)系咽白。這里采用webpack4版本舉例啤握,在development mode時(shí)沒有采用scope hoisting,而production mode時(shí)默認(rèn)開啟了該優(yōu)化局扶。

// core.js
export const a = 'Hello,Webpack';
// index.js 
import { a } from './base.js';
console.log(a);
development mode
production mode

如果你在項(xiàng)目中使用webpack3恨统,你需要開啟webpack.optimize.ModuleConcatenationPlugin來滿足作用域提升的功能叁扫。如果你在項(xiàng)目中使用webpack4三妈,那么你在開發(fā)模式即是關(guān)閉作用域提升,在生產(chǎn)模式開啟該功能莫绣。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末畴蒲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子对室,更是在濱河造成了極大的恐慌模燥,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掩宜,死亡現(xiàn)場離奇詭異蔫骂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)牺汤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門辽旋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人檐迟,你說我怎么就攤上這事补胚。” “怎么了追迟?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵溶其,是天一觀的道長。 經(jīng)常有香客問我敦间,道長瓶逃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任廓块,我火速辦了婚禮金闽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剿骨。我一直安慰自己代芜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布浓利。 她就那樣靜靜地躺著挤庇,像睡著了一般钞速。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嫡秕,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天渴语,我揣著相機(jī)與錄音,去河邊找鬼昆咽。 笑死驾凶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的掷酗。 我是一名探鬼主播调违,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泻轰!你這毒婦竟也來了技肩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤浮声,失蹤者是張志新(化名)和其女友劉穎虚婿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泳挥,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡然痊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屉符。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剧浸。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖筑煮,靈堂內(nèi)的尸體忽然破棺而出辛蚊,到底是詐尸還是另有隱情,我是刑警寧澤真仲,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布袋马,位于F島的核電站,受9級特大地震影響秸应,放射性物質(zhì)發(fā)生泄漏虑凛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一软啼、第九天 我趴在偏房一處隱蔽的房頂上張望桑谍。 院中可真熱鬧,春花似錦祸挪、人聲如沸锣披。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雹仿。三九已至增热,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胧辽,已是汗流浹背峻仇。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留邑商,地道東北人摄咆。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像人断,于是被迫代替她去往敵國和親吭从。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

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