@aniyajs/rotor
Version:
基于webpack5开发的一款专注于打包、运行的工具
144 lines (129 loc) • 4.37 kB
JavaScript
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
;
const chalk = require("chalk");
const findUp = require("find-up");
const path = require("path");
class ModuleNotFoundPlugin {
constructor(appPath) {
this.appPath = appPath;
this.useYarnCommand = this.useYarnCommand.bind(this);
this.getRelativePath = this.getRelativePath.bind(this);
this.prettierError = this.prettierError.bind(this);
}
useYarnCommand() {
try {
return findUp.sync("yarn.lock", { cwd: this.appPath }) != null;
} catch (_) {
return false;
}
}
getRelativePath(_file) {
let file = path.relative(this.appPath, _file);
if (file.startsWith("..")) {
file = _file;
} else if (!file.startsWith(".")) {
file = "." + path.sep + file;
}
return file;
}
prettierError(err) {
let { details: _details = "", origin } = err;
if (origin == null) {
const caseSensitivity =
err.message &&
/\[CaseSensitivePathsPlugin\] `(.*?)` .* `(.*?)`/.exec(err.message);
if (caseSensitivity) {
const [, incorrectPath, actualName] = caseSensitivity;
const actualFile = this.getRelativePath(
path.join(path.dirname(incorrectPath), actualName),
);
const incorrectName = path.basename(incorrectPath);
err.message = `找不到文件:'${incorrectName}'与磁盘上对应的名称不匹配:'${actualFile}'.`;
}
return err;
}
const file = this.getRelativePath(origin.resource);
let details = _details.split("\n");
const request = /resolve '(.*?)' in '(.*?)'/.exec(details);
if (request) {
const isModule = details[1] && details[1].includes("module");
const isFile = details[1] && details[1].includes("file");
let [, target, context] = request;
context = this.getRelativePath(context);
if (isModule) {
const isYarn = this.useYarnCommand();
details = [
`找不到模块:'${target}'。确保安装了这个包。`,
"",
"你可以运行以下命令来安装这个包:" +
(isYarn
? chalk.bold(`yarn add ${target}`)
: chalk.bold(`npm install ${target}`)) +
".",
];
} else if (isFile) {
details = [`找不到文件'${target}'在'${context}'里面。`];
} else {
details = [err.message];
}
} else {
details = [err.message];
}
err.message = [file, ...details].join("\n").replace("错误:", "");
const isModuleScopePluginError =
err.error && err.error.__module_scope_plugin;
if (isModuleScopePluginError) {
err.message = err.message.replace("没有找到模块:", "");
}
return err;
}
apply(compiler) {
const { prettierError } = this;
compiler.hooks.make.intercept({
register(tap) {
if (!(tap.name === "MultiEntryPlugin" || tap.name === "EntryPlugin")) {
return tap;
}
return Object.assign({}, tap, {
fn: (compilation, callback) => {
tap.fn(compilation, (err, ...args) => {
if (err && err.name === "ModuleNotFoundError") {
err = prettierError(err);
}
callback(err, ...args);
});
},
});
},
});
compiler.hooks.normalModuleFactory.tap("ModuleNotFoundPlugin", (nmf) => {
nmf.hooks.afterResolve.intercept({
register(tap) {
if (tap.name !== "CaseSensitivePathsPlugin") {
return tap;
}
return Object.assign({}, tap, {
fn: (compilation, callback) => {
tap.fn(compilation, (err, ...args) => {
if (
err &&
err.message &&
err.message.includes("CaseSensitivePathsPlugin")
) {
err = prettierError(err);
}
callback(err, ...args);
});
},
});
},
});
});
}
}
module.exports = ModuleNotFoundPlugin;