@stylexjs/unplugin 0.17.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 ADDED
@@ -0,0 +1,66 @@
1
+ # @stylexjs/unplugin
2
+
3
+ Universal bundler plugin for StyleX built on top of unplugin. It compiles StyleX at build time, aggregates CSS from all transformed modules, and appends the result into an existing CSS asset produced by your bundler.
4
+
5
+ - Works with Vite/Rollup and Webpack/Rspack via unplugin.
6
+ - Ensures a single CSS output for StyleX by injecting into one existing CSS file.
7
+
8
+ ## Install
9
+
10
+ ```
11
+ npm i -D @stylexjs/unplugin
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ Vite:
17
+
18
+ ```js
19
+ // vite.config.ts
20
+ import { defineConfig } from 'vite'
21
+ import stylex from '@stylexjs/unplugin'
22
+
23
+ export default defineConfig({
24
+ plugins: [stylex()]
25
+ })
26
+ ```
27
+
28
+ Rollup:
29
+
30
+ ```js
31
+ // rollup.config.mjs
32
+ import stylex from '@stylexjs/unplugin'
33
+
34
+ export default {
35
+ // ...
36
+ plugins: [stylex()],
37
+ }
38
+ ```
39
+
40
+ Webpack:
41
+
42
+ ```js
43
+ // webpack.config.js
44
+ const stylex = require('@stylexjs/unplugin').default
45
+
46
+ module.exports = {
47
+ // ...
48
+ plugins: [stylex()],
49
+ }
50
+ ```
51
+
52
+ ## Options
53
+
54
+ - `dev`: boolean, defaults based on `NODE_ENV`.
55
+ - `importSources`: array of import sources to scan, default `['stylex', '@stylexjs/stylex']`.
56
+ - `useCSSLayers`: boolean, emit CSS layers.
57
+ - `babelConfig`: `{ plugins, presets }` to merge.
58
+ - `unstable_moduleResolution`: forward to StyleX Babel plugin.
59
+ - `lightningcssOptions`: pass-through options for lightningcss.
60
+ - `cssInjectionTarget`: optional `(fileName: string) => boolean` to pick a CSS asset to append to. If not provided, the plugin picks `index.css`, `style.css`, or the first `.css` asset.
61
+
62
+ ## Notes
63
+
64
+ - The plugin always aggregates all StyleX CSS across modules in a compilation and injects it into one CSS asset. With multiple outputs (e.g. client/SSR), each output will get its own aggregated CSS.
65
+ - If the bundler does not produce any CSS assets, the plugin logs a warning and skips injection.
66
+
package/lib/consts.js ADDED
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.VIRTUAL_STYLEX_RUNTIME_SCRIPT = exports.VIRTUAL_STYLEX_CSS_ONLY_SCRIPT = exports.DEV_RUNTIME_SCRIPT = exports.DEV_RUNTIME_PATH = exports.DEV_CSS_PATH = exports.DEV_AFTER_UPDATE_DELAY = void 0;
7
+ const DEV_CSS_PATH = exports.DEV_CSS_PATH = '/virtual:stylex.css';
8
+ const DEV_RUNTIME_PATH = exports.DEV_RUNTIME_PATH = '/virtual:stylex.js';
9
+ const DEV_AFTER_UPDATE_DELAY = exports.DEV_AFTER_UPDATE_DELAY = 180;
10
+ const VIRTUAL_STYLEX_RUNTIME_SCRIPT = exports.VIRTUAL_STYLEX_RUNTIME_SCRIPT = `
11
+ const STYLE_ID = '__stylex_virtual__';
12
+ const DEV_CSS_PATH = '${DEV_CSS_PATH}';
13
+ const AFTER_UPDATE_DELAY = ${DEV_AFTER_UPDATE_DELAY};
14
+ let lastCSS = '';
15
+
16
+ function ensure(){
17
+ let el=document.getElementById(STYLE_ID);
18
+ if (!el) {
19
+ el=document.createElement('style');
20
+ el.id=STYLE_ID;document.head.appendChild(el);
21
+ }
22
+ return el;
23
+ }
24
+
25
+ function disableLink() {
26
+ try{
27
+ const links = [...document.querySelectorAll('link[rel="stylesheet"]')];
28
+ for (const l of links) {
29
+ if(typeof l.href==='string' && l.href.includes(DEV_CSS_PATH)) {
30
+ l.disabled=true;
31
+ }
32
+ }
33
+ } catch {}
34
+ }
35
+
36
+ async function fetchCSS() {
37
+ const t = Date.now();
38
+ const r = await fetch(DEV_CSS_PATH + '?t=' + t, {cache: 'no-store'});
39
+ return r.text();
40
+ }
41
+
42
+ async function update(){
43
+ try {
44
+ const css = await fetchCSS();
45
+ if (css!==lastCSS) {
46
+ ensure().textContent = css;
47
+ disableLink();
48
+ lastCSS = css;
49
+ }
50
+ } catch {}
51
+ }
52
+
53
+ update();
54
+
55
+ if(import.meta.hot){
56
+ import.meta.hot.on('stylex:css-update', update);
57
+ import.meta.hot.on('vite:afterUpdate', () => setTimeout(update, AFTER_UPDATE_DELAY));
58
+ import.meta.hot.dispose(() => {
59
+ const el = document.getElementById(STYLE_ID);
60
+ if (el && el.parentNode) el.parentNode.removeChild(el);
61
+ });
62
+ }
63
+
64
+ export {};
65
+ `;
66
+ const VIRTUAL_STYLEX_CSS_ONLY_SCRIPT = exports.VIRTUAL_STYLEX_CSS_ONLY_SCRIPT = `
67
+ const DEV_CSS_PATH='${DEV_CSS_PATH}';
68
+
69
+ function bust() {
70
+ try {
71
+ const links = [...document.querySelectorAll('link[rel="stylesheet"]')];
72
+ for (const l of links) {
73
+ if (typeof l.href==='string' && l.href.includes(DEV_CSS_PATH)) {
74
+ const u = new URL(l.href, location.origin);
75
+ u.searchParams.set('t', String(Date.now()));
76
+ l.href=u.pathname+u.search;
77
+ }
78
+ }
79
+ } catch {}
80
+ }
81
+
82
+ // initial attempt to ensure we have a fresh version after client connects
83
+ if (document.readyState !== 'loading') {
84
+ bust();
85
+ } else {
86
+ document.addEventListener('DOMContentLoaded', bust);
87
+ }
88
+
89
+ if (import.meta.hot){
90
+ import.meta.hot.on('stylex:css-update', bust);
91
+ }
92
+
93
+ export {};
94
+ `;
95
+ const DEV_RUNTIME_SCRIPT = exports.DEV_RUNTIME_SCRIPT = `
96
+ const STYLE_ID='__stylex_virtual__';
97
+ const DEV_CSS_PATH = '${DEV_CSS_PATH}';
98
+ const AFTER_UPDATE_DELAY = 180;
99
+ const POLL_INTERVAL = 800;
100
+ let lastCSS='';
101
+
102
+ function ensure() {
103
+ let el = document.getElementById(STYLE_ID);
104
+ if(!el){
105
+ el = document.createElement('style');
106
+ el.id = STYLE_ID;
107
+ document.head.appendChild(el);
108
+ }
109
+ return el;
110
+ }
111
+ function disableLink() {
112
+ try {
113
+ const links = [ ...document.querySelectorAll('link[rel="stylesheet"]') ];
114
+ for(const l of links) {
115
+ if(typeof l.href==='string' && l.href.includes(DEV_CSS_PATH)) {
116
+ l.disabled=true;
117
+ }
118
+ }
119
+ } catch {
120
+ // ignore
121
+ }
122
+ }
123
+ async function fetchCSS(){
124
+ const t=Date.now();
125
+ const r=await fetch(DEV_CSS_PATH+'?t='+t,{cache:'no-store'});
126
+ return r.text();
127
+ }
128
+ async function update(){
129
+ try {
130
+ const css=await fetchCSS();
131
+ if(css!==lastCSS){
132
+ ensure().textContent = css;
133
+ disableLink();
134
+ lastCSS = css;
135
+ }
136
+ } catch {}
137
+ }
138
+ update();
139
+
140
+ if(import.meta.hot){
141
+ import.meta.hot.on('stylex:css-update', update);
142
+ import.meta.hot.on('vite:afterUpdate',() => setTimeout(update, AFTER_UPDATE_DELAY));
143
+ }
144
+ `;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.devInjectMiddleware = void 0;
7
+ var _consts = require("./consts");
8
+ const devInjectMiddleware = (req, res, next) => {
9
+ if (!req.url) return next();
10
+ if (req.url.startsWith(_consts.DEV_RUNTIME_PATH)) {
11
+ res.statusCode = 200;
12
+ res.setHeader('Content-Type', 'application/javascript');
13
+ res.end(_consts.DEV_RUNTIME_SCRIPT);
14
+ return;
15
+ }
16
+ next();
17
+ };
18
+ exports.devInjectMiddleware = devInjectMiddleware;
@@ -0,0 +1,138 @@
1
+ export const DEV_CSS_PATH = '/virtual:stylex.css';
2
+ export const DEV_RUNTIME_PATH = '/virtual:stylex.js';
3
+ export const DEV_AFTER_UPDATE_DELAY = 180;
4
+ export const VIRTUAL_STYLEX_RUNTIME_SCRIPT = `
5
+ const STYLE_ID = '__stylex_virtual__';
6
+ const DEV_CSS_PATH = '${DEV_CSS_PATH}';
7
+ const AFTER_UPDATE_DELAY = ${DEV_AFTER_UPDATE_DELAY};
8
+ let lastCSS = '';
9
+
10
+ function ensure(){
11
+ let el=document.getElementById(STYLE_ID);
12
+ if (!el) {
13
+ el=document.createElement('style');
14
+ el.id=STYLE_ID;document.head.appendChild(el);
15
+ }
16
+ return el;
17
+ }
18
+
19
+ function disableLink() {
20
+ try{
21
+ const links = [...document.querySelectorAll('link[rel="stylesheet"]')];
22
+ for (const l of links) {
23
+ if(typeof l.href==='string' && l.href.includes(DEV_CSS_PATH)) {
24
+ l.disabled=true;
25
+ }
26
+ }
27
+ } catch {}
28
+ }
29
+
30
+ async function fetchCSS() {
31
+ const t = Date.now();
32
+ const r = await fetch(DEV_CSS_PATH + '?t=' + t, {cache: 'no-store'});
33
+ return r.text();
34
+ }
35
+
36
+ async function update(){
37
+ try {
38
+ const css = await fetchCSS();
39
+ if (css!==lastCSS) {
40
+ ensure().textContent = css;
41
+ disableLink();
42
+ lastCSS = css;
43
+ }
44
+ } catch {}
45
+ }
46
+
47
+ update();
48
+
49
+ if(import.meta.hot){
50
+ import.meta.hot.on('stylex:css-update', update);
51
+ import.meta.hot.on('vite:afterUpdate', () => setTimeout(update, AFTER_UPDATE_DELAY));
52
+ import.meta.hot.dispose(() => {
53
+ const el = document.getElementById(STYLE_ID);
54
+ if (el && el.parentNode) el.parentNode.removeChild(el);
55
+ });
56
+ }
57
+
58
+ export {};
59
+ `;
60
+ export const VIRTUAL_STYLEX_CSS_ONLY_SCRIPT = `
61
+ const DEV_CSS_PATH='${DEV_CSS_PATH}';
62
+
63
+ function bust() {
64
+ try {
65
+ const links = [...document.querySelectorAll('link[rel="stylesheet"]')];
66
+ for (const l of links) {
67
+ if (typeof l.href==='string' && l.href.includes(DEV_CSS_PATH)) {
68
+ const u = new URL(l.href, location.origin);
69
+ u.searchParams.set('t', String(Date.now()));
70
+ l.href=u.pathname+u.search;
71
+ }
72
+ }
73
+ } catch {}
74
+ }
75
+
76
+ // initial attempt to ensure we have a fresh version after client connects
77
+ if (document.readyState !== 'loading') {
78
+ bust();
79
+ } else {
80
+ document.addEventListener('DOMContentLoaded', bust);
81
+ }
82
+
83
+ if (import.meta.hot){
84
+ import.meta.hot.on('stylex:css-update', bust);
85
+ }
86
+
87
+ export {};
88
+ `;
89
+ export const DEV_RUNTIME_SCRIPT = `
90
+ const STYLE_ID='__stylex_virtual__';
91
+ const DEV_CSS_PATH = '${DEV_CSS_PATH}';
92
+ const AFTER_UPDATE_DELAY = 180;
93
+ const POLL_INTERVAL = 800;
94
+ let lastCSS='';
95
+
96
+ function ensure() {
97
+ let el = document.getElementById(STYLE_ID);
98
+ if(!el){
99
+ el = document.createElement('style');
100
+ el.id = STYLE_ID;
101
+ document.head.appendChild(el);
102
+ }
103
+ return el;
104
+ }
105
+ function disableLink() {
106
+ try {
107
+ const links = [ ...document.querySelectorAll('link[rel="stylesheet"]') ];
108
+ for(const l of links) {
109
+ if(typeof l.href==='string' && l.href.includes(DEV_CSS_PATH)) {
110
+ l.disabled=true;
111
+ }
112
+ }
113
+ } catch {
114
+ // ignore
115
+ }
116
+ }
117
+ async function fetchCSS(){
118
+ const t=Date.now();
119
+ const r=await fetch(DEV_CSS_PATH+'?t='+t,{cache:'no-store'});
120
+ return r.text();
121
+ }
122
+ async function update(){
123
+ try {
124
+ const css=await fetchCSS();
125
+ if(css!==lastCSS){
126
+ ensure().textContent = css;
127
+ disableLink();
128
+ lastCSS = css;
129
+ }
130
+ } catch {}
131
+ }
132
+ update();
133
+
134
+ if(import.meta.hot){
135
+ import.meta.hot.on('stylex:css-update', update);
136
+ import.meta.hot.on('vite:afterUpdate',() => setTimeout(update, AFTER_UPDATE_DELAY));
137
+ }
138
+ `;
@@ -0,0 +1,11 @@
1
+ import { DEV_RUNTIME_SCRIPT, DEV_RUNTIME_PATH } from "./consts.mjs";
2
+ export const devInjectMiddleware = (req, res, next) => {
3
+ if (!req.url) return next();
4
+ if (req.url.startsWith(DEV_RUNTIME_PATH)) {
5
+ res.statusCode = 200;
6
+ res.setHeader('Content-Type', 'application/javascript');
7
+ res.end(DEV_RUNTIME_SCRIPT);
8
+ return;
9
+ }
10
+ next();
11
+ };