diff --git a/.changeset/modern-kids-obey.md b/.changeset/modern-kids-obey.md
new file mode 100644
index 00000000..18c4fff8
--- /dev/null
+++ b/.changeset/modern-kids-obey.md
@@ -0,0 +1,5 @@
+---
+"@devup-ui/wasm": patch
+---
+
+Optimize keyframe name
diff --git a/.changeset/neat-donuts-fix.md b/.changeset/neat-donuts-fix.md
new file mode 100644
index 00000000..540a24c2
--- /dev/null
+++ b/.changeset/neat-donuts-fix.md
@@ -0,0 +1,10 @@
+---
+"@devup-ui/rsbuild-plugin": patch
+"@devup-ui/webpack-plugin": patch
+"@devup-ui/wasm": patch
+"@devup-ui/next-plugin": patch
+"@devup-ui/vite-plugin": patch
+"@devup-ui/components": patch
+---
+
+Feat split css
diff --git a/.changeset/petite-dragons-carry.md b/.changeset/petite-dragons-carry.md
new file mode 100644
index 00000000..8cea4206
--- /dev/null
+++ b/.changeset/petite-dragons-carry.md
@@ -0,0 +1,8 @@
+---
+"@devup-ui/rsbuild-plugin": patch
+"@devup-ui/webpack-plugin": patch
+"@devup-ui/next-plugin": patch
+"@devup-ui/vite-plugin": patch
+---
+
+Update option
diff --git a/Cargo.lock b/Cargo.lock
index 10606525..87f4ef92 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -45,6 +45,15 @@ dependencies = [
"vsimd",
]
+[[package]]
+name = "bimap"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "bitflags"
version = "2.9.1"
@@ -252,8 +261,9 @@ checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
name = "css"
version = "0.1.0"
dependencies = [
+ "bimap",
"once_cell",
- "phf 0.13.1",
+ "phf",
"regex",
"rstest",
"serde",
@@ -264,6 +274,7 @@ dependencies = [
name = "devup-ui-wasm"
version = "0.1.0"
dependencies = [
+ "bimap",
"console_error_panic_hook",
"css",
"extractor",
@@ -316,7 +327,7 @@ dependencies = [
"oxc_parser",
"oxc_span",
"oxc_syntax",
- "phf 0.13.1",
+ "phf",
"rstest",
"serial_test",
"strum",
@@ -647,9 +658,9 @@ dependencies = [
[[package]]
name = "oxc_allocator"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e887a8496b18a4bce4a760ae2dbd50e5137fa2a27ee99087797d7b8e860a7b5c"
+checksum = "1dad79355dfb8a36a772d2aa758e429ae02f533d33c314f538d20ef188db0147"
dependencies = [
"allocator-api2",
"bumpalo",
@@ -660,9 +671,9 @@ dependencies = [
[[package]]
name = "oxc_ast"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "931e1fae25d9669204681577381f6e90d2c9fe502d306c862f46ff72bcef8cf7"
+checksum = "a9987f0e42aef7eb2deccec8dec26b17c658c8616bb7260a53037b765db708f0"
dependencies = [
"bitflags",
"oxc_allocator",
@@ -676,11 +687,11 @@ dependencies = [
[[package]]
name = "oxc_ast_macros"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5958a8ac69a955048dabcfcbf8af791dbb7f598bbea5bae33243240f3846457c"
+checksum = "08b4b00b34d96543ca44ce82e2e48098197b651b639ff211df48d1725215db08"
dependencies = [
- "phf 0.12.1",
+ "phf",
"proc-macro2",
"quote",
"syn",
@@ -688,9 +699,9 @@ dependencies = [
[[package]]
name = "oxc_ast_visit"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95d2ce2cb5be550d7a94fc3b927d4247d69aea57943baafbf6547362831e69a5"
+checksum = "522d1393ad48548702a8ff9b747100e9c0959dbd37cd677e12d9ffb5eb7f6490"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -700,9 +711,9 @@ dependencies = [
[[package]]
name = "oxc_cfg"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d950f4f67648b1995c836bd96ae423cdf6800b2332d1ba5b18fd81166daad2f1"
+checksum = "0bdf2665550303cfdc9843e4a7f6d88f3216075f42e38b2c2cc0224bf0ba1632"
dependencies = [
"bitflags",
"itertools 0.14.0",
@@ -715,9 +726,9 @@ dependencies = [
[[package]]
name = "oxc_codegen"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e252dc98109ed7ee39120255f566ee13f8e6016d86fa38137e99768165f60e7"
+checksum = "081b3d96db8e9f1677d56a959873f971285bf565276c11d61e7b61affee15790"
dependencies = [
"bitflags",
"cow-utils",
@@ -737,15 +748,15 @@ dependencies = [
[[package]]
name = "oxc_data_structures"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b3258dc882e0348934e2a9973cd0d9e3c465642b729842320d23abf835175a"
+checksum = "e2d124d0e1498479cd9410b494fe12d4018a1db55400508c0f8d9d0817934dc6"
[[package]]
name = "oxc_diagnostics"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dc24fdf0407c9ecb202efb99fa9870f3623994ae8daae56e696a511894d67ba"
+checksum = "0befbac8654a5a1cef8ee9b31ff6cf669c9abde763f30fb12c2c284993c86498"
dependencies = [
"cow-utils",
"oxc-miette",
@@ -754,9 +765,9 @@ dependencies = [
[[package]]
name = "oxc_ecmascript"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61cfc9801af5b0068e11061ff8100fb38c2ca0875c696aa405b5505d212b5e2f"
+checksum = "1c59f9f0cfb236ae7b1e8f1be956f3585078256d8a4f8881cbe3b02edd7c57b1"
dependencies = [
"cow-utils",
"num-bigint",
@@ -769,9 +780,9 @@ dependencies = [
[[package]]
name = "oxc_estree"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bac265e2cd8c77ac8d4230f1538e8ff9f6f5d9e41b9107af58f8d3c4626b028"
+checksum = "70bffad4cb83abd3db5310ccdb5f298b19377244d43eda7ec3912b544452bcb2"
[[package]]
name = "oxc_index"
@@ -781,9 +792,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392"
[[package]]
name = "oxc_parser"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b4427e7c4d4507bb4561c113e25bbbb737d03355f311d3fb606f0029fdcb3f6"
+checksum = "90a651f61f532b9c5485c65786363b42c3a711ba60871746740409f381b49bea"
dependencies = [
"bitflags",
"cow-utils",
@@ -804,25 +815,25 @@ dependencies = [
[[package]]
name = "oxc_regular_expression"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17ec07cb1081ed5798e2ef7d3e10154784cd1bf47c5170ff3d519d44bc97ad07"
+checksum = "8b97261c926b800200a07309eefc7b5801432ed3a91b76b5ea9780f97fc961d4"
dependencies = [
"bitflags",
"oxc_allocator",
"oxc_ast_macros",
"oxc_diagnostics",
"oxc_span",
- "phf 0.12.1",
+ "phf",
"rustc-hash",
"unicode-id-start",
]
[[package]]
name = "oxc_semantic"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8191888545927293275ff32593584327dbd2c5805345abba1236f6febe55b567"
+checksum = "b594d9a93b359ba5421118c0cc2664795138e171ffb60c345e621fc8ea4cf4dd"
dependencies = [
"itertools 0.14.0",
"oxc_allocator",
@@ -835,7 +846,7 @@ dependencies = [
"oxc_index",
"oxc_span",
"oxc_syntax",
- "phf 0.12.1",
+ "phf",
"rustc-hash",
"self_cell",
]
@@ -856,9 +867,9 @@ dependencies = [
[[package]]
name = "oxc_span"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "008d14e804d79adac31c5cb5b27fbfde52055a0cf86276c9b822cfa40b24d75c"
+checksum = "1948fe931738f956b2c673804bce7f93b3dc8fcb4575485ef65adc15fcae3d92"
dependencies = [
"compact_str",
"oxc-miette",
@@ -869,9 +880,9 @@ dependencies = [
[[package]]
name = "oxc_syntax"
-version = "0.82.3"
+version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "675313926fe94e71b9cdf6ed0338e0bfb40e827e2b5fd0c65a059aff002e7fa2"
+checksum = "ad28a43d5b4ccf4f286b68f377d364790c098128729b44a52421cf9de2ce3ec0"
dependencies = [
"bitflags",
"cow-utils",
@@ -883,7 +894,7 @@ dependencies = [
"oxc_estree",
"oxc_index",
"oxc_span",
- "phf 0.12.1",
+ "phf",
"rustc-hash",
"unicode-id-start",
]
@@ -929,38 +940,17 @@ dependencies = [
"serde",
]
-[[package]]
-name = "phf"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
-dependencies = [
- "phf_macros 0.12.1",
- "phf_shared 0.12.1",
- "serde",
-]
-
[[package]]
name = "phf"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
dependencies = [
- "phf_macros 0.13.1",
- "phf_shared 0.13.1",
+ "phf_macros",
+ "phf_shared",
"serde",
]
-[[package]]
-name = "phf_generator"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b"
-dependencies = [
- "fastrand",
- "phf_shared 0.12.1",
-]
-
[[package]]
name = "phf_generator"
version = "0.13.1"
@@ -968,20 +958,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
dependencies = [
"fastrand",
- "phf_shared 0.13.1",
-]
-
-[[package]]
-name = "phf_macros"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d713258393a82f091ead52047ca779d37e5766226d009de21696c4e667044368"
-dependencies = [
- "phf_generator 0.12.1",
- "phf_shared 0.12.1",
- "proc-macro2",
- "quote",
- "syn",
+ "phf_shared",
]
[[package]]
@@ -990,22 +967,13 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
dependencies = [
- "phf_generator 0.13.1",
- "phf_shared 0.13.1",
+ "phf_generator",
+ "phf_shared",
"proc-macro2",
"quote",
"syn",
]
-[[package]]
-name = "phf_shared"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
-dependencies = [
- "siphasher",
-]
-
[[package]]
name = "phf_shared"
version = "0.13.1"
diff --git a/apps/landing/next.config.ts b/apps/landing/next.config.ts
index b676aed5..43b915ec 100644
--- a/apps/landing/next.config.ts
+++ b/apps/landing/next.config.ts
@@ -10,11 +10,8 @@ const withMDX = createMDX({
})
export default withMDX(
- DevupUI(
- {
- pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
- output: 'export',
- },
- { include: ['@devup-ui/components', '@devup-ui/reset-css'] },
- ),
+ DevupUI({
+ pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
+ output: 'export',
+ }),
)
diff --git a/apps/landing/package.json b/apps/landing/package.json
index e5c7229a..dbdd0c7a 100644
--- a/apps/landing/package.json
+++ b/apps/landing/package.json
@@ -16,15 +16,15 @@
"@devup-ui/reset-css": "workspace:*",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/react": "^3.1.0",
- "@next/mdx": "^15.5.0",
+ "@next/mdx": "^15.5.2",
"@types/mdx": "^2.0.13",
"body-scroll-lock": "3.1.5",
"clsx": "^2.1.1",
- "next": "^15.5.0",
+ "next": "^15.5.2",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-markdown": "^10.1.0",
- "react-syntax-highlighter": "^15.6.1",
+ "react-syntax-highlighter": "^15.6.6",
"remark-gfm": "^4.0.1"
},
"devDependencies": {
diff --git a/apps/next/package.json b/apps/next/package.json
index 77dc77ba..bb6490a7 100644
--- a/apps/next/package.json
+++ b/apps/next/package.json
@@ -12,7 +12,7 @@
"dependencies": {
"react": "^19.1.1",
"react-dom": "^19.1.1",
- "next": "^15.5.0",
+ "next": "^15.5.2",
"@devup-ui/react": "workspace:*"
},
"devDependencies": {
diff --git a/apps/rsbuild/package.json b/apps/rsbuild/package.json
index 1d7b4c02..372902aa 100644
--- a/apps/rsbuild/package.json
+++ b/apps/rsbuild/package.json
@@ -15,8 +15,8 @@
"@devup-ui/react": "workspace:*"
},
"devDependencies": {
- "@rsbuild/core": "^1.4.15",
- "@rsbuild/plugin-react": "^1.3.5",
+ "@rsbuild/core": "^1.5.1",
+ "@rsbuild/plugin-react": "^1.4.0",
"@devup-ui/rsbuild-plugin": "workspace:*"
}
}
\ No newline at end of file
diff --git a/apps/rsbuild/rsbuild.config.mjs b/apps/rsbuild/rsbuild.config.mjs
index bbf18ab0..761daf4c 100644
--- a/apps/rsbuild/rsbuild.config.mjs
+++ b/apps/rsbuild/rsbuild.config.mjs
@@ -1,7 +1,7 @@
-import { defineConfig } from '@rsbuild/core';
-import { pluginReact } from '@rsbuild/plugin-react';
-import { DevupUIRsbuildPlugin } from '@devup-ui/rsbuild-plugin';
+import { DevupUI } from '@devup-ui/rsbuild-plugin'
+import { defineConfig } from '@rsbuild/core'
+import { pluginReact } from '@rsbuild/plugin-react'
export default defineConfig({
- plugins: [pluginReact(), DevupUIRsbuildPlugin()],
-});
+ plugins: [pluginReact(), DevupUI()],
+})
diff --git a/apps/vite-lib/package.json b/apps/vite-lib/package.json
index de0727b6..04ba5b10 100644
--- a/apps/vite-lib/package.json
+++ b/apps/vite-lib/package.json
@@ -18,7 +18,7 @@
"devDependencies": {
"vite-plugin-dts": "^4.5.4",
"@devup-ui/vite-plugin": "workspace:*",
- "@vitejs/plugin-react": "^5.0.1",
+ "@vitejs/plugin-react": "^5.0.2",
"vite": "^7.1.3",
"typescript": "^5",
"@types/node": "^24",
diff --git a/apps/vite/package.json b/apps/vite/package.json
index 7560f723..1a0829da 100644
--- a/apps/vite/package.json
+++ b/apps/vite/package.json
@@ -18,7 +18,7 @@
"devDependencies": {
"@devup-ui/vite-plugin": "workspace:*",
"vite": "^7.1.3",
- "@vitejs/plugin-react": "^5.0.1",
+ "@vitejs/plugin-react": "^5.0.2",
"typescript": "^5",
"@types/node": "^24",
"@types/react": "^19",
diff --git a/apps/vite/src/App.tsx b/apps/vite/src/App.tsx
index 88f55b93..cd1263fb 100644
--- a/apps/vite/src/App.tsx
+++ b/apps/vite/src/App.tsx
@@ -14,7 +14,7 @@ export default function App() {
hello
-
+ wf
typo
diff --git a/apps/vite/vite.config.ts b/apps/vite/vite.config.ts
index b41e40a9..456eed06 100644
--- a/apps/vite/vite.config.ts
+++ b/apps/vite/vite.config.ts
@@ -8,6 +8,7 @@ export default defineConfig({
react(),
DevupUI({
include: ['vite-lib-example'],
+ // singleCss: true,
}),
],
})
diff --git a/benchmark.js b/benchmark.js
index 01f8a8ce..be81bf39 100644
--- a/benchmark.js
+++ b/benchmark.js
@@ -20,6 +20,11 @@ function clearBuildFile() {
recursive: true,
force: true,
})
+ if (existsSync('./benchmark/next-devup-ui-single/.next'))
+ rmSync('./benchmark/next-devup-ui-single/.next', {
+ recursive: true,
+ force: true,
+ })
if (existsSync('./benchmark/next-mui/.next'))
rmSync('./benchmark/next-mui/.next', {
recursive: true,
@@ -30,6 +35,11 @@ function clearBuildFile() {
recursive: true,
force: true,
})
+ if (existsSync('./benchmark/next-devup-ui-single/df'))
+ rmSync('./benchmark/next-devup-ui-single/df', {
+ recursive: true,
+ force: true,
+ })
}
function checkDirSize(path) {
@@ -81,3 +91,13 @@ execSync('pnpm -F next-devup-ui-benchmark build', {
})
console.timeEnd('devup-ui')
console.info('devup-ui', checkDirSize('./benchmark/next-devup-ui/.next'))
+
+console.time('devup-ui-single')
+execSync('pnpm -F next-devup-ui-single-benchmark build', {
+ stdio: 'inherit',
+})
+console.timeEnd('devup-ui-single')
+console.info(
+ 'devup-ui-single',
+ checkDirSize('./benchmark/next-devup-ui-single/.next'),
+)
diff --git a/benchmark/next-chakra-ui/package.json b/benchmark/next-chakra-ui/package.json
index 6b8d7c04..57b17791 100644
--- a/benchmark/next-chakra-ui/package.json
+++ b/benchmark/next-chakra-ui/package.json
@@ -10,9 +10,9 @@
"lint": "next lint"
},
"dependencies": {
- "@chakra-ui/react": "^3.25.0",
+ "@chakra-ui/react": "^3.26.0",
"@emotion/react": "^11.14.0",
- "next": "^15.5.0",
+ "next": "^15.5.2",
"next-themes": "^0.4.6",
"react": "^19.1.1",
"react-dom": "^19.1.1",
diff --git a/benchmark/next-devup-ui-single/.gitignore b/benchmark/next-devup-ui-single/.gitignore
new file mode 100644
index 00000000..5ef6a520
--- /dev/null
+++ b/benchmark/next-devup-ui-single/.gitignore
@@ -0,0 +1,41 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/versions
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# env files (can opt-in for committing if needed)
+.env*
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/benchmark/next-devup-ui-single/README.md b/benchmark/next-devup-ui-single/README.md
new file mode 100644
index 00000000..665152ea
--- /dev/null
+++ b/benchmark/next-devup-ui-single/README.md
@@ -0,0 +1 @@
+## Nextjs App
diff --git a/benchmark/next-devup-ui-single/next.config.ts b/benchmark/next-devup-ui-single/next.config.ts
new file mode 100644
index 00000000..9e94bd9b
--- /dev/null
+++ b/benchmark/next-devup-ui-single/next.config.ts
@@ -0,0 +1,7 @@
+import { DevupUI } from '@devup-ui/next-plugin'
+
+const nextConfig = {
+ /* config options here */
+}
+
+export default DevupUI(nextConfig, { singleCss: true })
diff --git a/benchmark/next-devup-ui-single/package.json b/benchmark/next-devup-ui-single/package.json
new file mode 100644
index 00000000..7488e9b4
--- /dev/null
+++ b/benchmark/next-devup-ui-single/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "next-devup-ui-single-benchmark",
+ "version": "0.1.0",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build --experimental-debug-memory-usage",
+ "start": "next start",
+ "lint": "eslint"
+ },
+ "dependencies": {
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
+ "next": "^15.5.2",
+ "@devup-ui/react": "workspace:*"
+ },
+ "devDependencies": {
+ "@devup-ui/next-plugin": "workspace:*",
+ "typescript": "^5",
+ "@types/node": "^24",
+ "@types/react": "^19",
+ "@types/react-dom": "^19"
+ }
+}
\ No newline at end of file
diff --git a/benchmark/next-devup-ui-single/public/file.svg b/benchmark/next-devup-ui-single/public/file.svg
new file mode 100644
index 00000000..004145cd
--- /dev/null
+++ b/benchmark/next-devup-ui-single/public/file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/benchmark/next-devup-ui-single/public/globe.svg b/benchmark/next-devup-ui-single/public/globe.svg
new file mode 100644
index 00000000..567f17b0
--- /dev/null
+++ b/benchmark/next-devup-ui-single/public/globe.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/benchmark/next-devup-ui-single/public/next.svg b/benchmark/next-devup-ui-single/public/next.svg
new file mode 100644
index 00000000..5174b28c
--- /dev/null
+++ b/benchmark/next-devup-ui-single/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/benchmark/next-devup-ui-single/public/vercel.svg b/benchmark/next-devup-ui-single/public/vercel.svg
new file mode 100644
index 00000000..77053960
--- /dev/null
+++ b/benchmark/next-devup-ui-single/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/benchmark/next-devup-ui-single/public/window.svg b/benchmark/next-devup-ui-single/public/window.svg
new file mode 100644
index 00000000..b2b2a44f
--- /dev/null
+++ b/benchmark/next-devup-ui-single/public/window.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/benchmark/next-devup-ui-single/src/app/favicon.ico b/benchmark/next-devup-ui-single/src/app/favicon.ico
new file mode 100644
index 00000000..718d6fea
Binary files /dev/null and b/benchmark/next-devup-ui-single/src/app/favicon.ico differ
diff --git a/benchmark/next-devup-ui-single/src/app/layout.tsx b/benchmark/next-devup-ui-single/src/app/layout.tsx
new file mode 100644
index 00000000..6b8b4518
--- /dev/null
+++ b/benchmark/next-devup-ui-single/src/app/layout.tsx
@@ -0,0 +1,18 @@
+import type { Metadata } from 'next'
+
+export const metadata: Metadata = {
+ title: 'Create Next App',
+ description: 'Generated by create next app',
+}
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode
+}>) {
+ return (
+
+
{children}
+
+ )
+}
diff --git a/benchmark/next-devup-ui-single/src/app/page.tsx b/benchmark/next-devup-ui-single/src/app/page.tsx
new file mode 100644
index 00000000..ab9216cc
--- /dev/null
+++ b/benchmark/next-devup-ui-single/src/app/page.tsx
@@ -0,0 +1,51 @@
+'use client'
+
+import { Box, Text } from '@devup-ui/react'
+import { useState } from 'react'
+
+export default function HomePage() {
+ const [color, setColor] = useState('yellow')
+ const [enabled, setEnabled] = useState(false)
+
+ return (
+
+
+ Track & field champions:
+
+
+ hello
+ hello
+
+
text
+
+ hello
+
+
hello
+
+
+ )
+}
diff --git a/benchmark/next-devup-ui-single/tsconfig.json b/benchmark/next-devup-ui-single/tsconfig.json
new file mode 100644
index 00000000..426d9c2d
--- /dev/null
+++ b/benchmark/next-devup-ui-single/tsconfig.json
@@ -0,0 +1,41 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": [
+ "./src/*"
+ ]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ "df/*.d.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
\ No newline at end of file
diff --git a/benchmark/next-devup-ui/package.json b/benchmark/next-devup-ui/package.json
index 88e8e973..ade75d14 100644
--- a/benchmark/next-devup-ui/package.json
+++ b/benchmark/next-devup-ui/package.json
@@ -12,7 +12,7 @@
"dependencies": {
"react": "^19.1.1",
"react-dom": "^19.1.1",
- "next": "^15.5.0",
+ "next": "^15.5.2",
"@devup-ui/react": "workspace:*"
},
"devDependencies": {
diff --git a/benchmark/next-kuma-ui/package.json b/benchmark/next-kuma-ui/package.json
index 2d20bf33..d9d248a2 100644
--- a/benchmark/next-kuma-ui/package.json
+++ b/benchmark/next-kuma-ui/package.json
@@ -12,7 +12,7 @@
"dependencies": {
"react": "^19.1.1",
"react-dom": "^19.1.1",
- "next": "^15.5.0",
+ "next": "^15.5.2",
"@kuma-ui/core": "^1.5.9"
},
"devDependencies": {
diff --git a/benchmark/next-mui/package.json b/benchmark/next-mui/package.json
index 9cd01cc8..8d0ea7bb 100644
--- a/benchmark/next-mui/package.json
+++ b/benchmark/next-mui/package.json
@@ -13,7 +13,7 @@
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/material": "7.3.1",
- "next": "^15.5.0",
+ "next": "^15.5.2",
"next-themes": "^0.4.6",
"react": "^19.1.1",
"react-dom": "^19.1.1",
diff --git a/bindings/devup-ui-wasm/Cargo.toml b/bindings/devup-ui-wasm/Cargo.toml
index 8fbdd2cd..b8502e0d 100644
--- a/bindings/devup-ui-wasm/Cargo.toml
+++ b/bindings/devup-ui-wasm/Cargo.toml
@@ -29,6 +29,7 @@ once_cell = "1.21.3"
js-sys = "0.3.77"
serde_json = "1.0.143"
serde-wasm-bindgen = "0.6.5"
+bimap = { version = "0.6.3", features = ["serde"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.50"
diff --git a/bindings/devup-ui-wasm/src/lib.rs b/bindings/devup-ui-wasm/src/lib.rs
index 930cd73f..1e81040d 100644
--- a/bindings/devup-ui-wasm/src/lib.rs
+++ b/bindings/devup-ui-wasm/src/lib.rs
@@ -1,4 +1,5 @@
use css::class_map::{get_class_map, set_class_map};
+use css::file_map::{get_file_map, get_filename_by_file_num, set_file_map};
use extractor::extract_style::ExtractStyleProperty;
use extractor::extract_style::extract_style_value::ExtractStyleValue;
use extractor::extract_style::style_property::StyleProperty;
@@ -18,6 +19,9 @@ pub struct Output {
styles: HashSet,
map: Option,
default_collected: bool,
+ single_css: bool,
+ filename: String,
+ css_file: String,
}
#[wasm_bindgen]
extern "C" {
@@ -39,6 +43,11 @@ impl Output {
self.code.clone()
}
+ #[wasm_bindgen(getter)]
+ pub fn css_file(&self) -> String {
+ self.css_file.clone()
+ }
+
#[wasm_bindgen(getter)]
pub fn map(&self) -> Option {
self.map.clone()
@@ -52,7 +61,11 @@ impl Output {
for style in self.styles.iter() {
match style {
ExtractStyleValue::Static(st) => {
- let (cls, _) = match style.extract() {
+ let (cls, _) = match style.extract(if !self.single_css {
+ Some(self.filename.as_str())
+ } else {
+ None
+ }) {
Some(StyleProperty::ClassName(cls)) => (cls, None),
Some(StyleProperty::Variable {
class_name,
@@ -68,12 +81,21 @@ impl Output {
st.value(),
st.selector(),
st.style_order(),
+ if !self.single_css {
+ Some(self.filename.as_str())
+ } else {
+ None
+ },
) {
collected = true;
}
}
ExtractStyleValue::Dynamic(dy) => {
- let (cls, variable) = match style.extract() {
+ let (cls, variable) = match style.extract(if !self.single_css {
+ Some(self.filename.as_str())
+ } else {
+ None
+ }) {
Some(StyleProperty::ClassName(cls)) => (cls, None),
Some(StyleProperty::Variable {
class_name,
@@ -89,6 +111,11 @@ impl Output {
&format!("var({})", variable.unwrap()),
dy.selector(),
dy.style_order(),
+ if !self.single_css {
+ Some(self.filename.as_str())
+ } else {
+ None
+ },
) {
collected = true;
}
@@ -96,7 +123,13 @@ impl Output {
ExtractStyleValue::Keyframes(keyframes) => {
if sheet.add_keyframes(
- &keyframes.extract().to_string(),
+ &keyframes
+ .extract(if !self.single_css {
+ Some(self.filename.as_str())
+ } else {
+ None
+ })
+ .to_string(),
keyframes
.keyframes
.iter()
@@ -115,6 +148,11 @@ impl Output {
)
})
.collect(),
+ if !self.single_css {
+ Some(self.filename.as_str())
+ } else {
+ None
+ },
) {
collected = true;
}
@@ -138,7 +176,11 @@ impl Output {
return None;
}
- Some(sheet.create_css())
+ Some(sheet.create_css(if !self.single_css {
+ Some(&self.filename)
+ } else {
+ None
+ }))
}
}
@@ -155,28 +197,42 @@ pub fn is_debug() -> bool {
#[wasm_bindgen(js_name = "importSheet")]
pub fn import_sheet(sheet_object: JsValue) -> Result<(), JsValue> {
*GLOBAL_STYLE_SHEET.lock().unwrap() = serde_wasm_bindgen::from_value(sheet_object)
- .map_err(|e| JsValue::from_str(e.to_string().as_str()))?;
+ .map_err(|e| JsValue::from_str(&e.to_string()))?;
Ok(())
}
#[wasm_bindgen(js_name = "exportSheet")]
pub fn export_sheet() -> Result {
serde_json::to_string(&*GLOBAL_STYLE_SHEET.lock().unwrap())
- .map_err(|e| JsValue::from_str(e.to_string().as_str()))
+ .map_err(|e| JsValue::from_str(&e.to_string()))
}
#[wasm_bindgen(js_name = "importClassMap")]
pub fn import_class_map(sheet_object: JsValue) -> Result<(), JsValue> {
set_class_map(
serde_wasm_bindgen::from_value(sheet_object)
- .map_err(|e| JsValue::from_str(e.to_string().as_str()))?,
+ .map_err(|e| JsValue::from_str(&e.to_string()))?,
);
Ok(())
}
#[wasm_bindgen(js_name = "exportClassMap")]
pub fn export_class_map() -> Result {
- serde_json::to_string(&get_class_map()).map_err(|e| JsValue::from_str(e.to_string().as_str()))
+ serde_json::to_string(&get_class_map()).map_err(|e| JsValue::from_str(&e.to_string()))
+}
+
+#[wasm_bindgen(js_name = "importFileMap")]
+pub fn import_file_map(sheet_object: JsValue) -> Result<(), JsValue> {
+ set_file_map(
+ serde_wasm_bindgen::from_value(sheet_object)
+ .map_err(|e| JsValue::from_str(&e.to_string()))?,
+ );
+ Ok(())
+}
+
+#[wasm_bindgen(js_name = "exportFileMap")]
+pub fn export_file_map() -> Result {
+ serde_json::to_string(&get_file_map()).map_err(|e| JsValue::from_str(&e.to_string()))
}
#[wasm_bindgen(js_name = "codeExtract")]
@@ -184,7 +240,8 @@ pub fn code_extract(
filename: &str,
code: &str,
package: &str,
- css_file: &str,
+ css_dir: String,
+ single_css: bool,
) -> Result