vue项目源码-rollup-plugin-alias插件问题解

2020-02-17  本文已影响0人  Yezzle

在我用windows系统运行vue项目dev分支时,报了以下错误:

[!] (plugin Rollup Core) Error: Could not load F:\F盘\workspaces\vsCode2\vueProjects\vueSource\vue\src\core\config (imported by F:\F盘\workspaces\vsCode2\vueProjects\vueSource\vue\src\platforms\web\entry-runtime-with-compiler.js): ENOENT: no such file or directory, open 'F:\F盘\workspaces\vsCode2\vueProjects\vueSource\vue\src\core\config'

定位:看文件夹下确实是有这个config.js的,于是我在源码entry-runtime-with-compiler.js中config后加上.js后重新运行,index又找不到了,网上搜索一下发现主要是rollup-plugin-alias这个插件windows不兼容的问题,也有人自己修改了插件并提交到了自己的git仓库,但是他这里需要自己再去安装依赖构建,对于只是一个函数的插件我觉得没有必要,所以我准备直接用rollup调用他的原函数。 于是经过一顿修改后直接开启调试:
1. 修改rollup-plugin-alias/src/index.js,将其中的es6模块引入方式改为require,
2. 修改package.json文件main属性为src/index.js, 以便直接从源码中调试:

   node --inspect-brk .\node_modules\rollup\bin\rollup -w -c scripts/config.js --sourcemap --environment TARGET:web-full-dev

打开chrome并输入地址: chrome://inspect/ 打开调试窗口调试
分析: 通过调试分析发现,这个alias插件只做了一件事,就是把所有引入的相对路径以绝对路径的方式返回给rollup,所以就可以在这里搞事情了:对于没有js后缀的手动给他加速后缀并返回路径即可

下面是我修改之后的index.js:

const fs = require('fs');
const { platform } = require('os');
const path = require('path');
const posix = path.posix;
const slash = require('slash');

const VOLUME = /^([A-Z]:)/;
const IS_WINDOWS = platform() === 'win32';

// Helper functions
const noop = () => null;
const matches = (key, importee) => {
  if (importee.length < key.length) {
    return false;
  }
  if (importee === key) {
    return true;
  }
  const importeeStartsWithKey = (importee.indexOf(key) === 0);
  const importeeHasSlashAfterKey = (importee.substring(key.length)[0] === '/');
  return importeeStartsWithKey && importeeHasSlashAfterKey;
};
const endsWith = (needle, haystack) => haystack.slice(-needle.length) === needle;
// const isFilePath = id => /^\.?\//.test(id);
const isFilePath = id => /(^\.?\/)|(^[a-zA-Z]\:(\\|\/))/.test(id);
const exists = (uri) => {
  try {
    return fs.statSync(uri).isFile();
  } catch (e) {
    return false;
  }
};

const resolvePath = (fpath, resolves) => {
  if(exists(fpath)) return path.resolve(fpath);
  return doResolves(fpath, resolves, 0)
}

const doResolves = (fpath, resolves, i) =>{
  let newPath = path.resolve(`${fpath}${resolves[i]}`);
  if(!resolves[i]) return path.resolve(fpath)
  if(exists(newPath)) return newPath;
  return doResolves(fpath, resolves, i+1)
}

const normalizeId = (id) => {
  if ((IS_WINDOWS && typeof id === 'string') || VOLUME.test(id)) {
    return slash(id.replace(VOLUME, ''));
  }

  return id;
};

module.exports = function alias(options = {}) {
  const hasResolve = Array.isArray(options.resolve);
  const resolve = hasResolve ? options.resolve : ['.js'];
  const aliasKeys = hasResolve
    ? Object.keys(options).filter(k => k !== 'resolve') : Object.keys(options);

  // No aliases?
  if (!aliasKeys.length) {
    return {
      resolveId: noop,
    };
  }

  return {
    resolveId(importee, importer) {
      const importeeId = normalizeId(importee);
      const importerId = normalizeId(importer);

      // First match is supposed to be the correct one
      const toReplace = aliasKeys.find(key => matches(key, importeeId));

      if (!toReplace || !importerId) {
        return null;
      }

      const entry = options[toReplace];

      let updatedId = normalizeId(importeeId.replace(toReplace, entry));

      if (isFilePath(updatedId)) {
        const directory = posix.dirname(importerId);

        // Resolve file names
        const filePath = posix.resolve(directory, updatedId);
        const match = resolve.map(ext => (endsWith(ext, filePath) ? filePath : `${filePath}${ext}`))
          .find(exists);

        if (match) {
          updatedId = match;
          // To keep the previous behaviour we simply return the file path
          // with extension
        } else if (endsWith('.js', filePath)) {
          updatedId = filePath;
        } else {
          updatedId = filePath + '.js';
        }
      }

      // if alias is windows absoulate path return resolved path or
      // rollup on windows will throw:
      //  [TypeError: Cannot read property 'specifier' of undefined]
      if (VOLUME.test(entry)) {
        // return path.resolve(updatedId);
        return resolvePath(updatedId, resolve)
      }
      return updatedId;
    },
  };
}

上一篇下一篇

猜你喜欢

热点阅读