Skip to content

Commit

Permalink
@astrojs/tailwind: simplify, upgrade & fix support for ts config file (
Browse files Browse the repository at this point in the history
…#6724)

Co-authored-by: bluwy <[email protected]>
  • Loading branch information
TomPichaud and bluwy authored Jun 14, 2023
1 parent 06315a1 commit 3f1cb6b
Show file tree
Hide file tree
Showing 15 changed files with 205 additions and 152 deletions.
34 changes: 34 additions & 0 deletions .changeset/real-spies-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
'@astrojs/tailwind': major
---

Let tailwind postcss plugin load its config file itself. This changes the `tailwind.config.js` loading behaviour where Tailwind would load the config file from `process.cwd()` instead of the project `root`. You can configure the integration's `config.path` option to load from a specific path instead.

```js
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import { fileURLToPath } from 'url';

export default defineConfig({
integrations: [
tailwind({
config: {
path: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
},
}),
],
});
```
This change also requires a Tailwind config file to exist in your project as Astro's fallback value is no longer provided. It is set up automatically during `astro add tailwind`, but you can also manually create a `tailwind.config.cjs` file in your project root:
```js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}
```
9 changes: 8 additions & 1 deletion packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import { fileURLToPath } from 'url';

// https://astro.build/config
export default defineConfig({
integrations: [tailwind()],
integrations: [
tailwind({
config: {
path: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
},
}),
],
vite: {
build: {
assetsInlineLimit: 0,
Expand Down
9 changes: 0 additions & 9 deletions packages/astro/e2e/fixtures/tailwindcss/postcss.config.js

This file was deleted.

2 changes: 0 additions & 2 deletions packages/astro/test/astro-scripts.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { expect } from 'chai';
import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
import { tailwind } from './fixtures/astro-scripts/deps.mjs';

describe('Scripts (hoisted and not)', () => {
describe('Build', () => {
Expand Down Expand Up @@ -141,7 +140,6 @@ describe('Scripts (hoisted and not)', () => {
fixture = await loadFixture({
root: './fixtures/astro-scripts/',
integrations: [
tailwind(),
{
name: 'test-script-injection-with-injected-route',
hooks: {
Expand Down
11 changes: 8 additions & 3 deletions packages/astro/test/fixtures/astro-scripts/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import { fileURLToPath } from 'url';

export default defineConfig({
integrations: [
tailwind()
]
})
tailwind({
config: {
path: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)),
},
}),
],
});
2 changes: 0 additions & 2 deletions packages/astro/test/fixtures/astro-scripts/deps.mjs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';

import { fileURLToPath } from 'url';

// https://astro.build/config
export default defineConfig({
integrations: [tailwind()],
integrations: [
tailwind({
config: {
path: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)),
},
}),
],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}
13 changes: 10 additions & 3 deletions packages/astro/test/fixtures/tailwindcss-ts/astro.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { defineConfig } from 'astro/config';
import tailwind from "@astrojs/tailwind";
import tailwind from '@astrojs/tailwind';
import { fileURLToPath } from 'url';

// https://astro.build/config
export default defineConfig({
integrations: [tailwind()]
});
integrations: [
tailwind({
config: {
path: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
},
}),
],
});
10 changes: 9 additions & 1 deletion packages/astro/test/fixtures/tailwindcss/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import mdx from '@astrojs/mdx';
import { fileURLToPath } from 'url';

// https://astro.build/config
export default defineConfig({
integrations: [tailwind(), mdx()],
integrations: [
tailwind({
config: {
path: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
},
}),
mdx(),
],
vite: {
build: {
assetsInlineLimit: 0,
Expand Down
10 changes: 0 additions & 10 deletions packages/astro/test/fixtures/tailwindcss/postcss.config.js

This file was deleted.

3 changes: 1 addition & 2 deletions packages/integrations/tailwind/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@
"dev": "astro-scripts dev \"src/**/*.ts\""
},
"dependencies": {
"@proload/core": "^0.3.3",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
"postcss": "^8.4.24",
"postcss-load-config": "^4.0.1"
},
"devDependencies": {
Expand Down
111 changes: 12 additions & 99 deletions packages/integrations/tailwind/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,9 @@
import load, { resolve } from '@proload/core';
import type { AstroConfig, AstroIntegration } from 'astro';
import type { AstroIntegration } from 'astro';
import autoprefixerPlugin from 'autoprefixer';
import fs from 'fs/promises';
import path from 'path';
import tailwindPlugin, { type Config as TailwindConfig } from 'tailwindcss';
import resolveConfig from 'tailwindcss/resolveConfig.js';
import { fileURLToPath } from 'url';
import type { ResultPlugin } from 'postcss-load-config';
import tailwindPlugin from 'tailwindcss';
import type { CSSOptions, UserConfig } from 'vite';

function getDefaultTailwindConfig(srcUrl: URL): TailwindConfig {
return resolveConfig({
theme: {
extend: {},
},
plugins: [],
content: [path.join(fileURLToPath(srcUrl), `**`, `*.{astro,html,js,jsx,svelte,ts,tsx,vue}`)],
presets: undefined, // enable Tailwind's default preset
}) as TailwindConfig;
}

async function getUserConfig(root: URL, configPath?: string, isRestart = false) {
const resolvedRoot = fileURLToPath(root);
let userConfigPath: string | undefined;

if (configPath) {
const configPathWithLeadingSlash = /^\.*\//.test(configPath) ? configPath : `./${configPath}`;
userConfigPath = fileURLToPath(new URL(configPathWithLeadingSlash, root));
}

if (isRestart) {
// Hack: Write config to temporary file at project root
// This invalidates and reloads file contents when using ESM imports or "resolve"
const resolvedConfigPath = (await resolve('tailwind', {
mustExist: false,
cwd: resolvedRoot,
filePath: userConfigPath,
})) as string;

const { dir, base } = path.parse(resolvedConfigPath);
const tempConfigPath = path.join(dir, `.temp.${Date.now()}.${base}`);
await fs.copyFile(resolvedConfigPath, tempConfigPath);

let result: load.Config<Record<any, any>> | undefined;
try {
result = await load('tailwind', {
mustExist: false,
cwd: resolvedRoot,
filePath: tempConfigPath,
});
} catch (err) {
console.error(err);
} finally {
await fs.unlink(tempConfigPath);
}

return {
...result,
filePath: resolvedConfigPath,
};
} else {
return await load('tailwind', {
mustExist: false,
cwd: resolvedRoot,
filePath: userConfigPath,
});
}
}

async function getPostCssConfig(
root: UserConfig['root'],
postcssInlineOptions: CSSOptions['postcss']
Expand All @@ -86,20 +23,19 @@ async function getPostCssConfig(
}

async function getViteConfiguration(
tailwindConfig: TailwindConfig,
viteConfig: AstroConfig['vite']
tailwindConfigPath: string | undefined,
viteConfig: UserConfig
) {
// We need to manually load postcss config files because when inlining the tailwind and autoprefixer plugins,
// that causes vite to ignore postcss config files
const postcssConfigResult = await getPostCssConfig(viteConfig.root, viteConfig.css?.postcss);

const postcssOptions = (postcssConfigResult && postcssConfigResult.options) || {};

const postcssPlugins =
postcssConfigResult && postcssConfigResult.plugins ? postcssConfigResult.plugins.slice() : [];
postcssPlugins.push(tailwindPlugin(tailwindConfig));
const postcssOptions = postcssConfigResult?.options ?? {};
const postcssPlugins = postcssConfigResult?.plugins?.slice() ?? [];

postcssPlugins.push(tailwindPlugin(tailwindConfigPath) as ResultPlugin);
postcssPlugins.push(autoprefixerPlugin());

return {
css: {
postcss: {
Expand All @@ -123,7 +59,7 @@ type TailwindOptions =
* Disabling this is useful when further customization of Tailwind styles
* and directives is required. See {@link https://tailwindcss.com/docs/functions-and-directives#tailwind Tailwind's docs}
* for more details on directives and customization.
* @default: true
* @default true
*/
applyBaseStyles?: boolean;
};
Expand All @@ -136,33 +72,10 @@ export default function tailwindIntegration(options?: TailwindOptions): AstroInt
return {
name: '@astrojs/tailwind',
hooks: {
'astro:config:setup': async ({
config,
updateConfig,
injectScript,
addWatchFile,
isRestart,
}) => {
'astro:config:setup': async ({ config, updateConfig, injectScript }) => {
// Inject the Tailwind postcss plugin
const userConfig = await getUserConfig(config.root, customConfigPath, isRestart);

if (customConfigPath && !userConfig?.value) {
throw new Error(
`Could not find a Tailwind config at ${JSON.stringify(
customConfigPath
)}. Does the file exist?`
);
}

if (addWatchFile && userConfig?.filePath) {
addWatchFile(userConfig.filePath);
}

const tailwindConfig =
(userConfig?.value as TailwindConfig) ?? getDefaultTailwindConfig(config.srcDir);

updateConfig({
vite: await getViteConfiguration(tailwindConfig, config.vite),
vite: await getViteConfiguration(customConfigPath, config.vite),
});

if (applyBaseStyles) {
Expand Down
Loading

0 comments on commit 3f1cb6b

Please sign in to comment.