diff --git a/packages/playground/extensions/__tests__/extensions.spec.ts b/packages/playground/extensions/__tests__/extensions.spec.ts
new file mode 100644
index 00000000000000..42469b78a97ffb
--- /dev/null
+++ b/packages/playground/extensions/__tests__/extensions.spec.ts
@@ -0,0 +1,10 @@
+test('should have no 404s', () => {
+ browserLogs.forEach((msg) => {
+ expect(msg).not.toMatch('404')
+ })
+})
+
+test('not contain `.mjs`', async () => {
+ let appHtml = await page.content()
+ expect(appHtml).toMatch('Hello Vite!')
+})
diff --git a/packages/playground/extensions/index.html b/packages/playground/extensions/index.html
new file mode 100644
index 00000000000000..f9bbcd93f01cb8
--- /dev/null
+++ b/packages/playground/extensions/index.html
@@ -0,0 +1,6 @@
+
Hello Vite!
+
+
diff --git a/packages/playground/extensions/package.json b/packages/playground/extensions/package.json
new file mode 100644
index 00000000000000..08c62477f039d9
--- /dev/null
+++ b/packages/playground/extensions/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "test-extensions",
+ "private": true,
+ "version": "0.0.0",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "debug": "node --inspect-brk ../../vite/bin/vite",
+ "serve": "vite preview"
+ },
+ "dependencies": {
+ "vue": "^3.0.8"
+ }
+}
diff --git a/packages/playground/extensions/vite.config.js b/packages/playground/extensions/vite.config.js
new file mode 100644
index 00000000000000..53c744b71d3637
--- /dev/null
+++ b/packages/playground/extensions/vite.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ resolve: {
+ alias: [{ find: 'vue', replacement: 'vue/dist/vue.esm-bundler.js' }],
+ extensions: ['.js']
+ }
+}
diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts
index 9f7a483e61febe..cc4cd0c5731291 100644
--- a/packages/vite/src/client/client.ts
+++ b/packages/vite/src/client/client.ts
@@ -8,7 +8,8 @@ import {
} from 'types/hmrPayload'
import { CustomEventName } from 'types/customEvent'
import { ErrorOverlay, overlayId } from './overlay'
-import './env'
+// eslint-disable-next-line node/no-missing-import
+import '@vite/env'
// injected by the hmr plugin when served
declare const __ROOT__: string
diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts
index 10318f7de16d7a..88653f135eaad8 100644
--- a/packages/vite/src/node/config.ts
+++ b/packages/vite/src/node/config.ts
@@ -21,7 +21,12 @@ import { ESBuildOptions } from './plugins/esbuild'
import dotenv from 'dotenv'
import dotenvExpand from 'dotenv-expand'
import { Alias, AliasOptions } from 'types/alias'
-import { CLIENT_DIR, DEFAULT_ASSETS_RE } from './constants'
+import {
+ CLIENT_PUBLIC_PATH,
+ CLIENT_ENTRY,
+ ENV_ENTRY,
+ DEFAULT_ASSETS_RE
+} from './constants'
import {
InternalResolveOptions,
ResolveOptions,
@@ -295,13 +300,16 @@ export async function resolveConfig(
config.root ? path.resolve(config.root) : process.cwd()
)
+ const clientAlias = [
+ { find: /^[\/]?@vite\/env/, replacement: () => ENV_ENTRY },
+ { find: CLIENT_PUBLIC_PATH, replacement: () => CLIENT_ENTRY }
+ ]
+
// resolve alias with internal client alias
const resolvedAlias = mergeAlias(
- // #1732 the CLIENT_DIR may contain $$ which cannot be used as direct
- // replacement string.
// @ts-ignore because @rollup/plugin-alias' type doesn't allow function
// replacement, but its implementation does work with function values.
- [{ find: /^\/@vite\//, replacement: () => CLIENT_DIR + '/' }],
+ clientAlias,
config.resolve?.alias || config.alias || []
)