From 4b1f529589ce2198f45a78eee6648fd4ced315e7 Mon Sep 17 00:00:00 2001 From: Sped0n Date: Wed, 12 Nov 2025 16:56:30 +0800 Subject: [PATCH] refactor: migrate to vite for critical scss bundling, remove dart sass dependency Signed-off-by: Sped0n --- .gitignore | 5 +- .prettierignore | 8 +- assets/bundled/critical.css | 263 ++++++++++++++++++++++++++++++++ assets/scss/_core/_font.scss | 7 +- assets/ts/critical.ts | 2 + docs.md | 16 +- eslint.config.mjs | 8 +- layouts/partials/head/link.html | 4 +- vite.config.ts | 26 +++- 9 files changed, 309 insertions(+), 30 deletions(-) create mode 100644 assets/bundled/critical.css create mode 100644 assets/ts/critical.ts diff --git a/.gitignore b/.gitignore index 87d4b53..9b74d88 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Hugo default output directory public/ -/exampleSite/resources/ +exampleSite/resources/ node_modules/ build/ @@ -25,3 +25,6 @@ jsconfig.json # css map *.css.map + +# dummmy file +assets/bundled/critical.js diff --git a/.prettierignore b/.prettierignore index 0ba978c..aaa821f 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,7 @@ -node_modules -static -exmapleSite +node_modules/ +static/ +exmapleSite/ single.json pnpm-lock.yaml +assets/bundled/ +assets/bundled/ diff --git a/assets/bundled/critical.css b/assets/bundled/critical.css new file mode 100644 index 0000000..c5b6b99 --- /dev/null +++ b/assets/bundled/critical.css @@ -0,0 +1,263 @@ +/*** + The new CSS reset - version 1.11.1 (last updated 24.10.2023) + GitHub page: https://github.com/elad2412/the-new-css-reset +***/ +/* + Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property + - The "symbol *" part is to solve Firefox SVG sprite bug + - The "html" element is excluded, otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36) + */ +*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; +} + +/* Preferred box-sizing value */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Fix mobile Safari increase font-size on landscape mode */ +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + +/* Reapply the pointer cursor for anchor tags */ +a, +button { + cursor: revert; +} + +/* Remove list styles (bullets/numbers) */ +ol, +ul, +menu, +summary { + list-style: none; +} + +/* For images to not be able to exceed their container */ +img { + max-inline-size: 100%; + max-block-size: 100%; +} + +/* removes spacing between cells in tables */ +table { + border-collapse: collapse; +} + +/* Safari - solving issue when using user-select:none on the text input doesn't working */ +input, +textarea { + -webkit-user-select: auto; +} + +/* revert the 'white-space' property for textarea elements on Safari */ +textarea { + white-space: revert; +} + +/* minimum style to allow to style meter element */ +meter { + -webkit-appearance: revert; + appearance: revert; +} + +/* preformatted text - use only for this feature */ +:where(pre) { + all: revert; + box-sizing: border-box; +} + +/* reset default text opacity of input placeholder */ +::placeholder { + color: unset; +} + +/* fix the feature of 'hidden' attribute. + display:revert; revert to element instead of attribute */ +:where([hidden]) { + display: none; +} + +/* revert for bug in Chromium browsers + - fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/ +:where([contenteditable]:not([contenteditable=false])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; +} + +/* apply back the draggable feature - exist only in Chromium and Safari */ +:where([draggable=true]) { + -webkit-user-drag: element; +} + +/* Revert Modal native behavior */ +:where(dialog:modal) { + all: revert; + box-sizing: border-box; +} + +@font-face { + font-family: "Geist"; + src: url('{{- "lib/fonts/GeistVF.woff2" | absURL -}}') format("woff2 supports variations"), url('{{- "lib/fonts/GeistVF.woff2" | absURL -}}') format("woff2-variations"); + font-weight: 400; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "FW"; + src: url('{{- "lib/fonts/fw.woff2" | absURL -}}') format("woff2"); + font-weight: 400; + font-style: normal; + font-display: swap; +} +body { + line-height: 1.2; + font-size: 16px; + font-family: "Geist", sans-serif; +} +body button { + font-family: "FW", sans-serif; +} +@media (min-width: 768px) { + body { + font-size: 18px; + } +} +@media (min-width: 1024px) { + body { + font-size: 19px; + } +} + +:root { + --window-height: 100vh; + --nav-height: 2rem; + --space-standard: 0.625rem; + --z-curtain: 200; + --z-nav-gallery: 500; + --z-cursor: 600; + --z-nav: 800; +} + +* { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + user-select: none; + background: white; +} + +html, +body { + overscroll-behavior-y: none; +} + +a, +button { + cursor: pointer; +} + +nav { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + height: var(--nav-height); + padding: 0 var(--space-standard); + position: fixed; + bottom: 0; + background: white; + z-index: var(--z-nav); + pointer-events: all; +} + +.num { + width: 0.625em; + display: inline-block; + text-align: center; +} + +.current { + font-style: italic; + text-decoration: underline; +} + +@media (max-width: 767px), (hover: none) { + nav { + top: 0; + } + .index, + .threshold { + display: none; + } +} +article { + padding: var(--space-standard); + max-width: 25em; +} +article p { + margin-bottom: 1em; +} +article u { + text-decoration: underline; +} +article > h1 { + font-size: 1.6em; +} +article > h2 { + font-size: 1.5em; +} +article > h3 { + font-size: 1.375em; +} +article > h4 { + font-size: 1.25em; +} +article > h5 { + font-size: 1.125em; +} +article h1, +article h2, +article h3, +article h4, +article h5, +article h6 { + font-weight: bold; + margin: 1.2rem 0; +} + +@media (max-width: 767px), (hover: none) { + article { + margin-top: var(--nav-height); + } +} +@media (max-width: 767px), (hover: none) { + .container { + position: fixed; + top: 0; + z-index: 0; + width: 100vw; + height: var(--window-height); + overflow-y: scroll; + overflow-x: hidden; + background: white; + overscroll-behavior: none; + -webkit-overflow-scrolling: none; + } + .disableScroll { + pointer-events: none; + } +} \ No newline at end of file diff --git a/assets/scss/_core/_font.scss b/assets/scss/_core/_font.scss index 9b41a0a..75d8cb9 100644 --- a/assets/scss/_core/_font.scss +++ b/assets/scss/_core/_font.scss @@ -1,9 +1,10 @@ @font-face { font-family: 'Geist'; src: - url('{{- "lib/fonts/GeistVF.woff2" | absURL -}}') + url(/* @vite-ignore */'{{- "lib/fonts/GeistVF.woff2" | absURL -}}') format('woff2 supports variations'), - url('{{- "lib/fonts/GeistVF.woff2" | absURL -}}') format('woff2-variations'); + url(/* @vite-ignore */'{{- "lib/fonts/GeistVF.woff2" | absURL -}}') + format('woff2-variations'); font-weight: 400; font-style: normal; font-display: swap; @@ -11,7 +12,7 @@ @font-face { font-family: 'FW'; - src: url('{{- "lib/fonts/fw.woff2" | absURL -}}') format('woff2'); + src: url(/* @vite-ignore */'{{- "lib/fonts/fw.woff2" | absURL -}}') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; diff --git a/assets/ts/critical.ts b/assets/ts/critical.ts new file mode 100644 index 0000000..4af7012 --- /dev/null +++ b/assets/ts/critical.ts @@ -0,0 +1,2 @@ +// this is a dummy file to trick vite to generate a critical.css file +import '../scss/critical.scss' diff --git a/docs.md b/docs.md index fd7c3fa..493a1d3 100644 --- a/docs.md +++ b/docs.md @@ -33,19 +33,6 @@ _[Contents](#contents)_ hugo v0.152.2+extended+withdeploy darwin/arm64 BuildDate=unknown VendorInfo=nixpkgs ``` -- [Dart Sass](https://gohugo.io/functions/css/sass/#dart-sass) (or install it with `npm install -g sass-embedded`) - - ```bash - ❯ sass --embedded --version - { - "protocolVersion": "2.4.0", - "compilerVersion": "1.70.0", - "implementationVersion": "1.70.0", - "implementationName": "dart-sass", - "id": 0 - } - ``` - - [pnpm](https://pnpm.io/installation) and [Node.js](https://nodejs.org/en/download), please note that these two are only needed for customizations or development. ```bash @@ -273,8 +260,7 @@ https://gohugo.io/templates/sitemap-template/#configuration _[Contents](#contents)_ -- Ensure `sass --embedded --version` return a valid result. -- Run `hugo` command. +Bridget will work as a normal Hugo theme (if you don't have needs to customize), https://gohugo.io/getting-started/usage/ is a great start. For further reading, you can refer to the `scripts` field of `package.json`. diff --git a/eslint.config.mjs b/eslint.config.mjs index 87ca595..62657f2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -12,7 +12,13 @@ export default defineConfig([ tseslint.configs.recommended, importPlugin.flatConfigs.recommended, solid, - globalIgnores(['**/node_modules', '**/static', '**/exampleSite', '*.mjs']), + globalIgnores([ + 'node_modules/', + 'static/', + 'exampleSite/', + '*.mjs', + 'assets/bundled/' + ]), { ...love, ...prettier, diff --git a/layouts/partials/head/link.html b/layouts/partials/head/link.html index c8c827a..f4c4d6a 100644 --- a/layouts/partials/head/link.html +++ b/layouts/partials/head/link.html @@ -2,8 +2,8 @@ {{- $fingerprint := .Scratch.Get "fingerprint" | default "" -}} {{- /* critical style */ -}} -{{- $style := dict "Source" "scss/critical.scss" "Fingerprint" $fingerprint -}} -{{- $options := dict "enableSourceMap" true "includePaths" (slice "node_modules") "transpiler" "dartsass" -}} +{{- $style := dict "Source" "bundled/critical.css" "Fingerprint" $fingerprint -}} +{{- $options := dict "enableSourceMap" false -}} {{- $style = dict "Context" . "ToCSS" $options "Inline" true "Template" true | merge $style -}} {{- partial "plugin/style.html" $style -}} diff --git a/vite.config.ts b/vite.config.ts index 2750dd8..a5f991f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,21 +4,37 @@ import solidPlugin from 'vite-plugin-solid' export default defineConfig({ plugins: [solidPlugin()], build: { - outDir: './static/bundled', + outDir: './', watch: process.env.DISABLE_WATCH ? null : { include: 'assets/**' }, rollupOptions: { - input: './assets/ts/main.tsx', + input: { + main: './assets/ts/main.tsx', + critical: './assets/ts/critical.ts' + }, output: { format: 'es', - entryFileNames: 'js/[name].js', - chunkFileNames: 'js/[hash:6].js', - assetFileNames: '[ext]/[name].[ext]', + entryFileNames: (chunkInfo) => + chunkInfo.name === 'critical' + ? 'assets/bundled/[name].js' + : 'static/bundled/js/[name].js', + chunkFileNames: 'static/bundled/js/[hash:6].js', + assetFileNames: (assetInfo) => + assetInfo.names[0]?.startsWith('critical') + ? 'assets/bundled/[name].[ext]' + : 'static/bundled/[ext]/[name].[ext]', compact: true } } + }, + css: { + preprocessorOptions: { + scss: { + loadPaths: ['./assets/scss'] + } + } } })