mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-08 09:27:19 +08:00
484 lines
20 KiB
JavaScript
484 lines
20 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.resolveNodeModuleFile = exports.resolveNodeModule = exports.resolveOptimizedModule = exports.resolveBareModuleRequest = exports.jsSrcRE = exports.createResolver = exports.mainFields = exports.supportedExts = void 0;
|
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
const path_1 = __importDefault(require("path"));
|
|
const slash_1 = __importDefault(require("slash"));
|
|
const utils_1 = require("./utils");
|
|
const serverPluginModuleResolve_1 = require("./server/serverPluginModuleResolve");
|
|
const optimizer_1 = require("./optimizer");
|
|
const serverPluginClient_1 = require("./server/serverPluginClient");
|
|
const cssUtils_1 = require("./utils/cssUtils");
|
|
const pathUtils_1 = require("./utils/pathUtils");
|
|
const chalk_1 = __importDefault(require("chalk"));
|
|
const debug = require('debug')('vite:resolve');
|
|
const isWin = require('os').platform() === 'win32';
|
|
const pathSeparator = isWin ? '\\' : '/';
|
|
exports.supportedExts = ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'];
|
|
exports.mainFields = ['module', 'jsnext', 'jsnext:main', 'browser', 'main'];
|
|
const defaultRequestToFile = (publicPath, root) => {
|
|
if (serverPluginModuleResolve_1.moduleRE.test(publicPath)) {
|
|
const id = publicPath.replace(serverPluginModuleResolve_1.moduleRE, '');
|
|
const cachedNodeModule = serverPluginModuleResolve_1.moduleIdToFileMap.get(id);
|
|
if (cachedNodeModule) {
|
|
return cachedNodeModule;
|
|
}
|
|
// try to resolve from optimized modules
|
|
const optimizedModule = resolveOptimizedModule(root, id);
|
|
if (optimizedModule) {
|
|
return optimizedModule;
|
|
}
|
|
// try to resolve from normal node_modules
|
|
const nodeModule = resolveNodeModuleFile(root, id);
|
|
if (nodeModule) {
|
|
serverPluginModuleResolve_1.moduleIdToFileMap.set(id, nodeModule);
|
|
return nodeModule;
|
|
}
|
|
}
|
|
const publicDirPath = path_1.default.join(root, 'public', publicPath.slice(1));
|
|
if (fs_extra_1.default.existsSync(publicDirPath)) {
|
|
return publicDirPath;
|
|
}
|
|
return path_1.default.join(root, publicPath.slice(1));
|
|
};
|
|
const defaultFileToRequest = (filePath, root) => serverPluginModuleResolve_1.moduleFileToIdMap.get(filePath) ||
|
|
'/' + slash_1.default(path_1.default.relative(root, filePath)).replace(/^public\//, '');
|
|
const isFile = (file) => {
|
|
try {
|
|
return fs_extra_1.default.statSync(file).isFile();
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
/**
|
|
* this function resolve fuzzy file path. examples:
|
|
* /path/file is a fuzzy file path for /path/file.tsx
|
|
* /path/dir is a fuzzy file path for /path/dir/index.js
|
|
*
|
|
* returning undefined indicates the filePath is not fuzzy:
|
|
* it is already an exact file path, or it can't match any file
|
|
*/
|
|
const resolveFilePathPostfix = (filePath) => {
|
|
const cleanPath = utils_1.cleanUrl(filePath);
|
|
if (!isFile(cleanPath)) {
|
|
let postfix = '';
|
|
for (const ext of exports.supportedExts) {
|
|
if (isFile(cleanPath + ext)) {
|
|
postfix = ext;
|
|
break;
|
|
}
|
|
const defaultFilePath = `/index${ext}`;
|
|
if (isFile(path_1.default.join(cleanPath, defaultFilePath))) {
|
|
postfix = defaultFilePath;
|
|
break;
|
|
}
|
|
}
|
|
const queryMatch = filePath.match(/\?.*$/);
|
|
const query = queryMatch ? queryMatch[0] : '';
|
|
const resolved = cleanPath + postfix + query;
|
|
if (resolved !== filePath) {
|
|
debug(`(postfix) ${filePath} -> ${resolved}`);
|
|
return postfix;
|
|
}
|
|
}
|
|
};
|
|
const isDir = (p) => fs_extra_1.default.existsSync(p) && fs_extra_1.default.statSync(p).isDirectory();
|
|
function createResolver(root, resolvers = [], userAlias = {}, assetsInclude) {
|
|
resolvers = [...resolvers];
|
|
const literalAlias = {};
|
|
const literalDirAlias = {};
|
|
const resolveAlias = (alias) => {
|
|
for (const key in alias) {
|
|
let target = alias[key];
|
|
// aliasing a directory
|
|
if (key.startsWith('/') && key.endsWith('/') && path_1.default.isAbsolute(target)) {
|
|
// check first if this is aliasing to a path from root
|
|
const fromRoot = path_1.default.join(root, target);
|
|
if (isDir(fromRoot)) {
|
|
target = fromRoot;
|
|
}
|
|
else if (!isDir(target)) {
|
|
continue;
|
|
}
|
|
resolvers.push({
|
|
requestToFile(publicPath) {
|
|
if (publicPath.startsWith(key)) {
|
|
return path_1.default.join(target, publicPath.slice(key.length));
|
|
}
|
|
},
|
|
fileToRequest(filePath) {
|
|
if (filePath.startsWith(target + pathSeparator)) {
|
|
return slash_1.default(key + path_1.default.relative(target, filePath));
|
|
}
|
|
}
|
|
});
|
|
literalDirAlias[key] = target;
|
|
}
|
|
else {
|
|
literalAlias[key] = target;
|
|
}
|
|
}
|
|
};
|
|
resolvers.forEach(({ alias }) => {
|
|
if (alias && typeof alias === 'object') {
|
|
resolveAlias(alias);
|
|
}
|
|
});
|
|
resolveAlias(userAlias);
|
|
const requestToFileCache = new Map();
|
|
const fileToRequestCache = new Map();
|
|
const resolver = {
|
|
requestToFile(publicPath) {
|
|
publicPath = decodeURIComponent(publicPath);
|
|
if (requestToFileCache.has(publicPath)) {
|
|
return requestToFileCache.get(publicPath);
|
|
}
|
|
let resolved;
|
|
for (const r of resolvers) {
|
|
const filepath = r.requestToFile && r.requestToFile(publicPath, root);
|
|
if (filepath) {
|
|
resolved = filepath;
|
|
break;
|
|
}
|
|
}
|
|
if (!resolved) {
|
|
resolved = defaultRequestToFile(publicPath, root);
|
|
}
|
|
const postfix = resolveFilePathPostfix(resolved);
|
|
if (postfix) {
|
|
if (postfix[0] === '/') {
|
|
resolved = path_1.default.join(resolved, postfix);
|
|
}
|
|
else {
|
|
resolved += postfix;
|
|
}
|
|
}
|
|
requestToFileCache.set(publicPath, resolved);
|
|
return resolved;
|
|
},
|
|
fileToRequest(filePath) {
|
|
if (fileToRequestCache.has(filePath)) {
|
|
return fileToRequestCache.get(filePath);
|
|
}
|
|
for (const r of resolvers) {
|
|
const request = r.fileToRequest && r.fileToRequest(filePath, root);
|
|
if (request)
|
|
return request;
|
|
}
|
|
const res = defaultFileToRequest(filePath, root);
|
|
fileToRequestCache.set(filePath, res);
|
|
return res;
|
|
},
|
|
/**
|
|
* Given a fuzzy public path, resolve missing extensions and /index.xxx
|
|
*/
|
|
normalizePublicPath(publicPath) {
|
|
if (publicPath === serverPluginClient_1.clientPublicPath) {
|
|
return publicPath;
|
|
}
|
|
// preserve query
|
|
const queryMatch = publicPath.match(/\?.*$/);
|
|
const query = queryMatch ? queryMatch[0] : '';
|
|
const cleanPublicPath = utils_1.cleanUrl(publicPath);
|
|
const finalize = (result) => {
|
|
result += query;
|
|
if (resolver.requestToFile(result) !== resolver.requestToFile(publicPath)) {
|
|
throw new Error(`[vite] normalizePublicPath check fail. please report to vite.`);
|
|
}
|
|
return result;
|
|
};
|
|
if (!serverPluginModuleResolve_1.moduleRE.test(cleanPublicPath)) {
|
|
return finalize(resolver.fileToRequest(resolver.requestToFile(cleanPublicPath)));
|
|
}
|
|
const filePath = resolver.requestToFile(cleanPublicPath);
|
|
const cacheDir = optimizer_1.resolveOptimizedCacheDir(root);
|
|
if (cacheDir) {
|
|
const relative = path_1.default.relative(cacheDir, filePath);
|
|
if (!relative.startsWith('..')) {
|
|
return finalize(path_1.default.posix.join('/@modules/', slash_1.default(relative)));
|
|
}
|
|
}
|
|
// fileToRequest doesn't work with files in node_modules
|
|
// because of edge cases like symlinks or yarn-aliased-install
|
|
// or even aliased-symlinks
|
|
// example id: "@babel/runtime/helpers/esm/slicedToArray"
|
|
// see the test case: /playground/TestNormalizePublicPath.vue
|
|
const id = cleanPublicPath.replace(serverPluginModuleResolve_1.moduleRE, '');
|
|
const { scope, name, inPkgPath } = utils_1.parseNodeModuleId(id);
|
|
if (!inPkgPath)
|
|
return publicPath;
|
|
let filePathPostFix = '';
|
|
let findPkgFrom = filePath;
|
|
while (!filePathPostFix.startsWith(inPkgPath)) {
|
|
// some package contains multi package.json...
|
|
// for example: @babel/runtime@7.10.2/helpers/esm/package.json
|
|
const pkgPath = utils_1.lookupFile(findPkgFrom, ['package.json'], true);
|
|
if (!pkgPath) {
|
|
throw new Error(`[vite] can't find package.json for a node_module file: ` +
|
|
`"${publicPath}". something is wrong.`);
|
|
}
|
|
filePathPostFix = slash_1.default(path_1.default.relative(path_1.default.dirname(pkgPath), filePath));
|
|
findPkgFrom = path_1.default.join(path_1.default.dirname(pkgPath), '../');
|
|
}
|
|
return finalize(['/@modules', scope, name, filePathPostFix].filter(Boolean).join('/'));
|
|
},
|
|
alias(id) {
|
|
let aliased = literalAlias[id];
|
|
if (aliased) {
|
|
return aliased;
|
|
}
|
|
for (const { alias } of resolvers) {
|
|
aliased = alias && typeof alias === 'function' ? alias(id) : undefined;
|
|
if (aliased) {
|
|
return aliased;
|
|
}
|
|
}
|
|
},
|
|
resolveRelativeRequest(importer, importee) {
|
|
const queryMatch = importee.match(utils_1.queryRE);
|
|
let resolved = importee;
|
|
if (importee.startsWith('.')) {
|
|
resolved = path_1.default.posix.resolve(path_1.default.posix.dirname(importer), importee);
|
|
for (const alias in literalDirAlias) {
|
|
if (importer.startsWith(alias)) {
|
|
if (!resolved.startsWith(alias)) {
|
|
// resolved path is outside of alias directory, we need to use
|
|
// its full path instead
|
|
const importerFilePath = resolver.requestToFile(importer);
|
|
const importeeFilePath = path_1.default.resolve(path_1.default.dirname(importerFilePath), importee);
|
|
resolved = resolver.fileToRequest(importeeFilePath);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
pathname: utils_1.cleanUrl(resolved) +
|
|
// path resolve strips ending / which should be preserved
|
|
(importee.endsWith('/') && !resolved.endsWith('/') ? '/' : ''),
|
|
query: queryMatch ? queryMatch[0] : ''
|
|
};
|
|
},
|
|
isPublicRequest(publicPath) {
|
|
return resolver
|
|
.requestToFile(publicPath)
|
|
.startsWith(path_1.default.resolve(root, 'public'));
|
|
},
|
|
isAssetRequest(filePath) {
|
|
return ((assetsInclude && assetsInclude(filePath)) || pathUtils_1.isStaticAsset(filePath));
|
|
}
|
|
};
|
|
return resolver;
|
|
}
|
|
exports.createResolver = createResolver;
|
|
exports.jsSrcRE = /\.(?:(?:j|t)sx?|vue)$|\.mjs$/;
|
|
const deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\//;
|
|
/**
|
|
* Redirects a bare module request to a full path under /@modules/
|
|
* It resolves a bare node module id to its full entry path so that relative
|
|
* imports from the entry can be correctly resolved.
|
|
* e.g.:
|
|
* - `import 'foo'` -> `import '/@modules/foo/dist/index.js'`
|
|
* - `import 'foo/bar/baz'` -> `import '/@modules/foo/bar/baz.js'`
|
|
*/
|
|
function resolveBareModuleRequest(root, id, importer, resolver) {
|
|
const optimized = resolveOptimizedModule(root, id);
|
|
if (optimized) {
|
|
// ensure optimized module requests always ends with `.js` - this is because
|
|
// optimized deps may import one another and in the built bundle their
|
|
// relative import paths ends with `.js`. If we don't append `.js` during
|
|
// rewrites, it may result in duplicated copies of the same dep.
|
|
return path_1.default.extname(id) === '.js' ? id : id + '.js';
|
|
}
|
|
let isEntry = false;
|
|
const basedir = path_1.default.dirname(resolver.requestToFile(importer));
|
|
const pkgInfo = resolveNodeModule(basedir, id, resolver);
|
|
if (pkgInfo) {
|
|
if (!pkgInfo.entry) {
|
|
console.error(chalk_1.default.yellow(`[vite] dependency ${id} does not have default entry defined in package.json.`));
|
|
}
|
|
else {
|
|
isEntry = true;
|
|
id = pkgInfo.entry;
|
|
}
|
|
}
|
|
if (!isEntry) {
|
|
const deepMatch = !isEntry && id.match(deepImportRE);
|
|
if (deepMatch) {
|
|
// deep import
|
|
const depId = deepMatch[1] || deepMatch[2];
|
|
// check if this is a deep import to an optimized dep.
|
|
if (resolveOptimizedModule(root, depId)) {
|
|
if (resolver.alias(depId) === id) {
|
|
// this is a deep import but aliased from a bare module id.
|
|
// redirect it the optimized copy.
|
|
return resolveBareModuleRequest(root, depId, importer, resolver);
|
|
}
|
|
if (!cssUtils_1.isCSSRequest(id) && !resolver.isAssetRequest(id)) {
|
|
// warn against deep imports to optimized dep
|
|
console.error(chalk_1.default.yellow(`\n[vite] Avoid deep import "${id}" (imported by ${importer})\n` +
|
|
`because "${depId}" has been pre-optimized by vite into a single file.\n` +
|
|
`Prefer importing directly from the module entry:\n` +
|
|
chalk_1.default.cyan(`\n import { ... } from "${depId}" \n\n`) +
|
|
`If the dependency requires deep import to function properly, \n` +
|
|
`add the deep path to ${chalk_1.default.cyan(`optimizeDeps.include`)} in vite.config.js.\n`));
|
|
}
|
|
}
|
|
// resolve ext for deepImport
|
|
const filePath = resolveNodeModuleFile(root, id);
|
|
if (filePath) {
|
|
const deepPath = id.replace(deepImportRE, '');
|
|
const normalizedFilePath = slash_1.default(filePath);
|
|
const postfix = normalizedFilePath.slice(normalizedFilePath.lastIndexOf(deepPath) + deepPath.length);
|
|
id += postfix;
|
|
}
|
|
}
|
|
}
|
|
// check and warn deep imports on optimized modules
|
|
const ext = path_1.default.extname(id);
|
|
if (!exports.jsSrcRE.test(ext)) {
|
|
// append import query for non-js deep imports
|
|
return id + (utils_1.queryRE.test(id) ? '&import' : '?import');
|
|
}
|
|
else {
|
|
return id;
|
|
}
|
|
}
|
|
exports.resolveBareModuleRequest = resolveBareModuleRequest;
|
|
const viteOptimizedMap = new Map();
|
|
function resolveOptimizedModule(root, id) {
|
|
const cacheKey = `${root}#${id}`;
|
|
const cached = viteOptimizedMap.get(cacheKey);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
const cacheDir = optimizer_1.resolveOptimizedCacheDir(root);
|
|
if (!cacheDir)
|
|
return;
|
|
const tryResolve = (file) => {
|
|
file = path_1.default.join(cacheDir, file);
|
|
if (fs_extra_1.default.existsSync(file) && fs_extra_1.default.statSync(file).isFile()) {
|
|
viteOptimizedMap.set(cacheKey, file);
|
|
return file;
|
|
}
|
|
};
|
|
return tryResolve(id) || tryResolve(id + '.js');
|
|
}
|
|
exports.resolveOptimizedModule = resolveOptimizedModule;
|
|
const nodeModulesInfoMap = new Map();
|
|
const nodeModulesFileMap = new Map();
|
|
function resolveNodeModule(root, id, resolver) {
|
|
const cacheKey = `${root}#${id}`;
|
|
const cached = nodeModulesInfoMap.get(cacheKey);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
let pkgPath;
|
|
try {
|
|
// see if the id is a valid package name
|
|
pkgPath = utils_1.resolveFrom(root, `${id}/package.json`);
|
|
}
|
|
catch (e) {
|
|
debug(`failed to resolve package.json for ${id}`);
|
|
}
|
|
if (pkgPath) {
|
|
// if yes, this is a entry import. resolve entry file
|
|
let pkg;
|
|
try {
|
|
pkg = fs_extra_1.default.readJSONSync(pkgPath);
|
|
}
|
|
catch (e) {
|
|
return;
|
|
}
|
|
let entryPoint;
|
|
// TODO properly support conditional exports
|
|
// https://nodejs.org/api/esm.html#esm_conditional_exports
|
|
// Note: this would require @rollup/plugin-node-resolve to support it too
|
|
// or we will have to implement that logic in vite's own resolve plugin.
|
|
if (!entryPoint) {
|
|
for (const field of exports.mainFields) {
|
|
if (typeof pkg[field] === 'string') {
|
|
entryPoint = pkg[field];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!entryPoint) {
|
|
entryPoint = 'index.js';
|
|
}
|
|
// resolve object browser field in package.json
|
|
// https://github.com/defunctzombie/package-browser-field-spec
|
|
const { browser: browserField } = pkg;
|
|
if (entryPoint && browserField && typeof browserField === 'object') {
|
|
entryPoint = mapWithBrowserField(entryPoint, browserField);
|
|
}
|
|
debug(`(node_module entry) ${id} -> ${entryPoint}`);
|
|
// save resolved entry file path using the deep import path as key
|
|
// e.g. foo/dist/foo.js
|
|
// this is the path raw imports will be rewritten to, and is what will
|
|
// be passed to resolveNodeModuleFile().
|
|
let entryFilePath;
|
|
// respect user manual alias
|
|
const aliased = resolver.alias(id);
|
|
if (aliased && aliased !== id) {
|
|
entryFilePath = resolveNodeModuleFile(root, aliased);
|
|
}
|
|
if (!entryFilePath && entryPoint) {
|
|
// #284 some packages specify entry without extension...
|
|
entryFilePath = path_1.default.join(path_1.default.dirname(pkgPath), entryPoint);
|
|
const postfix = resolveFilePathPostfix(entryFilePath);
|
|
if (postfix) {
|
|
entryPoint += postfix;
|
|
entryFilePath += postfix;
|
|
}
|
|
entryPoint = path_1.default.posix.join(id, entryPoint);
|
|
// save the resolved file path now so we don't need to do it again in
|
|
// resolveNodeModuleFile()
|
|
nodeModulesFileMap.set(entryPoint, entryFilePath);
|
|
}
|
|
const result = {
|
|
entry: entryPoint,
|
|
entryFilePath,
|
|
pkg
|
|
};
|
|
nodeModulesInfoMap.set(cacheKey, result);
|
|
return result;
|
|
}
|
|
}
|
|
exports.resolveNodeModule = resolveNodeModule;
|
|
function resolveNodeModuleFile(root, id) {
|
|
const cacheKey = `${root}#${id}`;
|
|
const cached = nodeModulesFileMap.get(cacheKey);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
try {
|
|
const resolved = utils_1.resolveFrom(root, id);
|
|
nodeModulesFileMap.set(cacheKey, resolved);
|
|
return resolved;
|
|
}
|
|
catch (e) {
|
|
// error will be reported downstream
|
|
}
|
|
}
|
|
exports.resolveNodeModuleFile = resolveNodeModuleFile;
|
|
const normalize = path_1.default.posix.normalize;
|
|
/**
|
|
* given a relative path in pkg dir,
|
|
* return a relative path in pkg dir,
|
|
* mapped with the "map" object
|
|
*/
|
|
function mapWithBrowserField(relativePathInPkgDir, map) {
|
|
const normalized = normalize(relativePathInPkgDir);
|
|
const foundEntry = Object.entries(map).find(([from]) => normalize(from) === normalized);
|
|
if (!foundEntry) {
|
|
return normalized;
|
|
}
|
|
const [, to] = foundEntry;
|
|
return normalize(to);
|
|
}
|
|
//# sourceMappingURL=resolver.js.map
|