在運用前端主流框架(react,vue,angular)開發過程當中,引入一個模塊或文件路徑,是如何解析到目標文件的?是按照什麼樣的規則和順序查找到的?這個問題乍一看是簡單,尤爲在小型項目中,模塊和文件並很少的狀況下。但遇到一些比較複雜的項目,模塊和文件路徑的引入須要謹慎當心,這就須要深刻地理解一下webpack的代碼路徑解析規則了。css
首先,綜合一下在項目中配置路徑的三種形式前端
相對路徑是相對於當前目錄的路徑vue
import {button} from '../component/button'
複製代碼
絕對路徑直接指明瞭文件的具體位置,直接能夠查找到(不建議使用)node
import {button} from '/home/me/file'
複製代碼
直接引入模塊名,會查找當前文件目錄,父級目錄直至根目錄下的 node_modules(默認) 文件夾,看是否有對應名稱的模塊。react
import React from 'react'
import "module/lib/file";
複製代碼
注意:默認的node_modules能夠根據webpack配置的
resolve.modules
進行更改webpack
注意:查找中會根據webpack配置的
resolve.extensions
自動補全擴展名web
注意:查找中會根據wepack配置的
resolve.alias
替換掉別名json
根據上述規則解析路徑後,解析器將路徑指向文件或者文件夾(目錄)bash
若是是文件,直接加載框架
若是是文件夾,查找裏面是否有package.json文件
1)若是有,默認按照裏面的main字段的文件名查找文件 (能夠經過resolve.mainFields
配置更改)
2)若是沒有,默認查找index.js文件(能夠經過resolve.mainFiles
配置更改)
瞭解上述的路徑形式和最終的解析規則後,根據個人一些標識,大體上也可以看出webpack路徑配置的發揮空間了。
webpack解析代碼路徑的核心模塊是
enhanced-resolve
模塊
webpack解析匹配代碼路徑的配置在
resolve
裏面
接下來將着重對resolve中alias,extensions,modules,mainFields,mainFiles屬性作單獨詳細的介紹。
alias,顧名思義,是指路徑的別名。簡單點說,就是用一個簡單的別名來替換一個經常使用的或者複雜的文件路徑。
原理:先替換,後解析。在引入模塊時,先將模塊路徑中匹配alias中的key替換成對應的value,再作查找。
注意一下幾點:
resolve: {
alias: {
'@': path.resolve(__dirname, 'components'),
// 這裏使用 path.resolve 和 __dirname 來獲取絕對路徑
// import '@/Button.js' 等同於 import '[項目絕對路徑]/components/Button.js'
x: './src/components' // 相對路徑
}
}
複製代碼
2.這裏的匹配是模糊匹配,不是精確匹配。即路徑中攜帶別名便可匹配
3.注意精確匹配的用法。在key的末尾帶一個$字符
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'x$': 'module/dir'
// Import 'x/file.js' // 這裏不能匹配
}
}
複製代碼
extensions中指定了webpack能夠識別的文件擴展名。
注意一下幾點:
resolve: {
extensions: ['js', 'vue', 'json']
}
複製代碼
查找聲明依賴名的模塊,默認搜索node_modules目錄。通常咱們不修改這個配置。
resolve: {
modules: ['node_modules']
},
複製代碼
在引用模塊時,指明使用package.json中哪一個字段指定的文件,默認是「main」
resolve: {
// 配置 target === "web" 或者 target === "webworker" 時 mainFields 默認值是:
mainFields: ['browser', 'module', 'main'],
// target 的值爲其餘時,mainFields 默認值爲:
mainFields: ["module", "main"],
}
複製代碼
由於一般狀況下,模塊的 package 都不會聲明 browser 或 module 字段,因此即是使用 main 了。
在目錄中沒有package.json時,指明使用該目錄中哪一個文件,默認是index.js
resolve: {
mainFiles: ['index'], // 能夠添加其餘默認使用的文件名
}
複製代碼
resolve除了上面介紹的幾個屬性外,還有其餘一些屬性,有興趣的筒子們能夠再深刻研究一下。但願我這篇文章對還不太清楚webpack代碼路徑的童鞋有必定的指引做用~~