Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integration callbacks #942

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/cool-rats-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@vanilla-extract/esbuild-plugin': minor
'@vanilla-extract/rollup-plugin': minor
'@vanilla-extract/sprinkles': minor
'@vanilla-extract/vite-plugin': minor
---

makes changes to the plugins integration (vite/webpack/esbuild/rollup) by allowing to pass those new callbacks to the `processVanillaFile` call
also exports the ProcessVanillaFileOptions & SprinklesProperties type
6 changes: 6 additions & 0 deletions .changeset/great-grapes-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@vanilla-extract/css': patch
---

fix(css): opti getDevPrefix by removing filePath regex
which was especially slow when used against filePath located somewhere in node_modules
5 changes: 5 additions & 0 deletions .changeset/moody-ears-study.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vanilla-extract/vite-plugin': minor
---

allows customizing the forceEmitCssInSsrBuild option for the vite plugin (needed to make the HMR work with SSR frameworks for those not hard-coded, like vite-plugin-ssr)
7 changes: 7 additions & 0 deletions .changeset/perfect-rocks-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@vanilla-extract/integration': minor
---

creates an AdapterContext (which is just a reference to the result of the adapter after the evalCode of processVanillaFile so anyone can retrieve the generated class names / CSS rules by file scopes

adding a onEvaluated callback to processVanillaFile to retrieve the resulting mapping of classNames by property+value+condition using the AdapterContext
6 changes: 6 additions & 0 deletions .changeset/strong-windows-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@vanilla-extract/integration': minor
---

adding a serializeVanillaModule callback like the current serializeVirtualCssPath callback, it allows customizing the behaviour
also exports the default implementation of serializeVanillaModule
5 changes: 5 additions & 0 deletions .changeset/tidy-gifts-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vanilla-extract/vite-plugin': minor
---

fix HMR
5 changes: 5 additions & 0 deletions .changeset/twelve-suns-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vanilla-extract/vite-plugin': minor
---

using raw .css.ts from another package than config.root
10 changes: 5 additions & 5 deletions packages/css/src/identifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ function getDevPrefix({
if (debugFileName) {
const { filePath } = getFileScope();

const matches = filePath.match(
/(?<dir>[^\/\\]*)?[\/\\]?(?<file>[^\/\\]*)\.css\.(ts|js|tsx|jsx|cjs|mjs)$/,
);
const pathParts = filePath.split('/');
const dir = pathParts[pathParts.length - 2];
const fileNameParts = pathParts[pathParts.length - 1].split('.');
const file = fileNameParts.length > 1 ? fileNameParts[0] : undefined;

if (matches && matches.groups) {
const { dir, file } = matches.groups;
if (dir || file) {
parts.unshift(file && file !== 'index' ? file : dir);
}
}
Expand Down
11 changes: 10 additions & 1 deletion packages/esbuild-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ import {
vanillaExtractTransformPlugin,
IdentifierOption,
CompileOptions,
ProcessVanillaFileOptions,
} from '@vanilla-extract/integration';
import type { Plugin } from 'esbuild';

const vanillaCssNamespace = 'vanilla-extract-css-ns';

interface VanillaExtractPluginOptions {
interface VanillaExtractPluginOptions
extends Pick<
ProcessVanillaFileOptions,
'onEvaluated' | 'serializeVanillaModule'
> {
outputCss?: boolean;
/**
* @deprecated Use `esbuildOptions.external` instead.
Expand All @@ -32,6 +37,8 @@ export function vanillaExtractPlugin({
processCss,
identifiers,
esbuildOptions,
onEvaluated,
serializeVanillaModule,
}: VanillaExtractPluginOptions = {}): Plugin {
if (runtime) {
// If using runtime CSS then just apply fileScopes and debug IDs to code
Expand Down Expand Up @@ -96,6 +103,8 @@ export function vanillaExtractPlugin({
filePath: path,
outputCss,
identOption,
onEvaluated,
serializeVanillaModule,
});

return {
Expand Down
5 changes: 5 additions & 0 deletions packages/integration/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {
defaultSerializeVanillaModule,
processVanillaFile,
parseFileScope,
stringifyFileScope,
Expand All @@ -15,4 +16,8 @@ export * from './filters';

export type { IdentifierOption } from './types';
export type { PackageInfo } from './packageInfo';
export type {
AdapterContext,
ProcessVanillaFileOptions,
} from './processVanillaFile';
export type { CompileOptions } from './compile';
87 changes: 59 additions & 28 deletions packages/integration/src/processVanillaFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function parseFileScope(serialisedFileScope: string): FileScope {
};
}

interface ProcessVanillaFileOptions {
export interface ProcessVanillaFileOptions {
source: string;
filePath: string;
outputCss?: boolean;
Expand All @@ -38,41 +38,66 @@ interface ProcessVanillaFileOptions {
fileScope: FileScope;
source: string;
}) => string | Promise<string>;
onEvaluated?: (args: {
source: string;
context: AdapterContext;
evalResult: Record<string, unknown>;
filePath: string;
}) => void;
serializeVanillaModule?: (
cssImports: Array<string>,
exports: Record<string, unknown>,
context: AdapterContext,
filePath: string,
) => string;
}

export interface AdapterContext {
cssByFileScope: Map<string, Css[]>;
localClassNames: Set<string>;
composedClassLists: Composition[];
usedCompositions: Set<string>;
}

type Css = Parameters<Adapter['appendCss']>[0];
type Composition = Parameters<Adapter['registerComposition']>[0];

export async function processVanillaFile({
source,
filePath,
outputCss = true,
identOption = process.env.NODE_ENV === 'production' ? 'short' : 'debug',
serializeVirtualCssPath,
serializeVanillaModule,
onEvaluated,
}: ProcessVanillaFileOptions) {
type Css = Parameters<Adapter['appendCss']>[0];
type Composition = Parameters<Adapter['registerComposition']>[0];

const cssByFileScope = new Map<string, Array<Css>>();
const localClassNames = new Set<string>();
const composedClassLists: Array<Composition> = [];
const usedCompositions = new Set<string>();
const context: AdapterContext = {
cssByFileScope: new Map<string, Array<Css>>(),
localClassNames: new Set<string>(),
composedClassLists: [],
usedCompositions: new Set<string>(),
};

const cssAdapter: Adapter = {
appendCss: (css, fileScope) => {
if (outputCss) {
const serialisedFileScope = stringifyFileScope(fileScope);
const fileScopeCss = cssByFileScope.get(serialisedFileScope) ?? [];
const fileScopeCss =
context.cssByFileScope.get(serialisedFileScope) ?? [];

fileScopeCss.push(css);

cssByFileScope.set(serialisedFileScope, fileScopeCss);
context.cssByFileScope.set(serialisedFileScope, fileScopeCss);
}
},
registerClassName: (className) => {
localClassNames.add(className);
context.localClassNames.add(className);
},
registerComposition: (composedClassList) => {
composedClassLists.push(composedClassList);
context.composedClassLists.push(composedClassList);
},
markCompositionUsed: (identifier) => {
usedCompositions.add(identifier);
context.usedCompositions.add(identifier);
},
onEndFileScope: () => {},
getIdentOption: () => identOption,
Expand All @@ -96,16 +121,17 @@ export async function processVanillaFile({
{ console, process, __adapter__: cssAdapter },
true,
);
onEvaluated?.({ source, context, evalResult, filePath });

process.env.NODE_ENV = currentNodeEnv;

const cssImports = [];

for (const [serialisedFileScope, fileScopeCss] of cssByFileScope) {
for (const [serialisedFileScope, fileScopeCss] of context.cssByFileScope) {
const fileScope = parseFileScope(serialisedFileScope);
const css = transformCss({
localClassNames: Array.from(localClassNames),
composedClassLists,
localClassNames: Array.from(context.localClassNames),
composedClassLists: context.composedClassLists,
cssObjs: fileScopeCss,
}).join('\n');

Expand Down Expand Up @@ -148,16 +174,12 @@ export async function processVanillaFile({
true,
);

const unusedCompositions = composedClassLists
.filter(({ identifier }) => !usedCompositions.has(identifier))
.map(({ identifier }) => identifier);

const unusedCompositionRegex =
unusedCompositions.length > 0
? RegExp(`(${unusedCompositions.join('|')})\\s`, 'g')
: null;

return serializeVanillaModule(cssImports, evalResult, unusedCompositionRegex);
return (serializeVanillaModule ?? defaultSerializeVanillaModule)(
cssImports,
evalResult,
context,
filePath,
);
}

export function stringifyExports(
Expand Down Expand Up @@ -246,11 +268,20 @@ export function stringifyExports(
);
}

function serializeVanillaModule(
export function defaultSerializeVanillaModule(
cssImports: Array<string>,
exports: Record<string, unknown>,
unusedCompositionRegex: RegExp | null,
context: AdapterContext,
) {
const unusedCompositions = context.composedClassLists
.filter(({ identifier }) => !context.usedCompositions.has(identifier))
.map(({ identifier }) => identifier);

const unusedCompositionRegex =
unusedCompositions.length > 0
? RegExp(`(${unusedCompositions.join('|')})\\s`, 'g')
: null;

const recipeImports = new Set<string>();

const moduleExports = Object.keys(exports).map((key) =>
Expand Down
11 changes: 10 additions & 1 deletion packages/rollup-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@ import {
getSourceFromVirtualCssFile,
virtualCssFileFilter,
CompileOptions,
ProcessVanillaFileOptions,
} from '@vanilla-extract/integration';
import { posix } from 'path';

const { relative, normalize, dirname } = posix;

interface Options {
interface Options
extends Pick<
ProcessVanillaFileOptions,
'onEvaluated' | 'serializeVanillaModule'
> {
identifiers?: IdentifierOption;
cwd?: string;
esbuildOptions?: CompileOptions['esbuildOptions'];
Expand All @@ -21,6 +26,8 @@ export function vanillaExtractPlugin({
identifiers,
cwd = process.cwd(),
esbuildOptions,
onEvaluated,
serializeVanillaModule,
}: Options = {}): Plugin {
const emittedFiles = new Map<string, string>();
const isProduction = process.env.NODE_ENV === 'production';
Expand Down Expand Up @@ -55,6 +62,8 @@ export function vanillaExtractPlugin({
source,
filePath,
identOption,
onEvaluated,
serializeVanillaModule,
});
return {
code: output,
Expand Down
1 change: 1 addition & 0 deletions packages/sprinkles/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
createSprinkles as internalCreateSprinkles,
} from './createSprinkles';
import { SprinklesProperties, ResponsiveArrayConfig } from './types';
export type { SprinklesProperties } from './types';

export { createNormalizeValueFn, createMapValueFn } from './createUtils';
export type { ConditionalValue, RequiredConditionalValue } from './createUtils';
Expand Down
Loading