npm 与 webpack打包
一、npm
介绍:js有两个主流的包管理器——npm和yarn,两者仓库是共通的
1. 本地怎么导入一个npm模块呢?
-
安装:npm一个模块后,package.json会记录该模块依赖信息,而该模块则会保存在node_modules里
-
使用:
import xx from 'xxx'
-
功能:Webpack打包时解析到这句话,会去node_modules里寻找对应模块并引用
-
寻找引用模块的过程:
- 我们先看看一个存放在node_modules的echarts-amap模块的目录:
│ index.html │ index.js │ LICENSE │ package.json │ README.md │ webpack.config.js │ ├─dist │ echarts-amap.min.js │ echarts-amap.min.js.map │ └─src amap.js AMapCoordSys.js AMapModel.js AMapView.js
- 入口:每一个npm模块都有一个入口,这个入口被维护在模块内部的package.json的main字段里,所以我们看看package.json:
{ "name": "echarts-amap", ... "main": "index.js", ... }
- 在这个例子,入口文件就是index.js。实际上,我们加载的,是该模块的入口文件,也就是说在这个例子里,我们实际加载的是index.js。然后我们再看看index.js:
module.exports = require('./dist/echarts-amap.min.js')
- index.js会导出echarts-amap.min.js。所以,最终我们import得到的就是echarts-amap.min.js。
- 而webpack最后也只会打包echarts-amap.min.js这个文件,减少打包资源的体积。
- 测试:我们可以通过script标签直接引用echarts-amap.min.js,最后发现效果是一样的。
二、webpack打包原理
- webpack打包后的bundle的代码结构如下:
(function (modules) { // 匿名函数,构成自身作用域
// 模块缓存
var installedModules = {};
// 模块加载的具体代码实现
function _webpack_require_(moduleId) {
...
}
...
// 执行入口模块'./src/index.js'的加载
return _webpack_require_(_webpack_require_.s = './src/index.js');
}) ({
// modules: 以key-value的形式存储所有被打包的模块
"./src/index.js": function(module, exports, _webpack_require_) {
// 如果是被import的,则"use strict";
eval("module.exports = _webpack_require_(\'./src/js/test.js\'");
},
"./src/js/test.js": function(module, exports, _webpakc_require_) {
eval('xxxxx');
}
})
- 执行流程:
- 最外层的匿名函数会初始化浏览器执行环境,完成一些变量、函数的定义
- 加载入口模块。比如在上例中,index.js就是入口模块。
- 执行模块代码。如果执行到module.exports则记录下模块的导出值;如果中间遇到_webpack_require_,暂时交出执行权,进入_webpack_require_函数体内进行加载其他模块的逻辑
- 在_webpack_require_中会判断即将加载的模块是否存在于installedModules中。如果存在则直接取值,否则回到第三步,执行该模块的代码来获取导出值。
- 所有模块的依赖都已执行完毕,最后执行权回到入口模块。但入口模块代码执行完毕,整个打包js运行结束。