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運行結束。