Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Nuxt integration #14319

Merged
merged 4 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Ensure content globs defined in `@config` files are relative to that file ([#14314](https://github.com/tailwindlabs/tailwindcss/pull/14314))
- Ensure CSS `theme()` functions are evaluated in media query ranges with collapsed whitespace ((#14321)[https://github.com/tailwindlabs/tailwindcss/pull/14321])
- Fix support for Nuxt projects in the Vite plugin (requires Nuxt 3.13.1+) ([#14319](https://github.com/tailwindlabs/tailwindcss/pull/14319))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not happy about this line but if we want to mention the improved Nuxt support we should mention the version number, otherwise people try it and it won't work 😢

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me tbh


## [4.0.0-alpha.21] - 2024-09-02

Expand Down
64 changes: 64 additions & 0 deletions integrations/vite/nuxt.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { expect } from 'vitest'
import { candidate, css, fetchStyles, html, json, retryAssertion, test, ts } from '../utils'

test(
'dev mode',
{
fs: {
'package.json': json`
{
"type": "module",
"dependencies": {
"@tailwindcss/vite": "workspace:^",
"nuxt": "^3.13.1",
"tailwindcss": "workspace:^",
"vue": "latest"
}
}
`,
'nuxt.config.ts': ts`
import tailwindcss from '@tailwindcss/vite'

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
vite: {
plugins: [tailwindcss()],
},

css: ['~/assets/css/main.css'],
devtools: { enabled: true },
compatibilityDate: '2024-08-30',
})
`,
'app.vue': html`
<template>
<div class="underline">Hello world!</div>
</template>
`,
'assets/css/main.css': css`@import 'tailwindcss';`,
},
},
async ({ fs, spawn, getFreePort }) => {
let port = await getFreePort()
await spawn(`pnpm nuxt dev --port ${port}`)

await retryAssertion(async () => {
let css = await fetchStyles(port)
expect(css).toContain(candidate`underline`)
})

await fs.write(
'app.vue',
html`
<template>
<div class="underline font-bold">Hello world!</div>
</template>
`,
)
await retryAssertion(async () => {
let css = await fetchStyles(port)
expect(css).toContain(candidate`underline`)
expect(css).toContain(candidate`font-bold`)
})
},
)
63 changes: 31 additions & 32 deletions packages/@tailwindcss-vite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import postcssImport from 'postcss-import'
import type { Plugin, ResolvedConfig, Rollup, Update, ViteDevServer } from 'vite'

export default function tailwindcss(): Plugin[] {
let server: ViteDevServer | null = null
let servers: ViteDevServer[] = []
let config: ResolvedConfig | null = null

let isSSR = false
Expand Down Expand Up @@ -58,36 +58,35 @@ export default function tailwindcss(): Plugin[] {
}

function invalidateAllRoots(isSSR: boolean) {
// If we're building then we don't need to update anything
if (!server) return

let updates: Update[] = []
for (let id of roots.keys()) {
let module = server.moduleGraph.getModuleById(id)
if (!module) {
// Note: Removing this during SSR is not safe and will produce
// inconsistent results based on the timing of the removal and
// the order / timing of transforms.
if (!isSSR) {
// It is safe to remove the item here since we're iterating on a copy
// of the keys.
roots.delete(id)
for (let server of servers) {
let updates: Update[] = []
for (let id of roots.keys()) {
let module = server.moduleGraph.getModuleById(id)
if (!module) {
// Note: Removing this during SSR is not safe and will produce
// inconsistent results based on the timing of the removal and
// the order / timing of transforms.
if (!isSSR) {
// It is safe to remove the item here since we're iterating on a copy
// of the keys.
roots.delete(id)
}
continue
}
continue
}

roots.get(id).requiresRebuild = false
server.moduleGraph.invalidateModule(module)
updates.push({
type: `${module.type}-update`,
path: module.url,
acceptedPath: module.url,
timestamp: Date.now(),
})
}
roots.get(id).requiresRebuild = false
server.moduleGraph.invalidateModule(module)
updates.push({
type: `${module.type}-update`,
path: module.url,
acceptedPath: module.url,
timestamp: Date.now(),
})
}

if (updates.length > 0) {
server.hot.send({ type: 'update', updates })
if (updates.length > 0) {
server.hot.send({ type: 'update', updates })
}
}
}

Expand Down Expand Up @@ -139,8 +138,8 @@ export default function tailwindcss(): Plugin[] {
name: '@tailwindcss/vite:scan',
enforce: 'pre',

configureServer(_server) {
server = _server
configureServer(server) {
servers.push(server)
},

async configResolved(_config) {
Expand Down Expand Up @@ -169,7 +168,7 @@ export default function tailwindcss(): Plugin[] {
},
transform(src, id, options) {
let extension = getExtension(id)
if (extension === '' || extension === 'css') return
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an optimization that makes sure vite <style> blocks aren't scanned for candidates in addition to css files.

if (isPotentialCssRootFile(id)) return
scanFile(id, src, extension, options?.ssr ?? false)
},
},
Expand All @@ -193,7 +192,7 @@ export default function tailwindcss(): Plugin[] {
// The reason why we can not rely on the invalidation here is that the
// users would otherwise see a flicker in the styles as the CSS might
// be loaded with an invalid set of candidates first.
await server?.waitForRequestsIdle?.(id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to bump the minimum Vite version to the one where waitForRequestsIdle was introduced if it's not already btw.

await Promise.all(servers.map((server) => server.waitForRequestsIdle(id)))
}

let generated = await root.generate(src, (file) => this.addWatchFile(file))
Expand Down