Skip to content

Commit 9d42549

Browse files
committed
fix(viewer): provide workaround for nuxt2 modules:done serverMiddleware race condition
1 parent 98296a8 commit 9d42549

File tree

3 files changed

+28
-14
lines changed

3 files changed

+28
-14
lines changed

src/context.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ twCtx.tryUse = () => {
2626
}
2727
twCtx.set = (instance, replace = true) => {
2828
const resolvedConfig = instance && resolveConfig(instance)
29+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
2930
resolvedConfig && useNuxt().callHook('tailwindcss:resolvedConfig', resolvedConfig, twCtx.tryUse() ?? undefined)
3031

3132
set(resolvedConfig as unknown as TWConfig, replace)
@@ -179,13 +180,13 @@ const createInternalContext = async (moduleOptions: ModuleOptions, nuxt = useNux
179180
}).filter(Boolean)
180181

181182
return [
182-
`// generated by the @nuxtjs/tailwindcss <https://github.com/nuxt-modules/tailwindcss> module at ${(new Date()).toLocaleString()}`,
183-
`const configMerger = require(${JSON.stringify(createResolver(import.meta.url).resolve('./runtime/merger.js'))});`,
184-
`\nconst inlineConfig = ${serializeConfig(moduleOptions.config as Partial<TWConfig>)};\n`,
185-
'const config = [',
186-
layerConfigs.join(',\n'),
187-
`].reduce((prev, curr) => configMerger(curr, prev), configMerger(inlineConfig, { content: { files: ${JSON.stringify(contentPaths)} } }));\n`,
188-
`module.exports = ${configUpdatedHook['main-config'] ? `(() => {const cfg=config;${configUpdatedHook['main-config']};return cfg;})()` : 'config'}\n`,
183+
`// generated by the @nuxtjs/tailwindcss <https://github.com/nuxt-modules/tailwindcss> module at ${(new Date()).toLocaleString()}`,
184+
`const configMerger = require(${JSON.stringify(createResolver(import.meta.url).resolve('./runtime/merger.js'))});`,
185+
`\nconst inlineConfig = ${serializeConfig(moduleOptions.config as Partial<TWConfig>)};\n`,
186+
'const config = [',
187+
layerConfigs.join(',\n'),
188+
`].reduce((prev, curr) => configMerger(curr, prev), configMerger(inlineConfig, { content: { files: ${JSON.stringify(contentPaths)} } }));\n`,
189+
`module.exports = ${configUpdatedHook['main-config'] ? `(() => {const cfg=config;${configUpdatedHook['main-config']};return cfg;})()` : 'config'}\n`,
189190
].join('\n')
190191
},
191192
})
@@ -208,10 +209,12 @@ const createInternalContext = async (moduleOptions: ModuleOptions, nuxt = useNux
208209
nuxt.hook('tailwindcss:internal:regenerateTemplates', (data) => {
209210
if (!data || !data.configTemplateUpdated) return
210211
const configFile = server.moduleGraph.getModuleById(configResolvedPath)
212+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
211213
configFile && server.moduleGraph.invalidateModule(configFile)
212214
})
213215
})
214216

217+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
215218
moduleOptions.exposeConfig && nuxt.hook('builder:watch', async (_, path) => {
216219
if (configPaths.includes(join(nuxt.options.rootDir, path))) {
217220
twCtx.set(_loadConfig(configResolvedPath))

src/module.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import { joinURL } from 'ufo'
33
import {
44
defineNuxtModule,
55
installModule,
6-
isNuxt2,
76
getNuxtVersion,
87
resolvePath,
98
useNuxt,
109
createResolver,
1110
addImports,
1211
updateTemplates,
1312
addTemplate,
13+
isNuxtMajorVersion,
1414
} from '@nuxt/kit'
1515

1616
// @ts-expect-error no declaration file
@@ -69,7 +69,7 @@ export default defineNuxtModule<ModuleOptions>({
6969
if (moduleOptions.editorSupport || moduleOptions.addTwUtil) {
7070
const editorSupportConfig = resolvers.resolveEditorSupportConfig(moduleOptions.editorSupport)
7171

72-
if ((editorSupportConfig.autocompleteUtil || moduleOptions.addTwUtil) && !isNuxt2()) {
72+
if ((editorSupportConfig.autocompleteUtil || moduleOptions.addTwUtil) && !isNuxtMajorVersion(2, nuxt)) {
7373
addImports({
7474
name: 'autocompleteUtil',
7575
from: createResolver(import.meta.url).resolve('./runtime/utils'),
@@ -100,12 +100,17 @@ export default defineNuxtModule<ModuleOptions>({
100100
nuxt.options.css.splice(injectPosition, 0, resolvedCss)
101101
}
102102

103+
// workaround for nuxt2 middleware race condition
104+
let nuxt2ViewerConfig: Parameters<typeof setupViewer>[0] = join(nuxt.options.buildDir, 'tailwind.config.cjs')
105+
103106
nuxt.hook('modules:done', async () => {
104107
const _config = await ctx.loadConfig()
105108

106109
const twConfig = ctx.generateConfig()
107110
ctx.registerHooks()
108111

112+
nuxt2ViewerConfig = twConfig.dst || _config
113+
109114
// expose resolved tailwind config as an alias
110115
if (moduleOptions.exposeConfig) {
111116
const exposeConfig = resolvers.resolveExposeConfig({ level: moduleOptions.exposeLevel, ...(typeof moduleOptions.exposeConfig === 'object' ? moduleOptions.exposeConfig : {}) })
@@ -128,7 +133,7 @@ export default defineNuxtModule<ModuleOptions>({
128133
}
129134

130135
// enabled only in development
131-
if (nuxt.options.dev) {
136+
if (nuxt.options.dev && !isNuxtMajorVersion(2, nuxt)) {
132137
// add tailwind-config-viewer endpoint
133138
if (moduleOptions.viewer) {
134139
const viewerConfig = resolvers.resolveViewerConfig(moduleOptions.viewer)
@@ -150,13 +155,20 @@ export default defineNuxtModule<ModuleOptions>({
150155
}
151156
else {
152157
// production only
158+
if (!nuxt.options.dev) return
159+
153160
if (moduleOptions.viewer) {
154161
const viewerConfig = resolvers.resolveViewerConfig(moduleOptions.viewer)
155162

156163
exportViewer(twConfig.dst || addTemplate({ filename: 'tailwind.config/viewer-config.cjs', getContents: () => `module.exports = ${JSON.stringify(_config)}`, write: true }).dst, viewerConfig)
157164
}
158165
}
159166
})
167+
168+
if (nuxt.options.dev && moduleOptions.viewer && isNuxtMajorVersion(2, nuxt)) {
169+
const viewerConfig = resolvers.resolveViewerConfig(moduleOptions.viewer)
170+
setupViewer(nuxt2ViewerConfig, viewerConfig, nuxt)
171+
}
160172
},
161173
})
162174

src/viewer.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { colors } from 'consola/utils'
22
import { eventHandler, sendRedirect, H3Event } from 'h3'
3-
import { addDevServerHandler, isNuxt2, isNuxt3, useNuxt } from '@nuxt/kit'
3+
import { addDevServerHandler, isNuxtMajorVersion, useNuxt } from '@nuxt/kit'
44
import { withTrailingSlash, withoutTrailingSlash, joinURL, cleanDoubleSlashes } from 'ufo'
55
import loadConfig from 'tailwindcss/loadConfig.js'
66
import { relative } from 'pathe'
@@ -15,7 +15,7 @@ export const setupViewer = async (twConfig: string | TWConfig, config: ViewerCon
1515
const viewerServer = (await import('tailwind-config-viewer/server/index.js').then(r => r.default || r))({ tailwindConfigProvider: typeof twConfig === 'string' ? () => loadConfig(twConfig) : () => twConfig }).asMiddleware()
1616
const viewerDevMiddleware = eventHandler(event => viewerServer(event.node?.req || event.req, event.node?.res || event.res))
1717

18-
if (isNuxt3()) {
18+
if (!isNuxtMajorVersion(2, nuxt)) {
1919
addDevServerHandler({
2020
handler: eventHandler((event) => {
2121
if (event.path === routeWithoutSlash) {
@@ -25,8 +25,7 @@ export const setupViewer = async (twConfig: string | TWConfig, config: ViewerCon
2525
})
2626
addDevServerHandler({ route, handler: viewerDevMiddleware })
2727
}
28-
29-
if (isNuxt2()) {
28+
else {
3029
// @ts-expect-error untyped nuxt2 property
3130
nuxt.options.serverMiddleware.push(
3231
// @ts-expect-error untyped handler parameters

0 commit comments

Comments
 (0)