import 被webpack 编译成了啥?
我们知道,webpack 打包过程如下:
- 合并webpack.config.js和命令行传递的参数,形成最终的配置
- 解析配置,得到entry入口
- 读取入口文件内容,通过@babel/parse将入口内容(code)转换成ast
- 通过@babel/traverse遍历ast得到模块的各个依赖
- 通过@babel/core(实际的转换工作是由@babel/preset-env来完成的)将ast转换成es5 code
- 通过循环伪递归的方式拿到所有模块的所有依赖并都转换成es5
那么,问题来了。
问题:import moduleName from 'xxModule’和import(‘xxModule’)经过webpack编译打包后最终变成了什么?在浏览器中是怎么运行的?
答案:
- import经过webpack打包以后变成一些Map对象,key为模块路径,value为模块的可执行函数;
- 当然其中的异步方法(import(‘xxModule’))比较特殊一些,它会单独打成一个包,采用动态加载的方式。
具体过程:当用户触发其加载的动作时,会动态的在head标签中创建一个script标签,然后发送一个http请求,加载模块,模块加载完成以后自动执行其中的代码,主要的工作有两个,更改缓存中模块的状态,另一个就是执行模块代码。(webpack4)
没看懂?继续往下看解析
分析:
-
初始化项目
执行命令npm init -y npm i webpack webpack-cli -D
webpack.config.js文件:
const path = require('path') module.exports = { entry: './src/index.js', // 为了利于分析打包后的代码,这里选择开发模式 mode: 'development', output: { path: path.resolve(__dirname, './dist'), filename: 'main.js' } }
src/index.js 文件:
/** * 入口文件,引入 print 方法,并执行 * 定义了一个 button 方法,为页面添加一个按钮,并为按钮设置了一个 onclick 事件,负责动态引入一个文件 */ import { print } from './num.js' print() function button () { const button = document.createElement('button') const text = document.createTextNode('click me') button.appendChild(text) button.onclick = e => import('./info.js').then(res => { console.log(res.log) }) return button } document.body.appendChild(button())
src/num.js 文件:
export function print () { console.log('我是 num.js 的 print 方法') }
src/num.js 文件:
export const log = "log info"
打包
执行命令
npx webpack
会看到多了一个 dist 目录,且看输出结果,main.js是我们在webpack.config.js中配置的输出的文件名,但是src_info_js.main.js呢?这是什么????
模版文件
新建/dist/index.html文件,并引入打包后的main.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src = "./main.js"></script>
</body>
</html>
在浏览器打开 index.html
控制台输出如下:
分析打包后的源码
首先将源码折叠
(function (modules) {
// xxxx
})({
// xxx
})
这是一个自执行函数
函数参数
webpack将所有的import moduleName from 'xxModule’都变成了一个Map对象,key为文件路径,value为一个可执行的函数,而函数内容其实就是模块中导出的内容,当然,模块自己也被webpack做了一些处理,接着往下进行。
从打包后Map对象中能找到我们代码中的各个模块,以及模块的内容,但是也多了很多不属于我们编写的代码,比如以__webpack_require__开头的代码,这些又是什么呢?其实是webpack自定义的一些方法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。