一、webpack的基本能力:處理依賴、模塊化、打包
1、依賴管理:方便引用第三方模塊,讓模塊更容易複用、避免全局注入導致的衝突、、避免重複加載或者加載不必要的模塊
2、合併代碼:把各個分散的模塊集中打包成大文件,減少HTTP的鏈接的請求次數,配合uglify.js可以減少、優化代碼的體積
3、各種插件:babel把ES6+轉化爲ES5-,eslint可以檢查編譯時的各種錯誤
二、webpack的工作原理
簡單的說就是分析代碼,找到“require”、“exports”、“define”等關鍵詞,並替換成對應模塊的引用。
在一個配置文件中,指明對某些文件進行編譯、壓縮、組合等任務。把你的項目當成一個整體,通過一個給定的主文件 (index.js),webpack將從這個文件開始找到你的項目的所有的依賴文件,使用loaders處理他們,最後打包爲一個瀏覽器可 以識別的js文件。
三、手寫原理如下
(function (modules) {
var installedModules = {}; //模塊緩存
function __webpack_require__(moduleId) {
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
//創建一個新的模塊並賦值給module,並且放置到模塊的緩存(installedModules)中
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
module.l = true;
return module.exports;
}
//把模塊的定義對象緩存在_webpack_require_.m屬性上
__webpack_require__.m=modules;
// 把已經回去過的模塊組緩存放在__webpack_require__.c屬性上, 方便以後獲取
__webpack_require__.c=installedModules;
// 給一個對象增加一個屬性 d=defineProperty
__webpack_require__.d=function(exports,name,getter){
// o=hasOwnProperty
if(__webpack_require__.o(exports,name)){
Object.defineProperty(exports,name,{enumerable:true,get:getter});
}
}
__webpack_require__.o=function(object,property){
return Object.prototype.hasOwnProperty.call(object,property);
}
//表示這是一個es6模塊 esports.__esModule=true; 表示這是一個es6模塊。
__webpack_require__.r=function(exports){
if(typeof Symbol!=='undefined' &&Symbol.toStringTag){
Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});
}
Object.defineProperty(exports,'_esModule',{value:true});
}
// 創建一個模擬的命名對象。
// t的核心作用是把一個任意的模塊common.js es module 都包裝成es module的形式
__webpack_require__.t=function(value,mode){
// 如果與1爲true ,說明第一位是1,那麼則表示value是模塊ID,需要直接通過require加載,獲取它的module.exports對象
// 0001
if(mode & 1){ // 加載這個模塊ID,把value重新賦值爲導出對象
value=__webpack_require__(value); // 從模塊ID變成了模塊的導出對象了。
}
// 1000 可以直接返回, 如果&1,&8,行爲類似於__webpack_require__
if(mode & 8){
return value;
}
//0100 如果與4 爲true 並且value有值,並且value._esModule 說明已經是一個esModule一個包裝過的模塊。
if(mode & 4 && typeof value==='object' && value._esModules){
return value;
}
var ns=Object.create(null); //創建一個新對象給他添加一個default屬性,屬性的值就是value。
Object.defineProperty(ns,'default',{enumerable:true,value})
// &2 等於 表示要把value所有屬性拷貝到命名空間上。ns
if(mode & 2 && typeof value !=='string'){
for(let key in value){
__webpack_require__.d(ns,key,function(key){ return value[key]}.bind(null,key));
}
}
return ns; // 此方法會在後面加載懶加載的時候用到。
}
// publicPath 公開訪問路徑
__webpack_require__.p='';
return __webpack_require__(__webpack_require__.s="./src/index.js");
})
(
{
"./src/index.js":
(function (module, exports, __webpack_require__) {
let title = __webpack_require__("./src/title.js");
console.log(title);
}),
"./src/title.js":
(function (module, exports) {
console.log('title');
})
}
)
// modules key 是模塊的相對路徑 ./src/index.js
// 值是一個value 是一個函數,格式有點像node中的node.js