|
1 | 1 | import { existsSync } from 'node:fs';
|
2 |
| -import { mkdir, mkdtemp, writeFile } from 'node:fs/promises'; |
| 2 | +import { mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises'; |
| 3 | +import { createRequire } from 'node:module'; |
3 | 4 | import { tmpdir } from 'node:os';
|
4 | 5 | import path from 'node:path';
|
5 | 6 | import { pathToFileURL } from 'node:url';
|
@@ -286,26 +287,80 @@ class TailwindRspackPluginImpl {
|
286 | 287 | await mkdir(outputDir, { recursive: true });
|
287 | 288 | }
|
288 | 289 |
|
289 |
| - const configPath = path.resolve(outputDir, 'tailwind.config.mjs'); |
| 290 | + const [configName, configContent] = await this.#generateTailwindConfig( |
| 291 | + userConfig, |
| 292 | + entryModules, |
| 293 | + ); |
| 294 | + const configPath = path.resolve(outputDir, configName); |
290 | 295 |
|
291 |
| - const content = JSON.stringify(entryModules); |
| 296 | + await writeFile(configPath, configContent); |
292 | 297 |
|
293 |
| - await writeFile( |
294 |
| - configPath, |
295 |
| - existsSync(userConfig) |
296 |
| - ? `\ |
| 298 | + return configPath; |
| 299 | + } |
| 300 | + |
| 301 | + async #resolveTailwindCSSVersion(): Promise<string> { |
| 302 | + const require = createRequire(import.meta.url); |
| 303 | + const pkgPath = require.resolve('tailwindcss/package.json', { |
| 304 | + paths: [this.compiler.context], |
| 305 | + }); |
| 306 | + |
| 307 | + const content = await readFile(pkgPath, 'utf-8'); |
| 308 | + |
| 309 | + const { version } = JSON.parse(content) as { version: string }; |
| 310 | + |
| 311 | + return version; |
| 312 | + } |
| 313 | + |
| 314 | + async #generateTailwindConfig( |
| 315 | + userConfig: string, |
| 316 | + entryModules: string[], |
| 317 | + ): Promise<['tailwind.config.mjs' | 'tailwind.config.cjs', string]> { |
| 318 | + const version = await this.#resolveTailwindCSSVersion(); |
| 319 | + |
| 320 | + const { default: satisfies } = await import( |
| 321 | + 'semver/functions/satisfies.js' |
| 322 | + ); |
| 323 | + |
| 324 | + const content = JSON.stringify(entryModules); |
| 325 | + if (satisfies(version, '^3.3.0')) { |
| 326 | + // Tailwind CSS support using ESM configuration in v3.3.0 |
| 327 | + // See: |
| 328 | + // - https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.0 |
| 329 | + // - https://github.com/tailwindlabs/tailwindcss/pull/10785 |
| 330 | + // - https://github.com/rspack-contrib/rsbuild-plugin-tailwindcss/issues/18 |
| 331 | + // |
| 332 | + // In this case, we provide an ESM configuration to support both ESM and CJS. |
| 333 | + return [ |
| 334 | + 'tailwind.config.mjs', |
| 335 | + existsSync(userConfig) |
| 336 | + ? `\ |
297 | 337 | import config from '${pathToFileURL(userConfig)}'
|
298 | 338 | export default {
|
299 | 339 | ...config,
|
300 | 340 | content: ${content}
|
301 | 341 | }`
|
302 |
| - : `\ |
| 342 | + : `\ |
303 | 343 | export default {
|
304 | 344 | content: ${content}
|
305 | 345 | }`,
|
306 |
| - ); |
| 346 | + ]; |
| 347 | + } |
307 | 348 |
|
308 |
| - return configPath; |
| 349 | + // Otherwise, we provide an CJS configuration since TailwindCSS would always use `require`. |
| 350 | + return [ |
| 351 | + 'tailwind.config.cjs', |
| 352 | + existsSync(userConfig) |
| 353 | + ? `\ |
| 354 | +const config = require(${JSON.stringify(userConfig)}) |
| 355 | +module.exports = { |
| 356 | + ...config, |
| 357 | + content: ${content} |
| 358 | +}` |
| 359 | + : `\ |
| 360 | +module.exports = { |
| 361 | + content: ${content} |
| 362 | +}`, |
| 363 | + ]; |
309 | 364 | }
|
310 | 365 | }
|
311 | 366 |
|
|
0 commit comments