diff --git a/packages/playground/css/index.html b/packages/playground/css/index.html index b2443e6ee9d5d5..c1128b68039047 100644 --- a/packages/playground/css/index.html +++ b/packages/playground/css/index.html @@ -21,6 +21,10 @@

CSS

@import from SASS _index: This should be olive and have bg image

+

+ @import from SASS _index: This should be olive and have bg image which url + contains alias +

@import from SASS _partial: This should be orchid

Imported SASS string:


@@ -29,6 +33,10 @@ 

CSS

@import from Less: This should be darkslateblue and have bg image

+

+ @import from Less: This should be darkslateblue and have bg image which url + contains alias +

Imported Less string:


 
diff --git a/packages/playground/css/nested/_index.scss b/packages/playground/css/nested/_index.scss
index 42306c84934322..6f2103c79fc2c8 100644
--- a/packages/playground/css/nested/_index.scss
+++ b/packages/playground/css/nested/_index.scss
@@ -2,3 +2,8 @@
   color: olive;
   background: url(./icon.png) 10px no-repeat;
 }
+
+.sass-at-import-alias {
+  color: olive;
+  background: url(@/nested/icon.png) 10px no-repeat;
+}
diff --git a/packages/playground/css/nested/nested.less b/packages/playground/css/nested/nested.less
index f6d00613c9e4a1..e4ce110ab73679 100644
--- a/packages/playground/css/nested/nested.less
+++ b/packages/playground/css/nested/nested.less
@@ -2,3 +2,8 @@
   color: darkslateblue;
   background: url(./icon.png) 10px no-repeat;
 }
+
+.less-at-import-alias {
+  color: darkslateblue;
+  background: url(@/nested/icon.png) 10px no-repeat;
+}
diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts
index bc509596d65a73..5afc94e61b762c 100644
--- a/packages/vite/src/node/plugins/css.ts
+++ b/packages/vite/src/node/plugins/css.ts
@@ -36,6 +36,7 @@ import MagicString from 'magic-string'
 import * as Postcss from 'postcss'
 import * as Sass from 'sass'
 import type Less from 'less'
+import { Alias } from 'types/alias'
 
 // const debug = createDebugger('vite:css')
 
@@ -535,6 +536,7 @@ async function compileCSS(
       case 'sass':
         opts = {
           includePaths: ['node_modules'],
+          alias: config.resolve.alias,
           ...opts
         }
         break
@@ -543,6 +545,7 @@ async function compileCSS(
       case 'stylus':
         opts = {
           paths: ['node_modules'],
+          alias: config.resolve.alias,
           ...opts
         }
     }
@@ -848,6 +851,7 @@ type StylePreprocessor = (
     [key: string]: any
     additionalData?: PreprocessorAdditionalData
     filename: string
+    alias: Alias[]
   },
   resolvers: CSSAtImportResolvers
 ) => StylePreprocessorResults | Promise
@@ -886,7 +890,7 @@ const scss: StylePreprocessor = async (source, root, options, resolvers) => {
     importer(url, importer, done) {
       resolvers.sass(url, importer).then((resolved) => {
         if (resolved) {
-          rebaseUrls(resolved, options.filename).then(done)
+          rebaseUrls(resolved, options.filename, options.alias).then(done)
         } else {
           done(null)
         }
@@ -936,7 +940,8 @@ const sass: StylePreprocessor = (source, root, options, aliasResolver) =>
  */
 async function rebaseUrls(
   file: string,
-  rootFile: string
+  rootFile: string,
+  alias: Alias[]
 ): Promise {
   file = path.resolve(file) // ensure os-specific flashes
   // in the same dir, no need to rebase
@@ -952,6 +957,14 @@ async function rebaseUrls(
   }
   const rebased = await rewriteCssUrls(content, (url) => {
     if (url.startsWith('/')) return url
+    // match alias, no need to rewrite
+    for (const { find } of alias) {
+      const matches =
+        typeof find === 'string' ? url.startsWith(find) : find.test(url)
+      if (matches) {
+        return url
+      }
+    }
     const absolute = path.resolve(fileDir, url)
     const relative = path.relative(rootDir, absolute)
     return normalizePath(relative)
@@ -968,6 +981,7 @@ const less: StylePreprocessor = async (source, root, options, resolvers) => {
   const viteResolverPlugin = createViteLessPlugin(
     nodeLess,
     options.filename,
+    options.alias,
     resolvers
   )
   source = await getSource(source, options.filename, options.additionalData)
@@ -1004,16 +1018,23 @@ let ViteLessManager: any
 function createViteLessPlugin(
   less: typeof Less,
   rootFile: string,
+  alias: Alias[],
   resolvers: CSSAtImportResolvers
 ): Less.Plugin {
   if (!ViteLessManager) {
     ViteLessManager = class ViteManager extends less.FileManager {
       resolvers
       rootFile
-      constructor(rootFile: string, resolvers: CSSAtImportResolvers) {
+      alias
+      constructor(
+        rootFile: string,
+        resolvers: CSSAtImportResolvers,
+        alias: Alias[]
+      ) {
         super()
         this.rootFile = rootFile
         this.resolvers = resolvers
+        this.alias = alias
       }
       supports() {
         return true
@@ -1032,7 +1053,7 @@ function createViteLessPlugin(
           path.join(dir, '*')
         )
         if (resolved) {
-          const result = await rebaseUrls(resolved, this.rootFile)
+          const result = await rebaseUrls(resolved, this.rootFile, this.alias)
           let contents
           if (result && 'contents' in result) {
             contents = result.contents
@@ -1052,7 +1073,9 @@ function createViteLessPlugin(
 
   return {
     install(_, pluginManager) {
-      pluginManager.addFileManager(new ViteLessManager(rootFile, resolvers))
+      pluginManager.addFileManager(
+        new ViteLessManager(rootFile, resolvers, alias)
+      )
     },
     minVersion: [3, 0, 0]
   }