一、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