内容简介:webpack 用于编译首先我们试着打包一个只包含由于打包后的文件比较繁琐, 这里我们简化一下打包后的文件
webpack 用于编译 javascript 模块, 可以把文件格式编译成我们想要的静态文件格式, 但是处理的过程并不是全部由 webpack 本身完成, webpack 只是提供了一个打包机制, 对于各类文件的打包处理需要使用相对应的 预处理模块 loader 来处理, 作为一种机制 webpack 会帮助各种 loader 提供识别入口目录、入口文件、 输出目录, 输出文件。
首先我们试着打包一个只包含 console.log('hello world') 的 js 文件。
初始化文件和安装 webpack 环境
# 新建 demo 目录
mkdir webpack-demo cd webpack-demo
# 初始化目录
npm init -y
# 本地安装 webpack 工具
npm install webpack webpacl-cli --save-dev
# webpack 默认的入口文件是 .src/index.js 创建 src 目录和 index.js 文件
mkdir src
echo “console.log('hello world')” > src/index.js
# 执行 webpack 命令 需要查看打包后文件, 这里使用 development 模式
npx webpack --mode development
复制代码
简化打包后文件
由于打包后的文件比较繁琐, 这里我们简化一下打包后的文件
(function(modules) {
var installedModules = {}
function __webpack_require__(moduleIid) {
}
return __webpack_require__(__webpack_require__.s = "./src/index.js")
})({
"./src/index.js": (function(module, exports) {
eval("console.log('test webpack entry')");
})
})
复制代码
打包后的文件含有大量的注释和 webpack 本身的变量, 为了方便分析可以把这些注释和 类似 __webpack_require__.s 的复制语句全部删掉
从上面的代码可以看到,
- 经过
webpack打包后的代码通过一个IIFE自执行函数, 这个函数接收一个对象参数, 这个对象的key为入口文件的目录,value是一个执行入口文件里面代码的函数 - 这个对象作为参数
modules传递给IIFE函数 -
IIFE函数里面声明了一个变量installedModules用来存放缓存, 一个函数__webpack_require__, 用来转化入口文件里面的代码 -
IIFE最终把modules里面的的key传递给__webpack_require__函数并返回。
我们进一步看 __webpack_require__ 函数都做了什么。
__webpack_require__ 分析
function (modules) {
var installedModules = {}
function __webpack_require__ (moduleId) {
if(installedModules[moduleId]) {
return installedModules[moduleId].exports
}
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__函数接收./src/index.js - 首先检查缓存
installedModules中是否包含key为./src/index.js的对象, 如果存在直接返回这个对象中的exports - 当缓存中不存在入口模块的时候, 在缓存中生成一个对象并放到缓存中, 这个对象包括三个值:
ilexports - 使用
modules[moduleId].call调用IIFE参数的value函数, 并把value对应的函数中的this指向赋值给了module.exports, 后面的call方法的后面三个参数为value对应函数的参数 - 最后返回了
module.exports, 这里的module.exports在第四步的时候已赋值为IIFE参数对象中的value对应的函数。
所以可以看出来。 函数 __webpack_require__ 实际返回的就是 IIFE 参数对象中的 value 对应的函数, 也就是 eval("\nconsole.log('test webpack entry')\n\n\n//# sourceURL=webpack:///./src/index.js?") ,
当我们运行 webpack 打包后的文件的时候执行的是 "console.log('test webpack entry')"
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
入口文件引用其他模块时的打包过程
上面讲的打包过程入口文件中并没有引用其他的代码模块, 当入口文件中引用其他的模块的时候, webpack 的打包过程也和上述过程相似。
在 ./src/ 下新建 main.js
module.exports = () => {
console.log('main module')
}
复制代码
在 ./src/index.js 中引入 main.js
const main = reuiqre('./main.js')
console.log('webpack index entry')
main()
复制代码
运行 npx webpack 打包后的文件
IIFE 参数的变化
(function (mudoles) {
})({
'./src/index.js': (function(module,exports, __webpack_require__) {
eval("const main = __webpack_require__(/*! ./main.js */ \"./src/main.js\")\r\nconsole.log('test webpack entry')\r\n\n\n//# sourceURL=webpack:///./src/index.js?");
}),
'./src/main.js': (function(module, exports) {
eval("console.log('main module')\n\n//# sourceURL=webpack:///./src/main.js?");
})
})
复制代码
如果入口文件中引用了其他模块的文件,将会把这些模块添加到 IIFE 的参数对象中, key 为模块的路径, value 执行该模块代码的函数。
IIFE 函数执行逻辑的变化
function (modules) {
var installedModules = {}
function __webpack_require__ (moduleId) {
if (installedModules[moduleId]) {
return installedMOdules[mudoleId].exports
}
var module = installedModuled[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)
return module.exports
}
return __webpack_require__(__webpack_require__.s = "./src/index.js")
}
复制代码
上面的代码中依旧返回了以 ./src/index.js 为参数的函数。 但是函数里面的逻辑发生了改变。
- 声明一个
installedModules变量存放缓存 - 将
./src/index.js传入__webpack_require__函数 -
./src/index.js不在缓存中, 往下执行 - 声明一个
module并在缓存中存放一以./src/index.js为key的对象 - 调用
modules[moduleId]函数,并指明 作用域和参数 也就是function(module,exports, __webpack_require__) { eval("const main = __webpack_require__(/*! ./main.js */ \"./src/main.js\")\r\nconsole.log('test webpack entry')\r\n\n\n//# sourceURL=webpack:///./src/index.js?")} 复制代码 - 返回
module.exports, 由于在第五步调用modules['./src/index.js']函数的时候, 已经把module.exports作为了函数的this作用域, 所以这时module.exports实际就是modules['./src/index.js']执行的函数。 - 在上面的函数中,
eval代码中使用了一个函数__webpack_require__, 这个函数就是在第五步modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)的最后一个参数__webpack_require__, 这时继续调用__webpack__require__函数并传入./src/main.js -
./src/main.js传入__webpack_require__中, 依旧不在缓存, 再次声明一个变量module并在缓存中新增一个key为./src/main.js的对象。 -
modules[moduleId].call这时调用IIFE参数对象中key为./src/main.js的函数:(function(module, exports) { eval("console.log('main module')\n\n//# sourceURL=webpack:///./src/main.js?"); }) 复制代码 - 返回
module.export, 同第6步相似这时的module.exports就是modules[./src/main.js]对应的函数。 - 返回的最终结果就是(去除了
eval和注释):
const main = console.log('main module')
console.log(test webpack entry)
复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Build Your Own Web Site the Right Way Using HTML & CSS
Ian Lloyd / SitePoint / 2006-05-02 / USD 29.95
Build Your Own Website The Right Way Using HTML & CSS teaches web development from scratch, without assuming any previous knowledge of HTML, CSS or web development techniques. This book introduces you......一起来看看 《Build Your Own Web Site the Right Way Using HTML & CSS》 这本书的介绍吧!
URL 编码/解码
URL 编码/解码
UNIX 时间戳转换
UNIX 时间戳转换