Repository: tailwindlabs/tailwindcss

Problem statement:
`@tailwindcss/vite` breaks `url()` using `resolve.alias`
<!-- Please provide all of the information requested below. We're a small team and without all of this information it's not possible for us to help and your bug report will be closed. -->

**What version of Tailwind CSS are you using?**

4.0.1

**What build tool (or framework if it abstracts the build tool) are you using?**

Vite 6.0.11 with @tailwindcss/vite 4.0.1

For example: postcss-cli 8.3.1, Next.js 10.0.9, webpack 5.28.0

**What version of Node.js are you using?**

22.13.0

**What browser are you using?**

Chrome

**What operating system are you using?**

Windows

**Reproduction URL**

https://stackblitz.com/edit/vitejs-vite-twabw18q?file=vite.config.ts,src%2Fstyles%2Fstyle.css&terminal=dev

1. Download the project from this button
    ![Image](https://github.com/user-attachments/assets/56ddae73-e21d-44f1-82b4-741e34c650d0) 
2. Run `npm i`
3. Run `npm run dev`
4. Open `http://localhost:5173`
5. The background image is not shown
    ![Image](https://github.com/user-attachments/assets/ce1797fd-230f-4596-bc00-41315c008b8a)

**Describe your issue**

In Vite, I can use alias set with `resolve.alias` in `url()`. For example:
```css
.logo.vanilla {
  background-image: url('~/images/javascript.svg');
}
```
This does not work when `@tailwindcss/vite` is used. (It works when `@tailwind/postcss` is used with Vite)

If you comment out `plugins: [tailwind()],` from `vite.config.ts` in the reproduction, you can see the background image shown, which is the expected behavior.
![Image](https://github.com/user-attachments/assets/9b2e34bb-8a68-4843-b4c1-a015116804fd)


Hints:
Same issue for me

Patch:
diff --git a/packages/@tailwindcss-node/src/urls.ts b/packages/@tailwindcss-node/src/urls.ts
--- a/packages/@tailwindcss-node/src/urls.ts
+++ b/packages/@tailwindcss-node/src/urls.ts
@@ -149,9 +149,12 @@ async function doUrlReplace(
   return `${funcName}(${wrap}${newUrl}${wrap})`
 }
 
-function skipUrlReplacer(rawUrl: string) {
+function skipUrlReplacer(rawUrl: string, aliases?: string[]) {
   return (
-    isExternalUrl(rawUrl) || isDataUrl(rawUrl) || rawUrl[0] === '#' || functionCallRE.test(rawUrl)
+    isExternalUrl(rawUrl) ||
+    isDataUrl(rawUrl) ||
+    !rawUrl[0].match(/[\.a-zA-Z0-9_]/) ||
+    functionCallRE.test(rawUrl)
   )
 }
 


Test patch:
diff --git a/packages/@tailwindcss-node/src/urls.test.ts b/packages/@tailwindcss-node/src/urls.test.ts
--- a/packages/@tailwindcss-node/src/urls.test.ts
+++ b/packages/@tailwindcss-node/src/urls.test.ts
@@ -24,6 +24,20 @@ test('URLs can be rewritten', async () => {
         background: url('/image.jpg');
         background: url("/image.jpg");
 
+        /* Potentially Vite-aliased URLs: ignored */
+        background: url(~/image.jpg);
+        background: url(~/foo/image.jpg);
+        background: url('~/image.jpg');
+        background: url("~/image.jpg");
+        background: url(#/image.jpg);
+        background: url(#/foo/image.jpg);
+        background: url('#/image.jpg');
+        background: url("#/image.jpg");
+        background: url(@/image.jpg);
+        background: url(@/foo/image.jpg);
+        background: url('@/image.jpg');
+        background: url("@/image.jpg");
+
         /* External URL: ignored */
         background: url(http://example.com/image.jpg);
         background: url('http://example.com/image.jpg');
@@ -109,6 +123,18 @@ test('URLs can be rewritten', async () => {
       background: url(/foo/image.jpg);
       background: url('/image.jpg');
       background: url("/image.jpg");
+      background: url(~/image.jpg);
+      background: url(~/foo/image.jpg);
+      background: url('~/image.jpg');
+      background: url("~/image.jpg");
+      background: url(#/image.jpg);
+      background: url(#/foo/image.jpg);
+      background: url('#/image.jpg');
+      background: url("#/image.jpg");
+      background: url(@/image.jpg);
+      background: url(@/foo/image.jpg);
+      background: url('@/image.jpg');
+      background: url("@/image.jpg");
       background: url(http://example.com/image.jpg);
       background: url('http://example.com/image.jpg');
       background: url("http://example.com/image.jpg");