开门见山
1.打包单一模块
webpack.config.js
module.exports = {
entry:"./chunk1.js",
output: {
path: __dirname + '/dist',
filename: '[name].js'
},
};
chunk1.js
var chunk1=1;
exports.chunk1=chunk1;
打包后,main.js(webpack生成的一些注释已经去掉)
(function(modules) { // webpackBootstrap
// The module cache
var installedModules = {};
// 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] = {
exports: {},
id: moduleId,
loaded: false
};
// Execute the module function
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.loaded = true;
// Return the exports of the module
return module.exports;
}
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// __webpack_public_path__
__webpack_require__.p = "";
// Load entry module and return exports
return __webpack_require__(0);
})([function(module, exports) {
var chunk1=1;
exports.chunk1=chunk1;
}]);
这其实就是一个立即执行函数,简化一下就是:
(function(module){})([function(){},function(){}]);
OK,看一下自运行的匿名函数里面干了什么:
function(modules) { // webpackBootstrap
// modules就是一个数组,元素就是一个个函数体,就是我们声明的模块
var installedModules = {};
// The require function
function __webpack_require__(moduleId) {
...
}
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// __webpack_public_path__
__webpack_require__.p = "";
// Load entry module and return exports
return __webpack_require__(0);
}
整个函数里就声明了一个变量installedModules 和函数__webpack_require__,并在函数上添加了一个m,c,p属性,m属性保存的是传入的模块数组,c属性保存的是installedModules变量,P是一个空字符串。最后执行__webpack_require__函数,参数为零,并将其执行结果返回。下面看一下__webpack_require__干了什么:
function __webpack_require__(moduleId) {
//moduleId就是调用是传入的0
// installedModules[0]是undefined,继续往下
if(installedModules[moduleId])
return installedModules[moduleId].exports;
// module就是{exports: {},id: 0,loaded: false}
var module = installedModules[moduleId] = {
exports: {},
id: moduleId,
loaded: false
};
// 下面接着分析这个
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// 表明模块已经载入
module.loaded = true;
// 返回module.exports(注意modules[moduleId].call的时候module.exports会被修改)
return module.exports;
}
接着看一下modules[moduleId].call(module.exports, module, module.exports, __webpack_require__),其实就是
modules[moduleId].call({}, module, module.exports, __webpack_require__)
对call不了解当然也可以认为是这样(但是并不是等价,call能确保当模块中使用this的时候,this是指向module.exports的):
function a(module, exports) {
var chunk1=1;
exports.chunk1=chunk1;
}
a(module, exports,__webpack_require__);
传入的module就是{exports: {},id: 0,loaded: false},exports就是{},__webpack_require__就是声明的__webpack_require__函数(传入这个函数有什么用呢,第二节将会介绍);
运行后module.exports就是{chunk1:1}。所以当我们使用chunk1这个模块的时候(比如var chunk1=require("chunk1"),得到的就是一个对象{chunk1:1})。如果模块里没有exports.chunk1=chunk1或者module.exports=chunk1得到的就是一个空对象{}
2.使用模块
上面我们已经分析了webpack是怎么打包一个模块的(入口文件就是一个模块),现在我们来看一下使用一个模块,然后使用模块的文件作为入口文件
webpack.config.js
module.exports = {
entry:"./main.js",
output: {
path: __dirname + '/dist',
filename: '[name].js'
}
};
main.js
var chunk1=require("./chunk1");
console.log(chunk1);
打包后
(function (modules) { // webpackBootstrap
// The module cache
var installedModules = {};
// 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] = {
exports: {},
id: moduleId,
loaded: false
};
// Execute the module function
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.loaded = true;
// Return the exports of the module
return module.exports;
}
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// __webpack_public_path__
__webpack_require__.p = "";
// Load entry module and return exports
return __webpack_require__(0);
})([function (module, exports, __webpack_require__) {
var chunk1=__webpack_require__(1);
console.log(chunk1);
}, function (module, exports) {
var chunk1 = 1;
exports.chunk1 = chunk1;
}]);
不一样的地方就是自执行函数的参数由
[function(module, exports) { var chunk1=1; exports.chunk1=chunk1;}]
[function (module, exports, __webpack_require__) {
var chunk1=__webpack_require__(1);
console.log(chunk1);
}, function (module, exports) {
var chunk1 = 1;
exports.chunk1 = chunk1;
}]
其实就是多了一个main模块,不过这个模块没有导出项,而且这个模块依赖于chunk1模块。所以当运行__webpack_require__(0)的时候,main模块缓存到installedModules[0]上,modules[0].call(也就是调用main模块)的时候,chunk1被缓存到installedModules[1]上,并且导出对象{chunk1:1}给模块main使用
3.重复使用模块
webpack.config.js
module.exports = {
entry:"./main.js",
output: {
path: __dirname + '/dist',
filename: '[name].js'
}
};
main.js
var chunk1=require("./chunk1");
var chunk2=require(".chunlk2");
console.log(chunk1);
console.log(chunk2);
chunk1.js
var chunk2=require("./chunk2");
var chunk1=1;
exports.chunk1=chunk1;
chunk2.js
var chunk2=1;
exports.chunk2=chunk2;
打包后
(function (modules) { // webpackBootstrap
// The module cache
var installedModules = {};
// 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] = {
exports: {},
id: moduleId,
loaded: false
};
// Execute the module function
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
// Flag the module as loaded
module.loaded = true;
// Return the exports of the module
return module.exports;
}
// expose the modules object (__webpack_modules__)
__webpack_require__.m = modules;
// expose the module cache
__webpack_require__.c = installedModules;
// __webpack_public_path__
__webpack_require__.p = "";
// Load entry module and return exports
return __webpack_require__(0);
})([function (module, exports, __webpack_require__) {
var chunk1 = __webpack_require__(1);
var chunk2 = __webpack_require__(2);
console.log(chunk1);
console.log(chunk2);
}, function (module, exports, __webpack_require__) {
__webpack_require__(2);
var chunk1 = 1;
exports.chunk1 = chunk1;
}, function (module, exports) {
var chunk2 = 1;
exports.chunk2 = chunk2;
}]);
不难发现,当需要重复使用模块的时候,缓存变量installedModules 就起作用了
4.多个打包入口
不管是单一模块还是重复模块,和以上两种一样
5.入口参数为数组
webpack.config.js
module.exports = {
entry:['./main.js','./main1.js'],
output: {
path: __dirname + '/dist',
filename: '[name].js'
}
};
打包后
[
/* 0 */
/***/ function(module, exports, __webpack_require__) {
__webpack_require__(1);
module.exports = __webpack_require__(3);
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
var chunk1=__webpack_require__(2);
console.log(chunk1);
/***/ },
/* 2 */
/***/ function(module, exports) {
var chunk1=1;
exports.chunk1=chunk1;
/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {
var chunk1=__webpack_require__(2);
/***/ }
/******/ ]
这里只截取自执行匿名函数的参数,因为其他代码与之前一样。可以看到1就是main默模块,2就是chunk1模块,3就是mian1模块,0的作用就是运行模块mian,mian1,然后将main1模块导出(main1中没有导出项,所以到导出{}),总结一下:入口参数是字符串不管是多入口还是单入口,最后都会将入口模块的导出项导出,没有导出项就导出{},而入口参数是数组,就会将最后一个模块导出(webpackg官网有说明)
6.使用CommonsChunkPlugin插件
待续。。。