| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- "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
|