Skip to content

Commit

Permalink
Improve PostCSS and Tailwind support
Browse files Browse the repository at this point in the history
  • Loading branch information
drwpow committed May 21, 2021
1 parent 5c1f949 commit 13c8710
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 1,825 deletions.
2 changes: 2 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export default {
devOptions: {
/** The port to run the dev server on. */
port: 3000,
/** Path to tailwind.config.js if used, e.g. './tailwind.config.js' */
tailwindConfig: undefined,
},
};
```
15 changes: 0 additions & 15 deletions examples/snowpack/.stylelintrc.js

This file was deleted.

7 changes: 1 addition & 6 deletions examples/snowpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"astro-dev": "nodemon --delay 0.5 -w ../../packages/astro/dist -x '../../packages/astro/astro.mjs dev'",
"test": "jest /__test__/",
"format": "prettier --write \"src/**/*.js\" && yarn format:css",
"format:css": "stylelint 'src/**/*.scss' --fix",
"lint": "prettier --check \"src/**/*.js\""
},
"dependencies": {
Expand All @@ -31,11 +30,7 @@
"luxon": "^1.25.0",
"markdown-it": "^12.0.2",
"markdown-it-anchor": "^6.0.0",
"nodemon": "^2.0.7",
"stylelint": "^13.8.0",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-standard": "^20.0.0"
"nodemon": "^2.0.7"
},
"snowpack": {
"workspaceRoot": "../.."
Expand Down
5 changes: 5 additions & 0 deletions examples/tailwindcss/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
devOptions: {
tailwindConfig: './tailwind.config.js',
},
};
2 changes: 1 addition & 1 deletion examples/tailwindcss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"devDependencies": {
"astro": "^0.10.0",
"tailwindcss": "^2.1.1"
"tailwindcss": "^2.1.2"
},
"snowpack": {
"workspaceRoot": "../.."
Expand Down
3 changes: 3 additions & 0 deletions examples/tailwindcss/public/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
5 changes: 0 additions & 5 deletions examples/tailwindcss/src/components/Button.astro
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
<style>
@tailwind components;
@tailwind utilities;
</style>

<button class="py-2 px-4 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-opacity-75">
<slot />
</button>
4 changes: 1 addition & 3 deletions examples/tailwindcss/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import Button from '../components/Button.astro';
<head>
<meta charset="UTF-8" />
<title>Astro + TailwindCSS</title>
<style>
@tailwind base;
</style>
<link rel="stylesheet" type="text/css" href="/global.css">
</head>

<body>
Expand Down
9 changes: 5 additions & 4 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@
"@babel/parser": "^7.13.15",
"@babel/traverse": "^7.13.15",
"@silvenon/remark-smartypants": "^1.0.0",
"@snowpack/plugin-postcss": "^1.4.0-pre.1",
"@snowpack/plugin-sass": "^1.4.0",
"@snowpack/plugin-svelte": "^3.6.1",
"@snowpack/plugin-vue": "^2.4.0",
"@snowpack/plugin-svelte": "^3.7.0",
"@snowpack/plugin-vue": "^2.5.0",
"@vue/server-renderer": "^3.0.10",
"acorn": "^7.4.0",
"astro-parser": "0.1.0",
Expand All @@ -64,7 +65,7 @@
"moize": "^6.0.1",
"node-fetch": "^2.6.1",
"picomatch": "^2.2.3",
"postcss": "^8.2.8",
"postcss": "^8.2.15",
"postcss-icss-keyframes": "^0.2.1",
"preact": "^10.5.13",
"preact-render-to-string": "^5.1.18",
Expand All @@ -83,7 +84,7 @@
"sass": "^1.32.13",
"shorthash": "^0.0.2",
"slash": "^4.0.0",
"snowpack": "^3.3.7",
"snowpack": "^3.5.0",
"source-map-support": "^0.5.19",
"string-width": "^5.0.0",
"svelte": "^3.35.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export interface AstroConfig {
/** The port to run the dev server on. */
port: number;
projectRoot?: string;
/** Path to tailwind.config.js, if used */
tailwindConfig?: string;
};
}

Expand All @@ -36,6 +38,7 @@ export type AstroUserConfig = Omit<AstroConfig, 'buildOptions' | 'devOptions'> &
devOptions: {
port?: number;
projectRoot?: string;
tailwindConfig?: string;
};
};

Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/@types/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export interface CompileOptions {
astroConfig: AstroConfig;
extensions?: Record<string, ValidExtensionPlugins>;
mode: RuntimeMode;
tailwindConfig?: string;
}
23 changes: 4 additions & 19 deletions packages/astro/src/compiler/transform/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { TransformOptions, Transformer } from '../../@types/transformer';
import type { TemplateNode } from 'astro-parser';

import crypto from 'crypto';
import fs from 'fs';
import { createRequire } from 'module';
import path from 'path';
import { fileURLToPath } from 'url';
Expand Down Expand Up @@ -55,7 +54,6 @@ export interface StyleTransformResult {

interface StylesMiniCache {
nodeModules: Map<string, string>; // filename: node_modules location
tailwindEnabled?: boolean; // cache once per-run
}

/** Simple cache that only exists in memory per-run. Prevents the same lookups from happening over and over again within the same build or dev server session. */
Expand All @@ -68,6 +66,7 @@ export interface TransformStyleOptions {
type?: string;
filename: string;
scopedClass: string;
tailwindConfig?: string;
}

/** given a class="" string, does it contain a given class? */
Expand All @@ -80,7 +79,7 @@ function hasClass(classList: string, className: string): boolean {
}

/** Convert styles to scoped CSS */
async function transformStyle(code: string, { logging, type, filename, scopedClass }: TransformStyleOptions): Promise<StyleTransformResult> {
async function transformStyle(code: string, { logging, type, filename, scopedClass, tailwindConfig }: TransformStyleOptions): Promise<StyleTransformResult> {
let styleType: StyleType = 'css'; // important: assume CSS as default
if (type) {
styleType = getStyleType.get(type) || styleType;
Expand Down Expand Up @@ -122,7 +121,7 @@ async function transformStyle(code: string, { logging, type, filename, scopedCla
const postcssPlugins: Plugin[] = [];

// 2a. Tailwind (only if project uses Tailwind)
if (miniCache.tailwindEnabled) {
if (tailwindConfig) {
try {
const require = createRequire(import.meta.url);
const tw = require.resolve('tailwindcss', { paths: [import.meta.url, process.cwd()] });
Expand Down Expand Up @@ -192,21 +191,6 @@ export default function transformStyles({ compileOptions, filename, fileID }: Tr
const styleTransformPromises: Promise<StyleTransformResult>[] = []; // async style transform results to be finished in finalize();
const scopedClass = `astro-${hashFromFilename(fileID)}`; // this *should* generate same hash from fileID every time

// find Tailwind config, if first run (cache for subsequent runs)
if (miniCache.tailwindEnabled === undefined) {
const tailwindNames = ['tailwind.config.js', 'tailwind.config.mjs'];
for (const loc of tailwindNames) {
const tailwindLoc = path.join(fileURLToPath(compileOptions.astroConfig.projectRoot), loc);
if (fs.existsSync(tailwindLoc)) {
miniCache.tailwindEnabled = true; // Success! We have a Tailwind config file.
debug(compileOptions.logging, 'tailwind', 'Found config. Enabling.');
break;
}
}
if (miniCache.tailwindEnabled !== true) miniCache.tailwindEnabled = false; // We couldn‘t find one; mark as false
debug(compileOptions.logging, 'tailwind', 'No config found. Skipping.');
}

return {
visitors: {
html: {
Expand All @@ -231,6 +215,7 @@ export default function transformStyles({ compileOptions, filename, fileID }: Tr
type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined,
filename,
scopedClass,
tailwindConfig: compileOptions.tailwindConfig,
})
);
return;
Expand Down
18 changes: 12 additions & 6 deletions packages/astro/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,25 @@ function validateConfig(config: any): void {
}

// buildOptions
if (config.buildOptions && config.buildOptions.site !== undefined) {
if (typeof config.buildOptions.site !== 'string') throw new Error(`[config] buildOptions.site is not a string`);
try {
new URL(config.buildOptions.site);
} catch (err) {
throw new Error('[config] buildOptions.site must be a valid URL');
if (config.buildOptions) {
// buildOptions.site
if (config.buildOptions.site !== undefined) {
if (typeof config.buildOptions.site !== 'string') throw new Error(`[config] buildOptions.site is not a string`);
try {
new URL(config.buildOptions.site);
} catch (err) {
throw new Error('[config] buildOptions.site must be a valid URL');
}
}
}

// devOptions
if (typeof config.devOptions?.port !== 'number') {
throw new Error(`[config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`);
}
if (config.devOptions?.tailwindConfig !== undefined && typeof config.devOptions?.tailwindConfig !== 'string') {
throw new Error(`[config] devOptions.tailwindConfig: Expected string, received ${type(config.devOptions?.tailwindConfig)}`);
}
}

/** Set default config values */
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default async function dev(astroConfig: AstroConfig) {
break;
}
case 404: {
const fullurl = new URL(req.url || '/', 'https://example.org/');
const fullurl = new URL(req.url || '/', astroConfig.buildOptions.site || `http://localhost${astroConfig.devOptions.port}`);
const reqPath = decodeURI(fullurl.pathname);
error(logging, 'static', 'Not found', reqPath);
res.statusCode = 404;
Expand Down
40 changes: 33 additions & 7 deletions packages/astro/src/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,13 @@ interface CreateSnowpackOptions {
env: Record<string, any>;
mode: RuntimeMode;
resolvePackageUrl?: (pkgName: string) => Promise<string>;
target: 'frontend' | 'backend';
}

/** Create a new Snowpack instance to power Astro */
async function createSnowpack(astroConfig: AstroConfig, options: CreateSnowpackOptions) {
const { projectRoot, astroRoot, extensions } = astroConfig;
const { env, mode, resolvePackageUrl } = options;
const { env, mode, resolvePackageUrl, target } = options;

const internalPath = new URL('./frontend/', import.meta.url);

Expand All @@ -295,20 +296,43 @@ async function createSnowpack(astroConfig: AstroConfig, options: CreateSnowpackO
mountOptions[fileURLToPath(astroConfig.public)] = '/';
}

const plugins: (string | [string, any])[] = [
[fileURLToPath(new URL('../snowpack-plugin.cjs', import.meta.url)), astroPlugOptions],
[require.resolve('@snowpack/plugin-svelte'), { compilerOptions: { hydratable: true } }],
require.resolve('@snowpack/plugin-vue'),
];

// note: styles only need processing once
if (target === 'frontend') {
plugins.push(require.resolve('@snowpack/plugin-sass'));
plugins.push([
require.resolve('@snowpack/plugin-postcss'),
{
config: {
plugins: {
[require.resolve('autoprefixer')]: {},
...(astroConfig.devOptions.tailwindConfig ? { [require.resolve('tailwindcss')]: {} } : {}),
},
},
},
]);
}

// Tailwind: IDK what this does but it makes JIT work 🤷‍♂️
if (astroConfig.devOptions.tailwindConfig) {
(process.env as any).TAILWIND_DISABLE_TOUCH = true;
}

const snowpackConfig = await loadConfiguration({
root: fileURLToPath(projectRoot),
mount: mountOptions,
mode,
plugins: [
[fileURLToPath(new URL('../snowpack-plugin.cjs', import.meta.url)), astroPlugOptions],
require.resolve('@snowpack/plugin-sass'),
[require.resolve('@snowpack/plugin-svelte'), { compilerOptions: { hydratable: true } }],
require.resolve('@snowpack/plugin-vue'),
],
plugins,
devOptions: {
open: 'none',
output: 'stream',
port: 0,
tailwindConfig: astroConfig.devOptions.tailwindConfig,
},
buildOptions: {
out: astroConfig.dist,
Expand Down Expand Up @@ -343,6 +367,7 @@ export async function createRuntime(astroConfig: AstroConfig, { mode, logging }:
},
mode,
resolvePackageUrl,
target: 'backend',
});
debug(logging, 'core', `backend snowpack created [${stopTimer(timer.backend)}]`);

Expand All @@ -352,6 +377,7 @@ export async function createRuntime(astroConfig: AstroConfig, { mode, logging }:
astro: false,
},
mode,
target: 'frontend',
});
debug(logging, 'core', `frontend snowpack created [${stopTimer(timer.frontend)}]`);

Expand Down

0 comments on commit 13c8710

Please sign in to comment.