diff --git a/src/node/build/buildPluginResolve.ts b/src/node/build/buildPluginResolve.ts index 9831632c583d7f..2befc9f60cb237 100644 --- a/src/node/build/buildPluginResolve.ts +++ b/src/node/build/buildPluginResolve.ts @@ -14,32 +14,29 @@ export const createBuildResolvePlugin = ( return { name: 'vite:resolve', async resolveId(id: string) { + id = resolver.alias(id) || id if (id === hmrClientId) { return hmrClientId - } else if (id.startsWith('/')) { + } + if (id === 'vue' || id.startsWith('@vue/')) { + const vuePaths = resolveVue(root) + if (id in vuePaths) { + return (vuePaths as any)[id] + } + } + if (id.startsWith('/')) { const resolved = resolver.requestToFile(id) if (await fs.pathExists(resolved)) { debug(id, `-->`, resolved) return resolved } - } else if (id === 'vue' || id.startsWith('@vue/')) { - const vuePaths = resolveVue(root) - if (id in vuePaths) { - return (vuePaths as any)[id] - } } else if (!id.startsWith('.')) { - const request = resolver.idToRequest(id) - if (request) { - const resolved = resolver.requestToFile(request) - debug(id, `-->`, request, `--> `, resolved) - return resolved - } else { - const webModulePath = await resolveWebModule(root, id) - if (webModulePath) { - return webModulePath - } + const webModulePath = await resolveWebModule(root, id) + if (webModulePath) { + return webModulePath } } + // fallback to node-resolve }, load(id: string) { if (id === hmrClientId) { diff --git a/src/node/build/index.ts b/src/node/build/index.ts index c1cfa62882c3df..b1c2869a6db9fe 100644 --- a/src/node/build/index.ts +++ b/src/node/build/index.ts @@ -55,6 +55,7 @@ export async function build(options: BuildConfig = {}): Promise { outDir = path.resolve(root, 'dist'), assetsDir = 'assets', assetsInlineLimit = 4096, + alias = {}, resolvers = [], vueCompilerOptions, rollupInputOptions = {}, @@ -74,7 +75,7 @@ export async function build(options: BuildConfig = {}): Promise { const resolvedAssetsPath = path.join(outDir, assetsDir) const cssFileName = 'style.css' - const resolver = createResolver(root, resolvers) + const resolver = createResolver(root, resolvers, alias) const { htmlPlugin, renderIndex } = await createBuildHtmlPlugin( root, diff --git a/src/node/config.ts b/src/node/config.ts index 6c66067b2414c8..ce11f9dec1d9d1 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -11,6 +11,8 @@ import Rollup, { OutputOptions as RollupOutputOptions } from 'rollup' +export { Resolver } + /** * Options shared between server and build. */ diff --git a/src/node/resolver.ts b/src/node/resolver.ts index fdb0eaabc6d63c..d0e44dd81e2655 100644 --- a/src/node/resolver.ts +++ b/src/node/resolver.ts @@ -11,13 +11,13 @@ import { export interface Resolver { requestToFile(publicPath: string, root: string): string | undefined fileToRequest(filePath: string, root: string): string | undefined - idToRequest?(id: string): string | undefined + alias?(id: string): string | undefined } export interface InternalResolver { requestToFile(publicPath: string): string fileToRequest(filePath: string): string - idToRequest(id: string): string | undefined + alias(id: string): string | undefined } const defaultRequestToFile = (publicPath: string, root: string): string => { @@ -38,12 +38,6 @@ const defaultFileToRequest = (filePath: string, root: string): string => { return `/${slash(path.relative(root, filePath))}` } -const defaultIdToRequest = (id: string) => { - if (id.startsWith('@') && id.indexOf('/') < 0) { - return `/${id}` - } -} - export const supportedExts = ['.js', '.ts', '.jsx', '.tsx', '.json'] const debug = require('debug')('vite:resolve') @@ -78,7 +72,8 @@ const resolveExt = (id: string) => { export function createResolver( root: string, - resolvers: Resolver[] + resolvers: Resolver[], + alias: Record ): InternalResolver { return { requestToFile: (publicPath) => { @@ -103,12 +98,17 @@ export function createResolver( } return defaultFileToRequest(filePath, root) }, - idToRequest: (id: string) => { + alias: (id: string) => { + let aliased: string | undefined = alias[id] + if (aliased) { + return aliased + } for (const r of resolvers) { - const request = r.idToRequest && r.idToRequest(id) - if (request) return request + aliased = r.alias && r.alias(id) + if (aliased) { + return aliased + } } - return defaultIdToRequest(id) } } } diff --git a/src/node/server/index.ts b/src/node/server/index.ts index 7ed390bb712afd..9dcdad9621ff01 100644 --- a/src/node/server/index.ts +++ b/src/node/server/index.ts @@ -39,13 +39,18 @@ const internalPlugins: ServerPlugin[] = [ ] export function createServer(config: ServerConfig = {}): Server { - const { root = process.cwd(), plugins = [], resolvers = [] } = config + const { + root = process.cwd(), + plugins = [], + resolvers = [], + alias = {} + } = config const app = new Koa() const server = http.createServer(app.callback()) const watcher = chokidar.watch(root, { ignored: [/node_modules/] }) as HMRWatcher - const resolver = createResolver(root, resolvers) + const resolver = createResolver(root, resolvers, alias) const context = { root, app, diff --git a/src/node/utils/pathUtils.ts b/src/node/utils/pathUtils.ts index ec89c3139cfe91..06cbe29a984ead 100644 --- a/src/node/utils/pathUtils.ts +++ b/src/node/utils/pathUtils.ts @@ -50,7 +50,7 @@ export const isImportRequest = (ctx: Context): boolean => { return jsSrcFileRE.test(referer) } -const moduleRE = /^[^\/\.]/ +const bareImportRE = /^[^\/\.]/ const fileExtensionRE = /\.\w+$/ export const resolveImport = ( @@ -59,8 +59,9 @@ export const resolveImport = ( resolver: InternalResolver, timestamp?: string ): string => { - if (moduleRE.test(id)) { - return resolver.idToRequest(id) || `/@modules/${id}` + id = resolver.alias(id) || id + if (bareImportRE.test(id)) { + return `/@modules/${id}` } else { let { pathname, query } = resolveRelativeRequest(importer, id) // append an extension to extension-less imports