webpack搗鼓筆記

webpack是前端工程師必備神器梧喷,幫助我們解決了很多打包、構(gòu)建娇钱、部署伤柄、磨平各種js模塊差異等細(xì)瑣的工作。堅(jiān)信真相使人自由文搂,今天我們來(lái)看看就究竟做了什么

打包后的代碼

首先我們看下webpack打包后的代碼,這是設(shè)置library為umd的情況秤朗。他是一個(gè)立即執(zhí)行函數(shù)煤蹭,接受rootfactory兩個(gè)參數(shù),主要看下factory參數(shù),它的返回也是一個(gè)立即執(zhí)行函數(shù)

(function webpackUniversalModuleDefinition(root, factory) {
    // 這里只是各種判定硝皂,以適配各種亂七八雜的模塊格式(amd,cmd,es6)常挚,保證你在什么情況下引用都OJBK
    if(typeof exports === 'object' && typeof module === 'object')
        module.exports = factory();
    else if(typeof define === 'function' && define.amd)
        define([], factory);
    else {
        var a = factory();
        for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
    }
})(window, function() {  ... //這個(gè)函數(shù)里就是打包的代碼, 也即是factory函數(shù)體})

我們?cè)倏聪耭actory函數(shù),它會(huì)返回一個(gè)立即執(zhí)行函數(shù)稽物,其結(jié)果就是你入口文件導(dǎo)出的結(jié)構(gòu)奄毡。我們可以看到,我們的各個(gè)模塊會(huì)被組合成一個(gè)數(shù)組傳入這個(gè)webpack handle function贝或。

// factory函數(shù)
function() {
  return (function(modules) { /*webpack handle function body*/ })([ 
     { 'modules1': (fucntion (){  /*module1 body*/  })}, 
     { 'modules1': (fucntion (){  /*module1 body*/  })},
      ....
  ]);
}

我們?cè)倏聪?code>webpack handle function body, 首先看下入?yún)⒑蛂eturn吼过,入?yún)⒕褪俏覀兯玫母鱾€(gè)模塊modules,返回就是我們?nèi)肟谖募?code>./src/index.js exports 的結(jié)果咪奖。其他具體的可以看下里面的注釋

return (function(modules) { // webpackBootstrap
/******/    // The module cache 主要是緩存盗忱,保證了每個(gè)模塊只會(huì)excute一遍,提高速度
/******/    var installedModules = {};
/******/
/******/    // 這就是我們?cè)陧?xiàng)目源碼中使用的require函數(shù)羊赵,webpack會(huì)把require函數(shù)替換成__webpack_require__趟佃,
/******/    // 如果做過(guò)electron等其他項(xiàng)目的同學(xué)應(yīng)該會(huì)知道這個(gè)是個(gè)小坑,需要特殊處理下
/******/    function __webpack_require__(moduleId) {
/******/
/******/        // Check if module is in cache 這沒(méi)啥好說(shuō)的昧捷,緩存中直接返回
/******/        if(installedModules[moduleId]) {
/******/            return installedModules[moduleId].exports;
/******/        }
/******/        // 沒(méi)有命中緩存就新建一個(gè)module對(duì)象闲昭,用于存儲(chǔ)moduleId一個(gè)模塊
/******/        var module = installedModules[moduleId] = {
/******/            i: moduleId,
/******/            l: false,
/******/            exports: {}
/******/        };
/******/
/******/        // 我們所說(shuō)的每一個(gè)文件會(huì)封裝成一個(gè)函數(shù),這個(gè)函數(shù)就在這里調(diào)用靡挥,執(zhí)行的上下文是個(gè)空對(duì)象module.exports
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/        // Flag the module as loaded
/******/        module.l = true;
/******/
/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }
/******/
/******/    // 這下面設(shè)置了一些標(biāo)志和工具函數(shù)
/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;
/******/
/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;
/******/
/******/    // define getter function for harmony exports 導(dǎo)出的各個(gè)name設(shè)置到exports對(duì)象上
/******/    __webpack_require__.d = function(exports, name, getter) {
/******/        if(!__webpack_require__.o(exports, name)) {
/******/            Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/        }
/******/    };
/******/
/******/    // define __esModule on exports 給exports設(shè)置__esModule標(biāo)志
/******/    // 主要是es6模塊最后也需要轉(zhuǎn)換成commonjs的形式序矩,設(shè)置了這個(gè)標(biāo)志就表明這個(gè)模塊是從es6 module形式轉(zhuǎn)過(guò)來(lái)的
/******/    __webpack_require__.r = function(exports) {
/******/        if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/            Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/        }
/******/        Object.defineProperty(exports, '__esModule', { value: true });
/******/    };
/******/
/******/    // create a fake namespace object
/******/    // mode & 1: value is a module id, require it
/******/    // mode & 2: merge all properties of value into the ns
/******/    // mode & 4: return value when already ns object
/******/    // mode & 8|1: behave like require
/******/    __webpack_require__.t = function(value, mode) {
/******/        if(mode & 1) value = __webpack_require__(value);
/******/        if(mode & 8) return value;
/******/        if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/        var ns = Object.create(null);
/******/        __webpack_require__.r(ns);
/******/        Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/        if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/        return ns;
/******/    };
/******/
/******/    // getDefaultExport function for compatibility with non-harmony modules
/******/    __webpack_require__.n = function(module) {
/******/        var getter = module && module.__esModule ?
/******/            function getDefault() { return module['default']; } :
/******/            function getModuleExports() { return module; };
/******/        __webpack_require__.d(getter, 'a', getter);
/******/        return getter;
/******/    };
/******/
/******/    // Object.prototype.hasOwnProperty.call
/******/    __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";
/******/
/******/
/******/    // Load entry module and return exports
/******/    return __webpack_require__(__webpack_require__.s = "./src/index.js");
/******/ })

tree-shaking

我們接下來(lái)示例展示下webpack的tree-shaking功能。

webpack默認(rèn)是自帶tree-shaking功能的芹血,如果項(xiàng)目中使用了babel贮泞,就需要注意babel默認(rèn)會(huì)接管webpack的模塊轉(zhuǎn)化功能(即我們所說(shuō)的es6 module最終需要轉(zhuǎn)化成commonjs形式),這時(shí)候我們需要關(guān)閉babel的這個(gè)功能,只需要在.babelrc中設(shè)置"modules": false幔烛,或者是babel-loader的options中設(shè)置啃擦。

{
    "presets": [
      ["env", {"modules": false}]
    ],
    "plugins": [
        ["transform-react-jsx", {
            "pragma": "React.createElement"
        }]
    ]
}

我們現(xiàn)在寫(xiě)個(gè)index.js作為webpack的entry,引用了util.js中的a和c

// index.js
import { a, c } from './util';

a();
c();

這是util.js饿悬,里面還 export 了個(gè)b

// util.js
export const a = () => {
  console.log('a');
}
export const b = () => {
  console.log('b');
}
export const c = () => {
  console.log('c')
}

我們看下打包出來(lái)的結(jié)果令蛉,沒(méi)有tree-shakinga b c都在

/***/ "./src/util.js":
/*!*********************!*\
  !*** ./src/util.js ***!
  \*********************/
/*! exports provided: a, b, c */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return a; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return b; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return c; });
var a = function a() {
  console.log('a');
};
var b = function b() {
  console.log('b');
};
var c = function c() {
  console.log('c');
};

/***/ })

原來(lái)webpacktree-shaking只會(huì)在mode: 'poduction'下做狡恬,我們?cè)趐roduction下再build下看下結(jié)果

[function (e, t, n) {
    "use strict";
    n.r(t);
    console.log("a"), console.log("c")
  }]

我的老哥珠叔,tree-shaking的非常直接,直接把代碼放到了index模塊里弟劲,連requireexport都省了祷安,貌似有點(diǎn)過(guò)分了啊

通過(guò)一些簡(jiǎn)單的demo我們可以更加清楚的知道webpack是怎么組織我們的js代碼的,怎么磨平模塊差異的兔乞,可以加深對(duì)webpack打包的理解

有興趣的還可以看下這篇文章汇鞭,給了我很多啟發(fā)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凉唐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子霍骄,更是在濱河造成了極大的恐慌台囱,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件读整,死亡現(xiàn)場(chǎng)離奇詭異簿训,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)米间,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)强品,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人车伞,你說(shuō)我怎么就攤上這事择懂。” “怎么了另玖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵困曙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我谦去,道長(zhǎng)慷丽,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任鳄哭,我火速辦了婚禮要糊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘妆丘。我一直安慰自己锄俄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布勺拣。 她就那樣靜靜地躺著奶赠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪药有。 梳的紋絲不亂的頭發(fā)上毅戈,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音愤惰,去河邊找鬼苇经。 笑死,一個(gè)胖子當(dāng)著我的面吹牛宦言,可吹牛的內(nèi)容都是我干的扇单。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奠旺,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼令花!你這毒婦竟也來(lái)了阻桅?” 一聲冷哼從身側(cè)響起凉倚,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤兼都,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后稽寒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體扮碧,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年杏糙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了慎王。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宏侍,死狀恐怖赖淤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谅河,我是刑警寧澤咱旱,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站绷耍,受9級(jí)特大地震影響吐限,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜褂始,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一诸典、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧崎苗,春花似錦狐粱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至幅慌,卻和暖如春宋欺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胰伍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工齿诞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骂租。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓祷杈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親渗饮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子但汞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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

  • 1 Webpack 1.1 概念簡(jiǎn)介 1.1.1 WebPack是什么 1宿刮、一個(gè)打包工具 2、一個(gè)模塊加載工具 3...
    Kevin_Junbaozi閱讀 6,638評(píng)論 0 16
  • 作者:小 boy (滬江前端開(kāi)發(fā)工程師)本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明作者及出處踩叭。原文地址:https://www.smas...
    iKcamp閱讀 2,742評(píng)論 0 18
  • GitChat技術(shù)雜談 前言 本文較長(zhǎng)磕潮,為了節(jié)省你的閱讀時(shí)間,在文前列寫(xiě)作思路如下: 什么是 webpack容贝,它要...
    蕭玄辭閱讀 12,674評(píng)論 7 110
  • 寫(xiě)在前面的話 閱讀本文之前自脯,先看下面這個(gè)webpack的配置文件,如果每一項(xiàng)你都懂斤富,那本文能帶給你的收獲也許就比較...
    不忘初心_9a16閱讀 3,232評(píng)論 0 17
  • 模塊打包器:開(kāi)發(fā)一個(gè)項(xiàng)目膏潮,業(yè)務(wù)邏輯會(huì)很多,開(kāi)發(fā)會(huì)按照功能邏輯拆分成一個(gè)個(gè)的模塊满力,這樣開(kāi)發(fā)的時(shí)候更加有條理焕参,維護(hù)起來(lái)...
    谷子多閱讀 4,362評(píng)論 0 44