webpack 配置中的路徑

resolve.alias

resolve.alias 用於給模塊路徑指定別名。vue

爲何要給模塊路徑取別名呢?node

假設在咱們的源碼中有以下 import 語句:webpack

import BaseModel from '../../../../common/BaseModel';

export default class ProductModel extends BaseModel {

    // some code here
    
}

那麼每次引入 BaseModel 的時候,極可能都會面臨着寫很長一堆 ../../../../ 的問題,並且若是沒有編輯器的智能提示,很容易少寫(或者多寫)一層 ../web

此時就能夠在 webpack 配置中爲 BaseModel 指定一個別名:正則表達式

{
    // some other configs
    
    resolve: {
        alias: {
            common: require('path').resolve(__dirname, '../src/common')
        }
    }
    
    // some other configs
}

這樣一來,引入 BaseModel 的代碼就變成下面這樣了:數組

import BaseModel from 'common/BaseModel';

另一種場景,就是去掉路徑中的無心義的一層(站在使用者角度來講無心義)。好比安裝了 vue 模塊以後,若是不作任何配置,引入 vue 的代碼看起來是這樣的:babel

import Vue from 'vue/dist/vue.esm.js';

看起來多多少少會以爲彆扭,並且還很差調整成不一樣的版本(開發時用 vue.esm.js ,發佈的時候用 vue.runtime.js )。編輯器

此時在 webpack 中加上不一樣環境的別名:ui

{
    // some other configs
    
    resolve: {
        alias: {
            vue$: process.env.NODE_ENV === 'production'
                ? 'vue/dist/vue.runtime.js' : 'vue/dist/vue.esm.js'
        }
    }
    
    // some other configs
}

看起來就優雅不少了。code

那麼 alias 的原理是怎麼樣的呢?

配置了 alias 以後,在 webpack 解析引入(經過 import 或者 require )的模塊的時候,會先將源碼中的模塊路徑中匹配 alias 裏 key 的部分替換成 value 部分,再作查找。

好比源碼中有以下引入語句:

import Test1 from 'xyz/file';

alias 中有以下配置:

{
    // some other configs
    
    resolve: {
        alias: {
            xyz: './dir'
        }
    }
    
    // some other configs
}

在解析路徑的時候,會先將 xyz 替換成 ./dir ,那麼以前的 import 語句就至關於:

import Test1 from './dir/file.js';

而後 webpack 再基於 ./dir/file.js 去查找須要引入的模塊。

固然,也能夠配置絕對路徑:

{
    // some other configs
    
    resolve: {
        alias: {
            xyz: require('path').resolve(__dirname, '../dir')
        }
    }
    
    // some other configs
}

依然按照以前先替換後解析的流程執行。

另外,alias 還有一種特殊的語法:key 的末尾帶一個 $ 字符,表示精確匹配。

假設有下面 alias 配置:

{
    // some other configs
    
    resolve: {
        alias: {
            xyz$: 'xyz/dir'
        }
    }
    
    // some other configs
}

對於:

import 'xyz/file.js';

這種 import 語句,就沒法匹配上這條 alias 規則。

而:

import 'xyz';

才能匹配上。

更多 alias 的匹配示例,參考官網文檔

resolveLoader.modules

能夠經過 resolveLoader.modules 配置在哪些目錄下查找 loader ,默認是在 node_modules 目錄下查找。

那麼問題就來了,這個默認的 node_modules 指的是哪裏的 node_modules 目錄呢?換句話說,這裏的 node_modules 目錄對應的絕對路徑是怎麼構造的?

webpack 會以當前進程目錄( process.cwd() )開始,逐層往上查找 node_modules 目錄,若是查到根目錄,還沒找到,就拋出錯誤。這與 Node 查找 node_modules 目錄的行爲是一致的,只不過 Node 是從當前模塊所在目錄開始查找的。

對於其餘的相對目錄配置,查找邏輯與默認的 node_modules 同樣

對於絕對路徑,就直接找這個路徑對應的目錄了。

權威說明,可參考官網文檔

找到 resolveLoader.modules 的具體目錄以後,就按照配置的順序去查找 loader 了。

假設有以下配置:

{
    // some other configs
    
    resolveLoader: {
        modules: ['loaders1', 'loaders2']
    }
    
    // some other configs
}

若是當前進程目錄是 /a/b/c ,如今要查找 babel-loader ,就會按照以下順序查找:

/a/b/c/loaders1/babel-loader/...
/a/b/c/loaders2/babel-loader/...

/a/b/loaders1/babel-loader/...
/a/b/loaders2/babel-loader/...

/a/loaders1/babel-loader/...
/a/loaders2/babel-loader/...

/loaders1/babel-loader/...
/loaders2/babel-loader/...

注:上述示例省略號後面的內容根據其餘配置肯定,具體參看官網文檔,此處不贅述。

Rule.include 、 Rule.exclude 等路徑配置

Rule 中的 testincludeexclude 的值都是 Condition 實例。

Condition 實例可使下面的某一種值:

  • 一個字符串:輸入值必須以該字符串開始。
  • 一個正則表達式。
  • 一個由 Condition 實例組成的數組。
  • 一個對象:必須匹配全部屬性,每個屬性的行爲都是預先定義好的(屬性 key 只能是 andor 或者 not )。

對於 Rule.test ,值只能是一個正則表達式或者一個正則表達式數組。

對於 Rule.include ,值只能是一個字符串或者一個字符串數組。

Rule.exclude 的值和 Rule.include 同樣。

更詳細的描述,參考官網文檔

因此,Rule.includeRule.exclude 配置都會使用絕對路徑。

entry

entry 中配置的相對路徑,是相對於 process.cwd() 去查找的。

output.path

必須配置成一個絕對路徑。

babelrc 中的 pluginspresets 路徑

babelrc 中 pluginspresets 配置的相對路徑是相對於待轉換文件解析的。

好比在轉換 /a/b/c/d.js 模塊的時候,查找 babel-plugin-veui 的順序是:

/a/b/c/node_modules/babel-plugin-veui/...
/a/b/node_modules/babel-plugin-veui/...
/a/node_modules/babel-plugin-veui/...
/node_modules/babel-plugin-veui/...

presets 的解析邏輯與 plugins 一致。

相關文章
相關標籤/搜索