rollup别名配置插件详解(@rollup/plugin-alias) / (rollup-plugin-alias)

566 阅读2分钟

核心代码resolverId这个钩子

参数

  • importee: 被导入的模块路径
  • importer:导入该模块的文件路径
  • resolveOptions:解析选项

返回值类型

  • null: 表示rollup应该使用默认的解析逻辑
  • string:解析后的模块路径
  • object:包含id属性的对象,表示解析后的模块路径

核心代码

// 简单的匹配
function matches(pattern: string | RegExp, importee: string) {
  if (pattern instanceof RegExp) {
    return pattern.test(importee);
  }
  if (importee.length < pattern.length) {
    return false;
  }
  if (importee === pattern) {
    return true;
  }
  // eslint-disable-next-line prefer-template
  return importee.startsWith(pattern + '/');
}



resolveId(importee, importer, resolveOptions) {
    // importee: @/test.js
    // importer: path.resolve(__dirname, './main.js')
    // 例如配置是 resolve.alias: {
            "@": path.resolve(__dirname, './src')
        }
  // First match is supposed to be the correct one
  // 此时 matches函数应当会被返回true, 
  const matchedEntry = entries.find((entry) => matches(entry.find, importee));
  if (!matchedEntry) {
    return null;
  }
    // 这里被替换成绝对路径
  const updatedId = importee.replace(matchedEntry.find, matchedEntry.replacement);

  if (matchedEntry.resolverFunction) {
    return matchedEntry.resolverFunction.call(this, updatedId, importer, resolveOptions);
  }
    
   // 在这儿最终通过importer 和 updatedId 得到路径 src/test.js  
  return this.resolve(
    updatedId,
    importer,
    Object.assign({ skipSelf: true }, resolveOptions)
  ).then((resolved) => {
    if (resolved) return resolved;

    if (!path.isAbsolute(updatedId)) {
      this.warn(
        `rewrote ${importee} to ${updatedId} but was not an abolute path and was not handled by other plugins. ` +
          `This will lead to duplicated modules for the same path. ` +
          `To avoid duplicating modules, you should resolve to an absolute path.`
      );
    }
    return { id: updatedId };
  });
}

例如

resolve 别名配置

    resolve:{
        alias: {
           "@": path.resolve(__dirname, ''./src')
        }
    }

main.js

import '@/test.js'

test.js的位置在项目:src/test.js

通过插件的解析

当获取到main.js之后发现有别名,会通过转换

    {
        find: '@'
        replacement: /xxx/src
    }

const updatedId = importee.replace(matchedEntry.find, matchedEntry.replacement); 这段代码就是替换的作用,把@/test.js -> /xxx/src/test.js然后再通过

return this.resolve(
    updatedId,
    importer,
    Object.assign({ skipSelf: true }, resolveOptions)
  ).then((resolved) => {
    if (resolved) return resolved;

    if (!path.isAbsolute(updatedId)) {
      this.warn(
        `rewrote ${importee} to ${updatedId} but was not an abolute path and was not handled by other plugins. ` +
          `This will lead to duplicated modules for the same path. ` +
          `To avoid duplicating modules, you should resolve to an absolute path.`
      );
    }
    return { id: updatedId };
  });

importerupdatedId的路径替换

importer: main.js得到的path = /project
updatedId: test.js = /project/src/test.js
最终的updatedId,需要再浏览器展示,需要获取rootpath
app-root-path:这个包可以获取到 res.path:  /project
然后updatedI.replace(res.path, '') -> /src/test.js -> localhost:9090/src/test.js

app-root-path 核心代码

const getFirstPartFromNodeModules = function(resolved) { 
    const nodeModulesDir = sep + 'node_modules'; 
    if (-1 !== resolved.indexOf(nodeModulesDir)) { 
        const parts = resolved.split(nodeModulesDir); 
        if (parts.length) { 
            return parts[0]; 
        } 
    } 
    return null; 
}