深刻理解webpack如何解析代碼路徑

引入

在運用前端主流框架(react,vue,angular)開發過程當中,引入一個模塊或文件路徑,是如何解析到目標文件的?是按照什麼樣的規則和順序查找到的?這個問題乍一看是簡單,尤爲在小型項目中,模塊和文件並很少的狀況下。但遇到一些比較複雜的項目,模塊和文件路徑的引入須要謹慎當心,這就須要深刻地理解一下webpack的代碼路徑解析規則了。css

路徑

首先,綜合一下在項目中配置路徑的三種形式前端

  1. 相對路徑

相對路徑是相對於當前目錄的路徑vue

import {button} from '../component/button'
複製代碼
  1. 絕對路徑

絕對路徑直接指明瞭文件的具體位置,直接能夠查找到(不建議使用)node

import {button} from '/home/me/file'
複製代碼
  1. 模塊名

直接引入模塊名,會查找當前文件目錄,父級目錄直至根目錄下的 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

  1. 若是是文件,直接加載框架

  2. 若是是文件夾,查找裏面是否有package.json文件

    1)若是有,默認按照裏面的main字段的文件名查找文件 (能夠經過resolve.mainFields 配置更改)

    2)若是沒有,默認查找index.js文件(能夠經過resolve.mainFiles配置更改)

resolve配置

瞭解上述的路徑形式和最終的解析規則後,根據個人一些標識,大體上也可以看出webpack路徑配置的發揮空間了。

webpack解析代碼路徑的核心模塊是enhanced-resolve模塊

webpack解析匹配代碼路徑的配置在resolve裏面

接下來將着重對resolve中alias,extensions,modules,mainFields,mainFiles屬性作單獨詳細的介紹。

resolve.alias

alias,顧名思義,是指路徑的別名。簡單點說,就是用一個簡單的別名來替換一個經常使用的或者複雜的文件路徑。

原理:先替換,後解析。在引入模塊時,先將模塊路徑中匹配alias中的key替換成對應的value,再作查找。

注意一下幾點:

  1. 替換掉的路徑能夠是相對路徑,也能夠是絕對路徑。
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' // 這裏不能匹配
    }
}
複製代碼

resolve.extensions

extensions中指定了webpack能夠識別的文件擴展名。

注意一下幾點:

  1. 擴展名匹配的前後順序。從左到右依次匹配。好比下例中,引入import {Button} from './component/button',優先匹配的是button.js,若是沒有button.js,會匹配button.vue,依次往下。
  2. extensions中沒有的後綴,是不會自動補全的。好比下例中沒有css的擴展名,若是想引入import {Button} from './style/button',是匹配不到button.css文件的
resolve: {
    extensions: ['js', 'vue', 'json']
}
複製代碼

resolve.modules

查找聲明依賴名的模塊,默認搜索node_modules目錄。通常咱們不修改這個配置。

resolve: {
  modules: ['node_modules']
},
複製代碼

resolve.mainFields

在引用模塊時,指明使用package.json中哪一個字段指定的文件,默認是「main」

resolve: {
  // 配置 target === "web" 或者 target === "webworker" 時 mainFields 默認值是:
  mainFields: ['browser', 'module', 'main'],

  // target 的值爲其餘時,mainFields 默認值爲:
  mainFields: ["module", "main"],
}
複製代碼

由於一般狀況下,模塊的 package 都不會聲明 browser 或 module 字段,因此即是使用 main 了。

resolve.mainFiles

在目錄中沒有package.json時,指明使用該目錄中哪一個文件,默認是index.js

resolve: {
  mainFiles: ['index'], // 能夠添加其餘默認使用的文件名
}
複製代碼

最後

resolve除了上面介紹的幾個屬性外,還有其餘一些屬性,有興趣的筒子們能夠再深刻研究一下。但願我這篇文章對還不太清楚webpack代碼路徑的童鞋有必定的指引做用~~

相關文章
相關標籤/搜索