Skip to content

Commit

Permalink
Add postcss support to vite-plugin (#517)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjervis committed Dec 2, 2021
1 parent a4281f6 commit 64791f3
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 18 deletions.
9 changes: 9 additions & 0 deletions .changeset/curly-needles-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@vanilla-extract/vite-plugin': minor
---

Add postcss processing to the plugin

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.

The vite plugin now manually runs postcss over the generated css in serve mode, if any postcss config was found.
5 changes: 5 additions & 0 deletions .changeset/light-bobcats-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vanilla-extract/integration': major
---

processVanillaFile is now async
2 changes: 1 addition & 1 deletion packages/esbuild-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function vanillaExtractPlugin({
cwd: build.initialOptions.absWorkingDir,
});

const contents = processVanillaFile({
const contents = await processVanillaFile({
source,
filePath: path,
outputCss,
Expand Down
30 changes: 20 additions & 10 deletions packages/integration/src/processVanillaFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ interface ProcessVanillaFileOptions {
base64Source: string;
fileScope: FileScope;
source: string;
}) => string;
}) => string | Promise<string>;
}
export function processVanillaFile({
export async function processVanillaFile({
source,
filePath,
outputCss = true,
Expand Down Expand Up @@ -116,14 +116,24 @@ export function processVanillaFile({
: fileScope.filePath
}.vanilla.css`;

const virtualCssFilePath = serializeVirtualCssPath
? serializeVirtualCssPath({
fileName,
base64Source,
fileScope,
source: css,
})
: `import '${fileName}?source=${base64Source}';`;
let virtualCssFilePath: string;

if (serializeVirtualCssPath) {
const serializedResult = serializeVirtualCssPath({
fileName,
base64Source,
fileScope,
source: css,
});

if (typeof serializedResult === 'string') {
virtualCssFilePath = serializedResult;
} else {
virtualCssFilePath = await serializedResult;
}
} else {
virtualCssFilePath = `import '${fileName}?source=${base64Source}';`;
}

cssImports.push(virtualCssFilePath);
}
Expand Down
4 changes: 3 additions & 1 deletion packages/vite-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"license": "MIT",
"dependencies": {
"@vanilla-extract/integration": "^1.4.3",
"outdent": "^0.8.0"
"outdent": "^0.8.0",
"postcss": "^8.3.6",
"postcss-load-config": "^3.1.0"
},
"devDependencies": {
"vite": "^2.6.0"
Expand Down
28 changes: 24 additions & 4 deletions packages/vite-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
stringifyFileScope,
parseFileScope,
} from '@vanilla-extract/integration';
import { PostCSSConfigResult, resolvePostcssConfig } from './postcss';

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

let virtualExt: string;
Expand All @@ -50,9 +52,13 @@ export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
},
};
},
configResolved(resolvedConfig) {
async configResolved(resolvedConfig) {
config = resolvedConfig;

if (config.command === 'serve') {
postCssConfig = await resolvePostcssConfig(config);
}

virtualExt = `.vanilla.${config.command === 'serve' ? 'js' : 'css'}`;

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

let cssSource = source;

if (postCssConfig) {
const postCssResult = await (await import('postcss'))
.default(postCssConfig.plugins)
.process(source, {
...postCssConfig.options,
from: undefined,
map: false,
});

cssSource = postCssResult.css;
}

if (server && cssMap.has(fileId) && cssMap.get(fileId) !== source) {
const { moduleGraph } = server;
const module = moduleGraph.getModuleById(id);
Expand All @@ -148,11 +168,11 @@ export function vanillaExtractPlugin({ identifiers }: Options = {}): Plugin {
server.ws.send({
type: 'custom',
event: styleUpdateEvent(fileId),
data: source,
data: cssSource,
});
}

cssMap.set(fileId, source);
cssMap.set(fileId, cssSource);

return `import "${id}";`;
},
Expand Down
47 changes: 47 additions & 0 deletions packages/vite-plugin/src/postcss.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { ResolvedConfig } from 'vite';
import type { ProcessOptions, Plugin } from 'postcss';

export interface PostCSSConfigResult {
options: ProcessOptions;
plugins: Plugin[];
}

// Mostly copied from vite's implementation
// https://github.com/vitejs/vite/blob/efec70f816b80e55b64255b32a5f120e1cf4e4be/packages/vite/src/node/plugins/css.ts
export const resolvePostcssConfig = async (
config: ResolvedConfig,
): Promise<PostCSSConfigResult | null> => {
// inline postcss config via vite config
const inlineOptions = config.css?.postcss;
const inlineOptionsIsString = typeof inlineOptions === 'string';

if (inlineOptions && !inlineOptionsIsString) {
const options = { ...inlineOptions };

delete options.plugins;
return {
options,
plugins: inlineOptions.plugins || [],
};
} else {
try {
const searchPath =
typeof inlineOptions === 'string' ? inlineOptions : config.root;

const postCssConfig = await (
await import('postcss-load-config')
).default({}, searchPath);

return {
options: postCssConfig.options,
// @ts-expect-error - The postcssrc options don't agree with real postcss, but it should be ok
plugins: postCssConfig.plugins,
};
} catch (e: any) {
if (!/No PostCSS Config found/.test(e.message)) {
throw e;
}
return null;
}
}
};
4 changes: 2 additions & 2 deletions packages/webpack-plugin/src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export function pitch(this: LoaderContext) {

childCompiler
.getCompiledSource(this)
.then(({ source }) => {
const result = processVanillaFile({
.then(async ({ source }) => {
const result = await processVanillaFile({
source,
outputCss,
filePath: this.resourcePath,
Expand Down
4 changes: 4 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 64791f3

Please sign in to comment.