简单来说就是 找包的 package.json 判断有没有 exports 字段,用 key 去匹配,如果成功使用exports定义的文件,如没有就回退,找 main 字段
function resolvePackageEntry(id, { dir, data, setResolvedCache, getResolvedCache }, targetWeb, options) {
const { file: idWithoutPostfix, postfix } = splitFileAndPostfix(id);
// 分离文件名和后缀
const cached = getResolvedCache('.', targetWeb);
if (cached) {
return cached + postfix;
}
try {
let entryPoint;
// 预定入口
// resolve exports field with highest priority
// using https://github.com/lukeed/resolve.exports
if (data.exports) {
// 找 exports 是高优先级
entryPoint = resolveExportsOrImports(data, '.', options, targetWeb, 'exports');
}
// fallback to mainFields if still not resolved
if (!entryPoint) {
for (const field of options.mainFields) {
if (field === 'browser') {
if (targetWeb) {
entryPoint = tryResolveBrowserEntry(dir, data, options);
if (entryPoint) {
break;
}
}
}
else if (typeof data[field] === 'string') {
entryPoint = data[field];
break;
}
}
}
entryPoint ||= data.main;
// try default entry when entry is not define
// https://nodejs.org/api/modules.html#all-together
const entryPoints = entryPoint
? [entryPoint]
: ['index.js', 'index.json', 'index.node'];
for (let entry of entryPoints) {
// make sure we don't get scripts when looking for sass
let skipPackageJson = false;
if (options.mainFields[0] === 'sass' &&
!options.extensions.includes(path$o.extname(entry))) {
entry = '';
skipPackageJson = true;
}
else {
// resolve object browser field in package.json
const { browser: browserField } = data;
if (targetWeb &&
options.mainFields.includes('browser') &&
isObject$1(browserField)) {
entry = mapWithBrowserField(entry, browserField) || entry;
}
}
const entryPointPath = path$o.join(dir, entry);
const resolvedEntryPoint = tryFsResolve(entryPointPath, options, true, true, skipPackageJson);
if (resolvedEntryPoint) {
debug$f?.(`[package entry] ${colors$1.cyan(idWithoutPostfix)} -> ${colors$1.dim(resolvedEntryPoint)}${postfix !== '' ? ` (postfix: ${postfix})` : ''}`);
setResolvedCache('.', resolvedEntryPoint, targetWeb);
return resolvedEntryPoint + postfix;
}
}
}
catch (e) {
packageEntryFailure(id, e.message);
}
packageEntryFailure(id);
}
function resolveExportsOrImports(pkg, key, options, targetWeb, type) {
const additionalConditions = new Set(options.overrideConditions || [
'production',
'development',
'module',
...options.conditions,
]);
const conditions = [...additionalConditions].filter((condition) => {
switch (condition) {
case 'production':
return options.isProduction;
case 'development':
return !options.isProduction;
}
return true;
});
const fn = type === 'imports' ? f : o;
const result = fn(pkg, key, {
browser: targetWeb && !additionalConditions.has('node'),
require: options.isRequire && !additionalConditions.has('import'),
conditions,
});
return result ? result[0] : undefined;
}