打包一個模組
// webpack.config.js
module.exports = {
entry: {
index: "./main.js",
},
output: {
path: __dirname + '/dist',
filename: '[name].js'
},
};複製程式碼
// main.js, entry chunk
import { chunk2, chunk3 } from './main1';
import chunk5, { C1, C2, C3 } from './main2';
var chunk1 = 1;
exports.chunk1 = chunk1;
exports.chunk4 = {
a: 1,
b: 2
};
console.log(C1);
console.log(chunk3);複製程式碼
// main1.js
var chunk2 = 2;
exports.chunk2 = chunk2;
var chunk3 = 3;
exports.chunk3 = chunk3;
export function f1() {
return 'f1';
}
export function f2() {
return 'f2';
}複製程式碼
// main2.js
export function f3() {
return 'f3';
}
export default class C3 {
constructor() {
}
f1() {
console.log("f1")
}
f2() {
console.log("f2");
}
}
export const C1 = 'c1';
export const C2 = 'c2';複製程式碼
// result file, index.js
(function(modules) {
// modules在webpack1的時候是陣列,現在變成了key值是數字的物件
// module的快取
var installedModules = {};
// require方法,轉義成此
function __webpack_require__(moduleId) {
// 若module已被快取,直接返回
if(installedModules[moduleId])
return installedModules[moduleId].exports;
// 建立一個新的module,被放入快取中
// webpack1的時候都是全稱,現在估計為了省點空間,都變成了id => i, load => l
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
// 執行module
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// 標明此module已被載入
module.l = true;
// module.exports通過在執行module的時候,作為引數存進去,然後會儲存module中暴露給外界的介面,
// 如函式、變數等
return module.exports;
}
// 在原始檔中,直接使用__webpack_modules__,生成檔案用__webpack_require__.m替換
__webpack_require__.m = modules;
// 暴露module快取
__webpack_require__.c = installedModules;
// identity function for calling harmory imports with the correct context
__webpack_require__.i = function(value) { return value; };
// 為harmory exports 定義 getter function, configurable=false表明,此屬性不能修改
// 例如export const,由於是常量,需要用__webpack_require__.d進行定義
__webpack_require__.d = function(exports, name, getter) {
Object.defineProperty(exports, name, {
configurable: false,
enumerable: true,
get: getter
});
};
// 相容 non-harmony 模組,這些模組如果設了__esModule屬性,則被標記為non-harmony
__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 polyfill
__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
// 使用__webpack_public_path__,則會替換__webpack_require__.p
__webpack_require__.p = "//localhost:8000/";
// 載入入口模組,並返回exports
return __webpack_require__(__webpack_require__.s = 143);
})
/************************************************************************/
({
143: // 入口模組
function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(64);
},
64: // main.js
function(module, exports, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__main1__ = __webpack_require__(72);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__main2__ = __webpack_require__(73);
var chunk1 = 1;
exports.chunk1 = chunk1;
exports.chunk4 = {
a: 1,
b: 2
};
// 此如由於引用了C1,而C1又是常用,它事先定義成屬性a,此處直接引用物件的屬性a
console.log(__WEBPACK_IMPORTED_MODULE_1__main2__["a" /* C1 */]);
console.log(__WEBPACK_IMPORTED_MODULE_0__main1__["chunk3"]);
},
72: // main1.js
function(module, exports, __webpack_require__) {
"use strict";
/* unused harmony export f1 */
/* unused harmony export f2 */
// 此處註釋表示,這兩個harmony export模組沒有被使用,後續如果使用unglify外掛,f1與f2會被去掉
// 這個就是著名的tree-shaking
var chunk2 = 2;
exports.chunk2 = chunk2;
var chunk3 = 3;
exports.chunk3 = chunk3;
function f1() {
return 'f1';
}
function f2() {
return 'f2';
}
},
73: // main2.js
function(module, exports, __webpack_require__) {
"use strict";
/* unused harmony export f3 */
/* unused harmony export default */
/* harmony export (binding) */ __webpack_require__.d(exports, "a", function() { return C1; });
/* unused harmony export C2 */
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function f3() {
return 'f3';
}
var C3 = function () {
function C3() {
_classCallCheck(this, C3);
}
C3.prototype.f1 = function f1() {
console.log("f1");
};
C3.prototype.f2 = function f2() {
console.log("f2");
};
return C3;
}();
var C1 = 'c1';
var C2 = 'c2';
}
});複製程式碼
整個立即執行函式,主要是webpack_require, webpack_require.n, webpack_require.d起作用。installedModules是用於快取已經載入的模組。
非同步載入
// webpack.config.js
module.exports = {
entry: {
index: "./main.js",
},
output: {
path: __dirname + '/dist',
filename: '[name].js',
chunkFilename: "js/[name].js",
},
};複製程式碼
// main.js
var chunk1 = 1;
exports.chunk1 = chunk1;
function errorLoading(err) {
console.error('Dynamic page loading failed', err);
}
function loadRoute(cb) {
console.log("dynamic loading success");
return (module) => cb(null, module.default);
}
// 符合es6規範的非同步載入模組方法
System.import('./main1')
.then(loadRoute(cb))
.catch(errorLoading);複製程式碼
// main1.js
var chunk2 = 2;
exports.chunk2 = chunk2;
var chunk3 = 3;
exports.chunk3 = chunk3;
export function f1() {
return 'f1';
}
export function f2() {
return 'f2';
}
export default function f3() {
return 'f3';
}複製程式碼
// result file, index.js複製程式碼
// result file, 0.js
webpackJsonp([0],{
144:
function(module, exports, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ exports["f1"] = f1;
/* harmony export (immutable) */ exports["f2"] = f2;
/* harmony export (immutable) */ exports["default"] = f3;
var chunk2 = 2;
exports.chunk2 = chunk2;
var chunk3 = 3;
exports.chunk3 = chunk3;
function f1() {
return 'f1';
}
function f2() {
return 'f2';
}
function f3() {
return 'f3';
}
}
});複製程式碼
// result file index.js
(function(modules) { // webpackBootstrap
// install a JSONP callback for chunk loading
var parentJsonpFunction = window["webpackJsonp"];
// 全域性定義webpackJsonp,讓chunk載入的時候,直接可呼叫
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
// 將異載入的moreModules,新增到entry chunk的modules裡面
// 然後使所有chunk標記為已載入,並觸發回撥函式
var moduleId, chunkId, i = 0, resolves = [], result;
for(;i < chunkIds.length; i++) {
chunkId = chunkIds[i];
if(installedChunks[chunkId]) {
resolves.push(installedChunks[chunkId][0]);
}
installedChunks[chunkId] = 0;
}
// 將moreModules存入modules中
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId];
}
}
if(parentJsonpFunction) {
parentJsonpFunction(chunkIds, moreModules, executeModules);
}
// resolves就是需要觸發的回撥
while(resolves.length) {
resolves.shift()();
}
};
// The module cache
var installedModules = {};
// objects to store loaded and loading chunks
var installedChunks = {
3: 0
};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
if(installedModules[moduleId])
return installedModules[moduleId].exports;
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
// Execute the module function
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;
}
// 非同步載入函式,返回promise物件
__webpack_require__.e = function requireEnsure(chunkId) {
// 如果已經載入,則返回Promise.resolve
if(installedChunks[chunkId] === 0)
return Promise.resolve();
// an Promise means "currently loading".
if(installedChunks[chunkId]) {
return installedChunks[chunkId][2];
}
// 開始載入
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.async = true;
script.timeout = 120000;
// 載入的資源位置
script.src = __webpack_require__.p + "js/chunk/" + ({}[chunkId]||chunkId) + ".js";
var timeout = setTimeout(onScriptComplete, 120000);
script.onerror = script.onload = onScriptComplete;
function onScriptComplete() {
// avoid mem leaks in IE.
script.onerror = script.onload = null;
clearTimeout(timeout);
var chunk = installedChunks[chunkId];
if(chunk !== 0) {
if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
installedChunks[chunkId] = undefined;
}
};
head.appendChild(script);
var promise = new Promise(function(resolve, reject) {
// resolve與reject,屬於installedChunks[chunkId]的回撥函式,
// 在webpackJsonpCallback函式中,有可能被呼叫
installedChunks[chunkId] = [resolve, reject];
console.log(installedChunks[chunkId]);
});
return installedChunks[chunkId][2] = promise;
};
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// identity function for calling harmory imports with the correct context
__webpack_require__.i = function(value) { return value; };
// define getter function for harmory exports
__webpack_require__.d = function(exports, name, getter) {
Object.defineProperty(exports, name, {
configurable: false,
enumerable: true,
get: getter
});
};
// 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 = "//localhost:8000/";
// on error function for async loading
__webpack_require__.oe = function(err) { console.error(err); throw err; };
// Load entry module and return exports
return __webpack_require__(__webpack_require__.s = 141);
})
/************************************************************************/
({
141:
function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(64);
},
64:
function(module, exports, __webpack_require__) {
var chunk1 = 1;
exports.chunk1 = chunk1;
function errorLoading(err) {
console.error('Dynamic page loading failed', err);
}
function loadRoute() {
console.log("dynamic loading success");
return function (module) {
console.log(module.default);
};
}
// 符合es6規範的非同步載入模組
__webpack_require__.e/* System.import */(0).then(__webpack_require__.bind(null, 144)).then(loadRoute()).catch(errorLoading);
}
});複製程式碼
非同步載入,主要是多了webpackJsonp全域性函式,以及webpack_require.e作為載入script的函式。
CommonsChunkPlugin 提取公共包
// webpack.config.js
module.exports = {
entry: {
index: "./main.js",
spa: "./spamain.js"
},
output: {
path: __dirname + '/dist',
filename: '[name].js',
chunkFilename: "js/[name].js",
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
filename: "commons.js",
chunks: ['index', 'spa'],
}),
]
};複製程式碼
// result file, index.js
(function(modules) { // webpackBootstrap
// install a JSONP callback for chunk loading
var parentJsonpFunction = window["webpackJsonp"];
window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
// add "moreModules" to the modules object,
// then flag all "chunkIds" as loaded and fire callback
var moduleId, chunkId, i = 0, resolves = [], result;
for(;i < chunkIds.length; i++) {
chunkId = chunkIds[i];
if(installedChunks[chunkId])
resolves.push(installedChunks[chunkId][0]);
installedChunks[chunkId] = 0;
}
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId];
}
}
if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
while(resolves.length)
resolves.shift()();
// 這裡比非同步載入相同的函式多了一段執行邏輯,主要用於執行entry chunk
if(executeModules) {
for(i=0; i < executeModules.length; i++) {
result = __webpack_require__(__webpack_require__.s = executeModules[i]);
}
}
return result;
};
// The module cache
var installedModules = {};
// objects to store loaded and loading chunks
var installedChunks = {
3: 0
};
// The require function
function __webpack_require__(moduleId) {
// Check if module is in cache
if(installedModules[moduleId])
return installedModules[moduleId].exports;
// Create a new module (and put it into the cache)
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
// Execute the module function
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;
}
// This file contains only the entry chunk.
// The chunk loading function for additional chunks
__webpack_require__.e = function requireEnsure(chunkId) {
if(installedChunks[chunkId] === 0)
return Promise.resolve();
// an Promise means "currently loading".
if(installedChunks[chunkId]) {
return installedChunks[chunkId][2];
}
// start chunk loading
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.async = true;
script.timeout = 120000;
script.src = __webpack_require__.p + "js/chunk/" + ({"0":"index","1":"spa"}[chunkId]||chunkId) + ".js";
var timeout = setTimeout(onScriptComplete, 120000);
script.onerror = script.onload = onScriptComplete;
function onScriptComplete() {
// avoid mem leaks in IE.
script.onerror = script.onload = null;
clearTimeout(timeout);
var chunk = installedChunks[chunkId];
if(chunk !== 0) {
if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
installedChunks[chunkId] = undefined;
}
};
head.appendChild(script);
var promise = new Promise(function(resolve, reject) {
installedChunks[chunkId] = [resolve, reject];
});
return installedChunks[chunkId][2] = promise;
};
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// identity function for calling harmory imports with the correct context
__webpack_require__.i = function(value) { return value; };
// define getter function for harmory exports
__webpack_require__.d = function(exports, name, getter) {
Object.defineProperty(exports, name, {
configurable: false,
enumerable: true,
get: getter
});
};
// 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 = "//localhost:8000/";
// on error function for async loading
__webpack_require__.oe = function(err) { console.error(err); throw err; };
})
/************************************************************************/
({
8:
function(module, exports, __webpack_require__) {
"use strict";
/* unused harmony export f1 */
/* unused harmony export f2 */
/* unused harmony export default */
var chunk2 = 2;
exports.chunk2 = chunk2;
var chunk3 = 3;
exports.chunk3 = chunk3;
function f1() {
return 'f1';
}
function f2() {
return 'f2';
}
function f3() {
return 'f3';
}
}
});複製程式碼
// main.js
webpackJsonp([0],{
14:
function(module, exports, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__main1__ = __webpack_require__(8);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__main2__ = __webpack_require__(24);
var chunk1 = 1;
exports.chunk1 = chunk1;
exports.chunk4 = {
a: 1,
b: 2
};
},
24:
function(module, exports, __webpack_require__) {
"use strict";
/* unused harmony export f3 */
/* unused harmony export default */
/* unused harmony export C1 */
/* unused harmony export C2 */
/* unused harmony export C4 */
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function f3() {
return 'f3';
}
var C3 = function () {
function C3() {
_classCallCheck(this, C3);
}
C3.prototype.f1 = function f1() {
console.log("f1");
};
C3.prototype.f2 = function f2() {
console.log("f2");
};
return C3;
}();
var C1 = 'c1';
var C2 = 'c2';
var C4 = 'c4';
},
41:
function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(14);
}
},[41]);複製程式碼
// spamain.js
webpackJsonp([1],{
16:
function(module, exports, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__index_main1__ = __webpack_require__(8);
console.log(__WEBPACK_IMPORTED_MODULE_0__index_main1__["chunk2"]);
},
43:
function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(16);
}
},[43]);複製程式碼
提取公共包的這種情況,跟非同步載入很類似,不過它將主要的功能函式都提取到common.js中,並且新增了執行module的邏輯。但主要入口的chunk都在主要邏輯的index.js與spa.js中。
webpack2使用了一些低端瀏覽器並不支援的介面,因此如果需要支援這些低端瀏覽器的業務,需要謹慎使用。