샘플
tailwindcss 4.3.3: Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export
검증된 샘플 — npm tailwindcss 4.3.3: Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build…
sha256:7e8fea6fcad1e429a66c2ec7cabadab555fed65be50225e20dee895a0a8de843
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
MIT-0
실행 증거
선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.
- 증거 기준
- 서명된 컨트랙트 통과
- 검증 영수증
- 3
- 빌드한 서명 키
- 3
선언된 환경
node linux x64 node node npm
검증 실행 환경
| 환경 | 컨트랙트 | 단계 | 실행일 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-08 |
케이스
HOW- 목표
- Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export
- 심벌
-
- tailwindcss
- compile
- loadStylesheet
- loadModule
- build
- default
- 환경
- node
- 생성일
- 2026-08-16T07:54:12Z
컨트랙트
- assert default export throws when invoked as PostCSS plugin directing callers to @tailwindcss/postcss
- assert compile rejects when @import is used without providing loadStylesheet
- assert compile rejects when @plugin is used without providing loadModule
- assert compile returns compiler object with sync build method after resolving stylesheets and plugins
- assert compiler.build emits CSS rules matching candidate list and resolves @theme variables and @utility rules
- assert compiler.build ignores invalid and unreferenced candidates without error
파일
- NOTES.md
- csx.json
- package-lock.json
- package.json
- test/contract.mjs
소스
# Notes: tailwindcss v4 Programmatic API & Default Export Trap
## search_known_solution Response
`search_known_solution` found sample `sha256:52605f9f976b90b774ec86bcad38e5a02628014fd02d62a8b0b8937afdd907fc` ("Generate CSS with tailwind v4, which replaced tailwind.config.js with CSS-first config" demonstrating `@tailwindcss/postcss` integration with PostCSS). This sample addresses the core `tailwindcss` package's programmatic JS compilation API (`compile`, `loadStylesheet`, `loadModule`, `compiler.build`) and its default export trap.
## What a Model Would Have Written Instead
A model expecting Tailwind CSS v3 conventions reaches for `import tailwindcss from 'tailwindcss'` and invokes it as a PostCSS plugin (`tailwindcss(config)`), or attempts programmatic compilation via `await compile(css)` expecting automatic filesystem resolution or a direct CSS string return value.
## How the Wrong Version Fails
Loudly at runtime: calling the default export throws `Error: It looks like you're trying to use 'tailwindcss' directly as a PostCSS plugin...` because PostCSS integration moved to `@tailwindcss/postcss`, and calling `compile()` with `@import` or `@plugin` without custom `loadStylesheet` / `loadModule` callbacks throws `Error: No 'loadStylesheet' function provided to 'compile'` or `Error: No 'loadModule' function provided to 'compile'` as the v4 compiler is decoupled from filesystem I/O.
{"case":{"caseId":"case:sha256:ee1aaf2f33c7f0b23b36e6f947131a3b86bddbd20c8d01a03c0116fb25c96b2a","contract":["assert default export throws when invoked as PostCSS plugin directing callers to @tailwindcss/postcss","assert compile rejects when @import is used without providing loadStylesheet","assert compile rejects when @plugin is used without providing loadModule","assert compile returns compiler object with sync build method after resolving stylesheets and plugins","assert compiler.build emits CSS rules matching candidate list and resolves @theme variables and @utility rules","assert compiler.build ignores invalid and unreferenced candidates without error"],"goal":"Compile CSS programmatically with tailwindcss v4 using compile, loadStylesheet, loadModule, and synchronous compiler.build instead of invoking default export","kind":"HOW","packages":["pkg:npm/tailwindcss@4.3.3"],"schemaVersion":1,"symbols":["tailwindcss","compile","loadStylesheet","loadModule","build","default"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/tailwindcss@4.3.3"],"schemaVersion":1,"symbols":["tailwindcss","compile","loadStylesheet","loadModule","build","default"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-tailwindcss-api",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-tailwindcss-api",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"tailwindcss": "4.3.3"
}
},
"node_modules/tailwindcss": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz",
"integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==",
"license": "MIT"
}
}
}
{
"name": "npm-tailwindcss-api",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"dependencies": {
"tailwindcss": "4.3.3"
}
}
import { strict as assert } from 'node:assert';
import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import tailwindDefault, { compile } from 'tailwindcss';
import plugin from 'tailwindcss/plugin';
// 1. Assert default export throws when invoked as PostCSS plugin
assert.strictEqual(typeof tailwindDefault, 'function', 'default export should be a function');
assert.throws(
() => {
tailwindDefault();
},
{
name: 'Error',
message: /PostCSS plugin has moved to a separate package.*@tailwindcss\/postcss/,
},
'calling tailwindcss default export must throw PostCSS plugin deprecation error'
);
// 2. Assert compile throws when @import is present without loadStylesheet
await assert.rejects(
async () => {
await compile('@import "tailwindcss";', { base: process.cwd() });
},
{
name: 'Error',
message: /No `loadStylesheet` function provided to `compile`/,
},
'compile must reject with missing loadStylesheet error when @import is used without loader'
);
// 3. Assert compile throws when @plugin is present without loadModule
const tailwindPkgDir = path.dirname(fileURLToPath(import.meta.resolve('tailwindcss/package.json')));
async function mockLoadStylesheet(id, base) {
if (id === 'tailwindcss' || id === 'tailwindcss/index.css') {
const cssPath = path.join(tailwindPkgDir, 'index.css');
const content = await fs.readFile(cssPath, 'utf8');
return { path: cssPath, base: tailwindPkgDir, content };
}
const resolved = path.resolve(base, id);
const content = await fs.readFile(resolved, 'utf8');
return { path: resolved, base: path.dirname(resolved), content };
}
await assert.rejects(
async () => {
await compile('@import "tailwindcss";\n@plugin "custom-plugin";', {
base: process.cwd(),
loadStylesheet: mockLoadStylesheet,
});
},
{
name: 'Error',
message: /No `loadModule` function provided to `compile`/,
},
'compile must reject with missing loadModule error when @plugin is used without loader'
);
// 4. Set up custom plugin and compile with both loadStylesheet and loadModule
const customPlugin = plugin(function ({ addUtilities }) {
addUtilities({
'.skew-15': {
transform: 'skewY(15deg)',
},
});
});
async function mockLoadModule(id, base, resourceHint) {
if (id === 'custom-plugin') {
return {
path: 'virtual:custom-plugin',
base,
module: customPlugin,
};
}
throw new Error(`Unknown module: ${id}`);
}
const inputCss = `
@import "tailwindcss";
@plugin "custom-plugin";
@theme {
--color-accent: #e11d48;
}
@utility btn-primary {
background-color: var(--color-accent);
padding: 0.5rem 1rem;
}
`;
const compiler = await compile(inputCss, {
base: process.cwd(),
loadStylesheet: mockLoadStylesheet,
loadModule: mockLoadModule,
});
// Assert shape of returned compiler object
assert.strictEqual(typeof compiler, 'object', 'compile must resolve to compiler object');
assert.strictEqual(typeof compiler.build, 'function', 'compiler must expose a build function');
assert.ok(Array.isArray(compiler.sources), 'compiler must expose sources array');
// 5. Assert compiler.build generates CSS for requested candidates and custom definitions
const candidates = [
'btn-primary',
'skew-15',
'hover:skew-15',
'text-accent',
'p-4',
'opacity-50',
'nonexistent-helper-class',
];
const outputCss = compiler.build(candidates);
assert.strictEqual(typeof outputCss, 'string', 'build must return a CSS string synchronously');
// Assert custom utility and theme variables are emitted
assert.ok(outputCss.includes('.btn-primary'), 'emits .btn-primary utility class');
assert.ok(outputCss.includes('--color-accent: #e11d48') || outputCss.includes('#e11d48'), 'emits @theme token definition');
assert.ok(outputCss.includes('var(--color-accent)'), 'btn-primary references theme custom property');
// Assert plugin utility and variant are emitted
assert.ok(outputCss.includes('skewY(15deg)'), 'emits skew-15 transform from JS plugin');
assert.ok(outputCss.includes('.hover\\:skew-15:hover'), 'emits hover variant for plugin utility');
// Assert standard utility classes are emitted
assert.ok(outputCss.includes('.text-accent'), 'emits text-accent color utility');
assert.ok(outputCss.includes('.p-4'), 'emits p-4 padding utility');
assert.ok(outputCss.includes('.opacity-50'), 'emits opacity-50 utility');
// 6. Assert unrequested/unscanned utilities and invalid candidates are NOT emitted
assert.ok(!outputCss.includes('nonexistent-helper-class'), 'ignores invalid candidates');
assert.ok(!outputCss.includes('.m-8'), 'does not emit unrequested m-8 utility');
assert.ok(!outputCss.includes('.rotate-45'), 'does not emit unrequested rotate-45 utility');
console.log('CONTRACT PASS: tailwindcss programmatic API behaves as specified');