核心代码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 };
});
importer和updatedId的路径替换
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;
}