@sylphx/silk-vite-plugin 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -0
- package/dist/index.d.ts +32 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +79 -4
- package/package.json +2 -1
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# @sylphx/silk-vite-plugin
|
|
2
|
+
|
|
3
|
+
Vite plugin for Silk - enables build-time CSS extraction and optimization.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @sylphx/silk @sylphx/silk-vite-plugin
|
|
9
|
+
# or
|
|
10
|
+
bun add @sylphx/silk @sylphx/silk-vite-plugin
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
**vite.config.ts:**
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { defineConfig } from 'vite'
|
|
19
|
+
import { silk } from '@sylphx/silk-vite-plugin'
|
|
20
|
+
|
|
21
|
+
export default defineConfig({
|
|
22
|
+
plugins: [
|
|
23
|
+
silk({
|
|
24
|
+
outputFile: 'silk.css', // Output CSS file
|
|
25
|
+
inject: true, // Auto-inject CSS
|
|
26
|
+
minify: true, // Minify CSS in production
|
|
27
|
+
watch: true // Watch for changes
|
|
28
|
+
})
|
|
29
|
+
]
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Import CSS in your app:**
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import './silk.css'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- ✅ **Build-time Extraction** - Zero runtime CSS-in-JS overhead
|
|
42
|
+
- ✅ **Auto Injection** - Automatically inject CSS into HTML
|
|
43
|
+
- ✅ **Production Optimization** - Minification and deduplication
|
|
44
|
+
- ✅ **Hot Module Replacement** - Watch mode for development
|
|
45
|
+
- ✅ **TypeScript Support** - Full type safety
|
|
46
|
+
|
|
47
|
+
## Options
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
interface SilkPluginOptions {
|
|
51
|
+
outputFile?: string // Output CSS file (default: 'silk.css')
|
|
52
|
+
inject?: boolean // Auto-inject CSS (default: true)
|
|
53
|
+
minify?: boolean // Minify CSS (default: based on mode)
|
|
54
|
+
watch?: boolean // Watch for changes (default: true)
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Ecosystem
|
|
59
|
+
|
|
60
|
+
### Core
|
|
61
|
+
- **[@sylphx/silk](https://www.npmjs.com/package/@sylphx/silk)** - Core styling system
|
|
62
|
+
|
|
63
|
+
### Framework Integrations
|
|
64
|
+
- **[@sylphx/silk-react](https://www.npmjs.com/package/@sylphx/silk-react)** - React bindings
|
|
65
|
+
- **[@sylphx/silk-vue](https://www.npmjs.com/package/@sylphx/silk-vue)** - Vue 3 Composition API
|
|
66
|
+
- **[@sylphx/silk-svelte](https://www.npmjs.com/package/@sylphx/silk-svelte)** - Svelte reactive stores
|
|
67
|
+
- **[@sylphx/silk-solid](https://www.npmjs.com/package/@sylphx/silk-solid)** - Solid.js fine-grained reactivity
|
|
68
|
+
|
|
69
|
+
### Meta-Framework Plugins
|
|
70
|
+
- **[@sylphx/silk-nextjs](https://www.npmjs.com/package/@sylphx/silk-nextjs)** - Next.js App Router & RSC
|
|
71
|
+
- **[@sylphx/silk-remix](https://www.npmjs.com/package/@sylphx/silk-remix)** - Remix streaming SSR
|
|
72
|
+
- **[@sylphx/silk-astro](https://www.npmjs.com/package/@sylphx/silk-astro)** - Astro islands architecture
|
|
73
|
+
|
|
74
|
+
## Documentation
|
|
75
|
+
|
|
76
|
+
Full documentation: [GitHub Repository](https://github.com/sylphxltd/silk)
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
MIT © [SylphX Ltd](https://sylphx.com)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @sylphx/silk-vite-plugin
|
|
3
|
-
* Build-time CSS extraction
|
|
3
|
+
* Build-time CSS extraction with pre-compression (15-25% smaller)
|
|
4
4
|
*/
|
|
5
5
|
import type { Plugin } from 'vite';
|
|
6
|
+
export interface CompressionOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Enable Brotli compression (.css.br)
|
|
9
|
+
* 15-25% smaller than gzip, 70% compression for CSS
|
|
10
|
+
* @default true
|
|
11
|
+
*/
|
|
12
|
+
brotli?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Brotli quality (0-11, higher = better compression but slower)
|
|
15
|
+
* Use 11 for production (static compression, no runtime cost)
|
|
16
|
+
* @default 11
|
|
17
|
+
*/
|
|
18
|
+
brotliQuality?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Enable gzip compression (.css.gz)
|
|
21
|
+
* Fallback for older servers
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
gzip?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Gzip level (0-9)
|
|
27
|
+
* @default 9
|
|
28
|
+
*/
|
|
29
|
+
gzipLevel?: number;
|
|
30
|
+
}
|
|
6
31
|
export interface SilkPluginOptions {
|
|
7
32
|
/**
|
|
8
33
|
* Output CSS file path (relative to outDir)
|
|
@@ -24,6 +49,12 @@ export interface SilkPluginOptions {
|
|
|
24
49
|
* @default true
|
|
25
50
|
*/
|
|
26
51
|
watch?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Pre-compression options (Brotli + gzip)
|
|
54
|
+
* Generates .br and .gz files for web servers
|
|
55
|
+
* @default { brotli: true, gzip: true }
|
|
56
|
+
*/
|
|
57
|
+
compression?: CompressionOptions;
|
|
27
58
|
}
|
|
28
59
|
export declare function silk(options?: SilkPluginOptions): Plugin;
|
|
29
60
|
export default silk;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAA;AAOjD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IAEf;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAA;CACjC;AAED,wBAAgB,IAAI,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAoN5D;AAED,eAAe,IAAI,CAAA;AAEnB;;;GAGG;AACH,eAAO,MAAM,UAAU,iVAYtB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @sylphx/silk-vite-plugin
|
|
3
|
-
* Build-time CSS extraction
|
|
3
|
+
* Build-time CSS extraction with pre-compression (15-25% smaller)
|
|
4
4
|
*/
|
|
5
5
|
import { cssRules } from '@sylphx/silk';
|
|
6
|
+
import { compress } from 'brotli-wasm';
|
|
7
|
+
import { gzipSync } from 'node:zlib';
|
|
6
8
|
export function silk(options = {}) {
|
|
7
|
-
const { outputFile = 'silk.css', inject = true, minify, watch = true } = options;
|
|
9
|
+
const { outputFile = 'silk.css', inject = true, minify, watch = true, compression = {} } = options;
|
|
10
|
+
const compressionConfig = {
|
|
11
|
+
brotli: compression.brotli ?? true,
|
|
12
|
+
brotliQuality: compression.brotliQuality ?? 11,
|
|
13
|
+
gzip: compression.gzip ?? true,
|
|
14
|
+
gzipLevel: compression.gzipLevel ?? 9,
|
|
15
|
+
};
|
|
8
16
|
let server;
|
|
9
17
|
let isBuild = false;
|
|
10
18
|
const cssCache = new Set();
|
|
19
|
+
/**
|
|
20
|
+
* Generate compressed versions of CSS
|
|
21
|
+
*/
|
|
22
|
+
async function generateCompressedAssets(css, fileName) {
|
|
23
|
+
const outputs = [];
|
|
24
|
+
// Generate Brotli (.br)
|
|
25
|
+
if (compressionConfig.brotli) {
|
|
26
|
+
try {
|
|
27
|
+
const compressed = await compress(Buffer.from(css, 'utf-8'), {
|
|
28
|
+
quality: compressionConfig.brotliQuality,
|
|
29
|
+
});
|
|
30
|
+
outputs.push({
|
|
31
|
+
fileName: `${fileName}.br`,
|
|
32
|
+
source: Buffer.from(compressed),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.warn('Brotli compression failed:', error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Generate gzip (.gz)
|
|
40
|
+
if (compressionConfig.gzip) {
|
|
41
|
+
try {
|
|
42
|
+
const compressed = gzipSync(css, { level: compressionConfig.gzipLevel });
|
|
43
|
+
outputs.push({
|
|
44
|
+
fileName: `${fileName}.gz`,
|
|
45
|
+
source: compressed,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.warn('Gzip compression failed:', error);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return outputs;
|
|
53
|
+
}
|
|
11
54
|
/**
|
|
12
55
|
* Collect CSS rules from runtime
|
|
13
56
|
*/
|
|
@@ -81,18 +124,40 @@ export function silk(options = {}) {
|
|
|
81
124
|
return `${styleTag}\n${html}`;
|
|
82
125
|
},
|
|
83
126
|
},
|
|
84
|
-
generateBundle(_, bundle) {
|
|
127
|
+
async generateBundle(_, bundle) {
|
|
85
128
|
if (!isBuild)
|
|
86
129
|
return;
|
|
87
130
|
const css = generateCSS();
|
|
88
131
|
if (!css)
|
|
89
132
|
return;
|
|
90
|
-
// Emit CSS file
|
|
133
|
+
// Emit main CSS file
|
|
91
134
|
this.emitFile({
|
|
92
135
|
type: 'asset',
|
|
93
136
|
fileName: outputFile,
|
|
94
137
|
source: css,
|
|
95
138
|
});
|
|
139
|
+
// Generate and emit compressed versions
|
|
140
|
+
const compressedAssets = await generateCompressedAssets(css, outputFile);
|
|
141
|
+
for (const asset of compressedAssets) {
|
|
142
|
+
this.emitFile({
|
|
143
|
+
type: 'asset',
|
|
144
|
+
fileName: asset.fileName,
|
|
145
|
+
source: asset.source,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
// Log compression results
|
|
149
|
+
if (compressedAssets.length > 0) {
|
|
150
|
+
const originalSize = Buffer.byteLength(css, 'utf-8');
|
|
151
|
+
console.log('\n📦 Silk CSS Bundle:');
|
|
152
|
+
console.log(` Original: ${formatBytes(originalSize)} (${outputFile})`);
|
|
153
|
+
for (const asset of compressedAssets) {
|
|
154
|
+
const compressedSize = asset.source.length;
|
|
155
|
+
const savings = ((1 - compressedSize / originalSize) * 100).toFixed(1);
|
|
156
|
+
const ext = asset.fileName.split('.').pop();
|
|
157
|
+
console.log(` ${ext?.toUpperCase()}: ${formatBytes(compressedSize)} (-${savings}%)`);
|
|
158
|
+
}
|
|
159
|
+
console.log('');
|
|
160
|
+
}
|
|
96
161
|
// Update HTML to reference external CSS file
|
|
97
162
|
for (const fileName in bundle) {
|
|
98
163
|
const chunk = bundle[fileName];
|
|
@@ -139,3 +204,13 @@ if (import.meta.hot) {
|
|
|
139
204
|
})
|
|
140
205
|
}
|
|
141
206
|
`;
|
|
207
|
+
/**
|
|
208
|
+
* Format bytes to human-readable format
|
|
209
|
+
*/
|
|
210
|
+
function formatBytes(bytes) {
|
|
211
|
+
if (bytes < 1024)
|
|
212
|
+
return `${bytes}B`;
|
|
213
|
+
if (bytes < 1024 * 1024)
|
|
214
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
215
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
216
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sylphx/silk-vite-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Vite plugin for Silk - Build-time CSS extraction with production optimizations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"silk",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"@sylphx/silk": "workspace:*"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
+
"brotli-wasm": "^3.0.1",
|
|
46
47
|
"typescript": "^5.3.0",
|
|
47
48
|
"vite": "^5.0.0"
|
|
48
49
|
},
|