Skip to content

Commit 64791f3

Browse files
author
Ben Jervis
authored
Add postcss support to vite-plugin (#517)
1 parent a4281f6 commit 64791f3

File tree

9 files changed

+115
-18
lines changed

9 files changed

+115
-18
lines changed

.changeset/curly-needles-love.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@vanilla-extract/vite-plugin': minor
3+
---
4+
5+
Add postcss processing to the plugin
6+
7+
Vite supports postcss processing as a built in feature, but that's lost in dev mode with vanilla-extract because there are no actual css files for vite to pick up.
8+
9+
The vite plugin now manually runs postcss over the generated css in serve mode, if any postcss config was found.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@vanilla-extract/integration': major
3+
---
4+
5+
processVanillaFile is now async

packages/esbuild-plugin/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function vanillaExtractPlugin({
6363
cwd: build.initialOptions.absWorkingDir,
6464
});
6565

66-
const contents = processVanillaFile({
66+
const contents = await processVanillaFile({
6767
source,
6868
filePath: path,
6969
outputCss,

packages/integration/src/processVanillaFile.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ interface ProcessVanillaFileOptions {
3737
base64Source: string;
3838
fileScope: FileScope;
3939
source: string;
40-
}) => string;
40+
}) => string | Promise<string>;
4141
}
42-
export function processVanillaFile({
42+
export async function processVanillaFile({
4343
source,
4444
filePath,
4545
outputCss = true,
@@ -116,14 +116,24 @@ export function processVanillaFile({
116116
: fileScope.filePath
117117
}.vanilla.css`;
118118

119-
const virtualCssFilePath = serializeVirtualCssPath
120-
? serializeVirtualCssPath({
121-
fileName,
122-
base64Source,
123-
fileScope,
124-
source: css,
125-
})
126-
: `import '${fileName}?source=${base64Source}';`;
119+
let virtualCssFilePath: string;
120+
121+
if (serializeVirtualCssPath) {
122+
const serializedResult = serializeVirtualCssPath({
123+
fileName,
124+
base64Source,
125+
fileScope,
126+
source: css,
127+
});
128+
129+
if (typeof serializedResult === 'string') {
130+
virtualCssFilePath = serializedResult;
131+
} else {
132+
virtualCssFilePath = await serializedResult;
133+
}
134+
} else {
135+
virtualCssFilePath = `import '${fileName}?source=${base64Source}';`;
136+
}
127137

128138
cssImports.push(virtualCssFilePath);
129139
}

packages/vite-plugin/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
"license": "MIT",
1717
"dependencies": {
1818
"@vanilla-extract/integration": "^1.4.3",
19-
"outdent": "^0.8.0"
19+
"outdent": "^0.8.0",
20+
"postcss": "^8.3.6",
21+
"postcss-load-config": "^3.1.0"
2022
},
2123
"devDependencies": {
2224
"vite": "^2.6.0"

packages/vite-plugin/src/index.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
stringifyFileScope,
1313
parseFileScope,
1414
} from '@vanilla-extract/integration';
15+
import { PostCSSConfigResult, resolvePostcssConfig } from './postcss';
1516

1617
const styleUpdateEvent = (fileId: string) =>
1718
`vanilla-extract-style-update:${fileId}`;
@@ -25,6 +26,7 @@ export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
2526
let config: ResolvedConfig;
2627
let packageInfo: ReturnType<typeof getPackageInfo>;
2728
let server: ViteDevServer;
29+
let postCssConfig: PostCSSConfigResult | null;
2830
const cssMap = new Map<string, string>();
2931

3032
let virtualExt: string;
@@ -50,9 +52,13 @@ export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
5052
},
5153
};
5254
},
53-
configResolved(resolvedConfig) {
55+
async configResolved(resolvedConfig) {
5456
config = resolvedConfig;
5557

58+
if (config.command === 'serve') {
59+
postCssConfig = await resolvePostcssConfig(config);
60+
}
61+
5662
virtualExt = `.vanilla.${config.command === 'serve' ? 'js' : 'css'}`;
5763

5864
packageInfo = getPackageInfo(config.root);
@@ -133,10 +139,24 @@ export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
133139
filePath: validId,
134140
identOption:
135141
identifiers ?? (config.mode === 'production' ? 'short' : 'debug'),
136-
serializeVirtualCssPath: ({ fileScope, source }) => {
142+
serializeVirtualCssPath: async ({ fileScope, source }) => {
137143
const fileId = stringifyFileScope(fileScope);
138144
const id = `${virtualPrefix}${fileId}${virtualExt}`;
139145

146+
let cssSource = source;
147+
148+
if (postCssConfig) {
149+
const postCssResult = await (await import('postcss'))
150+
.default(postCssConfig.plugins)
151+
.process(source, {
152+
...postCssConfig.options,
153+
from: undefined,
154+
map: false,
155+
});
156+
157+
cssSource = postCssResult.css;
158+
}
159+
140160
if (server && cssMap.has(fileId) && cssMap.get(fileId) !== source) {
141161
const { moduleGraph } = server;
142162
const module = moduleGraph.getModuleById(id);
@@ -148,11 +168,11 @@ export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
148168
server.ws.send({
149169
type: 'custom',
150170
event: styleUpdateEvent(fileId),
151-
data: source,
171+
data: cssSource,
152172
});
153173
}
154174

155-
cssMap.set(fileId, source);
175+
cssMap.set(fileId, cssSource);
156176

157177
return `import "${id}";`;
158178
},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { ResolvedConfig } from 'vite';
2+
import type { ProcessOptions, Plugin } from 'postcss';
3+
4+
export interface PostCSSConfigResult {
5+
options: ProcessOptions;
6+
plugins: Plugin[];
7+
}
8+
9+
// Mostly copied from vite's implementation
10+
// https://github.com/vitejs/vite/blob/efec70f816b80e55b64255b32a5f120e1cf4e4be/packages/vite/src/node/plugins/css.ts
11+
export const resolvePostcssConfig = async (
12+
config: ResolvedConfig,
13+
): Promise<PostCSSConfigResult | null> => {
14+
// inline postcss config via vite config
15+
const inlineOptions = config.css?.postcss;
16+
const inlineOptionsIsString = typeof inlineOptions === 'string';
17+
18+
if (inlineOptions && !inlineOptionsIsString) {
19+
const options = { ...inlineOptions };
20+
21+
delete options.plugins;
22+
return {
23+
options,
24+
plugins: inlineOptions.plugins || [],
25+
};
26+
} else {
27+
try {
28+
const searchPath =
29+
typeof inlineOptions === 'string' ? inlineOptions : config.root;
30+
31+
const postCssConfig = await (
32+
await import('postcss-load-config')
33+
).default({}, searchPath);
34+
35+
return {
36+
options: postCssConfig.options,
37+
// @ts-expect-error - The postcssrc options don't agree with real postcss, but it should be ok
38+
plugins: postCssConfig.plugins,
39+
};
40+
} catch (e: any) {
41+
if (!/No PostCSS Config found/.test(e.message)) {
42+
throw e;
43+
}
44+
return null;
45+
}
46+
}
47+
};

packages/webpack-plugin/src/loader.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ export function pitch(this: LoaderContext) {
6565

6666
childCompiler
6767
.getCompiledSource(this)
68-
.then(({ source }) => {
69-
const result = processVanillaFile({
68+
.then(async ({ source }) => {
69+
const result = await processVanillaFile({
7070
source,
7171
outputCss,
7272
filePath: this.resourcePath,

pnpm-lock.yaml

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)