webpack配置別名alias出現的錯誤匹配
阿新 • • 發佈:2022-05-04
@(webpack)
webpack是一款功能強大的前端構建工具,不僅僅是針對js,它也可通過各種loader來構建相關的less,html,image等各種資源,將webpack配合流程制定工具gulp結合起來,則更為方便的自定義工作流程。
[TOC]
webpack的alias匹配問題初現
在webpack.config.js中,通過設定resolve屬性可以配置查詢“commonJS/AMD模組”的基路徑,也可以設定搜尋的模組字尾名,當然,最後一個就是我們要講的別名alias設定。
跟蹤問題
在模組開發過程中,我們可能會對可以複用的元件封裝成一個可被git管控的模組,並在引用的過程中採用帶版本號的方式引用
... module.exports = { entry: { main: 'index.js' }, output: { path: 'build' filename: '[name].js' }, resolve: { root: 'modules' alias: { 'mod/slider': '/path/mods/mod/slider/0.0.5', 'mod/footer': '/path/mods/mod/footer/0.0.2', 'mod/slider/0.0.3': '/path/mods/mod/slider/0.0.3', 'mod/header': '/path/mods/mod/header/0.0.1', 'mod/slider/0.0.1': '/path/mods/mod/slider/0.0.1' } } }
有一個簡單的需求,即在index.js中,可這樣引用:
var slider = require('mod/slider');
var sliderV3 = require('mod/slider/0.0.3');
var sliderV1 = require('mod/slider/0.0.1');
結果和我們預想的會有不同,webpack的別名處理邏輯會使這三個變數的引用都為 slider這個變數所對應的模組,要想解決這種情況,只能深入原始碼。
深入原始碼之ModuleAliasPlugin
先貼上部分原始碼:
var aliasMap = this.aliasMap; resolver.plugin("module", function(request, callback) { var fs = this.fileSystem; var keys = Object.keys(aliasMap); var i = 0; (function next() { for(;i < keys.length; i++) { var aliasName = keys[i]; var onlyModule = /$$/.test(aliasName); if(onlyModule) aliasName = aliasName.substr(0, aliasName.length-1); if((!onlyModule && request.request.indexOf(aliasName + "/") === 0) || request.request === aliasName) { var aliasValue = aliasMap[keys[i]]; if(request.request.indexOf(aliasValue + "/") !== 0 && request.request != aliasValue) { var newRequestStr = aliasValue + request.request.substr(aliasName.length); var newRequest = this.parse(newRequestStr); var obj = { path: request.path, request: newRequest.path, query: newRequest.query, directory: newRequest.directory }; var newCallback = createInnerCallback(callback, callback, "aliased with mapping " + JSON.stringify(aliasName) + ": " + JSON.stringify(aliasValue) + " to " + newRequestStr); if(newRequest.module) return this.doResolve("module", obj, newCallback); if(newRequest.directory) return this.doResolve("directory", obj, newCallback); return this.doResolve(["file", "directory"], obj, newCallback); } } } return callback(); }.call(this));
這段簡單的程式碼所做的就是針對別名做對映,獲取到對應的模組。 之所以出現上節的問題,就是因為這句判斷
if(request.request.indexOf(aliasValue + "/") !== 0 && request.request != aliasValue)
webpack的作者貌似有些多此一舉了,或者說是在我們的應用場景中並沒有考慮到,所以僅僅針對這個判斷進行修改就可以滿足需求。修改非常簡單,進行嚴格相等的判斷:
if(request.request != aliasValue)