From 7912442b7653519bf3c699fcd9612c003f3100b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Mierzwa?= Date: Thu, 5 Aug 2021 18:48:32 +0100 Subject: [PATCH] feat(ui): reduce css bundle size --- .gitignore | 1 + CHANGELOG.md | 5 +++ ui/.depcheckrc.yaml | 1 + ui/Makefile | 11 ++++++- ui/package-lock.json | 31 +++++++++++++++++++ ui/package.json | 2 ++ ui/purgecss.config.js | 11 +++++++ ui/src/Components/InhibitedByModal/index.tsx | 2 +- .../Labels/FilteringCounterBadge/index.tsx | 6 ++-- .../ManagedSilence/SilenceComment.tsx | 2 +- ui/src/Components/Modal/index.test.tsx | 2 +- ui/src/Components/Modal/index.tsx | 8 ++--- .../Components/NavBar/FilterInput/History.tsx | 12 +++---- ui/src/Components/OverviewModal/index.tsx | 2 +- 14 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 ui/purgecss.config.js diff --git a/.gitignore b/.gitignore index d1f994c78..92cc69e1c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /karma /karma-* /ui/build +/ui/build.pre /ui/coverage /ui/node_modules /ui/.eslintcache diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d16140d0..5982ba543 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ - Alert history queries didn't include grid labels as those got removed from alert groups in #3222, this is now fixed. +### Changed + +- Reduced CSS bundle size by removing unused CSS rules with + [PurgeCSS](https://purgecss.com/). + ## v0.89 ### Fixed diff --git a/ui/.depcheckrc.yaml b/ui/.depcheckrc.yaml index b813298e7..9cc5f80a9 100644 --- a/ui/.depcheckrc.yaml +++ b/ui/.depcheckrc.yaml @@ -14,3 +14,4 @@ ignores: - "@types/node" - "@percy/storybook" - "@storybook/preset-create-react-app" + - "purgecss" diff --git a/ui/Makefile b/ui/Makefile index bd2cf7b5a..6631b7470 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -22,7 +22,7 @@ npm-fetch: $(NODE_INSTALL) $(NODE_PATH)/%: $(NODE_INSTALL) @if [ ! -x $@ ]; then echo "missing script: $@" ; exit 1; fi -build/index.html: $(NODE_INSTALL) $(NODE_PATH)/react-scripts $(call rwildcard, public src, *) +build/index.html: $(NODE_INSTALL) $(NODE_PATH)/react-scripts $(call rwildcard, public src, *) purgecss.config.js @rm -fr node_modules/.cache/eslint-loader npm run build @@ -55,6 +55,15 @@ format: $(NODE_PATH)/prettier build/stats.json: build npx source-map-explorer build/static/*/*.{js,css} --json > build/stats.json +.PHONY: backup-css +backup-css: + mkdir -p build.pre/static + cp -R build/static/css build.pre/static/css + +build.pre/css.diff: build purgecss.config.js + npx prettier -w build.pre/static/css/*.css build/static/css/*.css + diff -uN build.pre/static/css build/static/css > build.pre/css.diff || echo + .PHONY: npm-upgrade npm-upgrade: rm -fr node_modules package-lock.json diff --git a/ui/package-lock.json b/ui/package-lock.json index 35b9686fc..8165ee4eb 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -19988,6 +19988,37 @@ } } }, + "purgecss": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.0.3.tgz", + "integrity": "sha512-PYOIn5ibRIP34PBU9zohUcCI09c7drPJJtTDAc0Q6QlRz2/CHQ8ywGLdE7ZhxU2VTqB7p5wkvj5Qcm05Rz3Jmw==", + "dev": true, + "requires": { + "commander": "^6.0.0", + "glob": "^7.0.0", + "postcss": "^8.2.1", + "postcss-selector-parser": "^6.0.2" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "postcss": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz", + "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" + } + } + } + }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", diff --git a/ui/package.json b/ui/package.json index 10d0c8b6d..0e48af5f3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -87,6 +87,7 @@ "jest-canvas-mock": "2.3.1", "jest-date-mock": "1.0.8", "prettier": "2.3.2", + "purgecss": "4.0.3", "react-scripts": "4.0.3", "sass": "1.37.5", "typescript": "4.3.5" @@ -94,6 +95,7 @@ "scripts": { "start": "REACT_APP_BACKEND_URI=http://localhost:8080 react-scripts start", "build": "react-scripts build", + "postbuild": "make backup-css && purgecss -c purgecss.config.js", "test": "react-scripts test", "storybook": "start-storybook", "snapshot": "build-storybook --quiet -s public && percy-storybook --widths=700,1280 --minimum_height=200", diff --git a/ui/purgecss.config.js b/ui/purgecss.config.js new file mode 100644 index 000000000..5d2e5758d --- /dev/null +++ b/ui/purgecss.config.js @@ -0,0 +1,11 @@ +module.exports = { + content: ["build/index.html", "build/static/js/*.js", "src/**/*.{ts,tsx}"], + css: ["build/static/css/*.css"], + output: "build/static/css", + variables: true, + fontFace: false, + keyframes: false, + safelist: { + greedy: [/^components-/, /^firing-[0-9]$/, /^alert-history-loading-/], + }, +}; diff --git a/ui/src/Components/InhibitedByModal/index.tsx b/ui/src/Components/InhibitedByModal/index.tsx index 009ba5a9d..9fdec8125 100644 --- a/ui/src/Components/InhibitedByModal/index.tsx +++ b/ui/src/Components/InhibitedByModal/index.tsx @@ -33,7 +33,7 @@ const InhibitedByModal: FC<{ - + diff --git a/ui/src/Components/Labels/FilteringCounterBadge/index.tsx b/ui/src/Components/Labels/FilteringCounterBadge/index.tsx index 7b281f574..391cfcfd1 100644 --- a/ui/src/Components/Labels/FilteringCounterBadge/index.tsx +++ b/ui/src/Components/Labels/FilteringCounterBadge/index.tsx @@ -20,7 +20,7 @@ const FilteringCounterBadge: FC<{ counter: number; themed: boolean; alwaysVisible?: boolean; - defaultColor?: "light" | "primary"; + defaultColor?: "bg-light" | "bg-primary"; isAppend?: boolean; }> = ({ alertStore, @@ -29,7 +29,7 @@ const FilteringCounterBadge: FC<{ counter, themed, alwaysVisible = false, - defaultColor = "light", + defaultColor = "bg-light", isAppend = true, }) => { const { ref, props } = useFlashTransition(counter); @@ -72,7 +72,7 @@ const FilteringCounterBadge: FC<{ themed ? cs.className : [ - `bg-${defaultColor}`, + `${defaultColor}`, "rounded-pill components-label-with-hover", ...cs.baseClassNames, ].join(" ") diff --git a/ui/src/Components/ManagedSilence/SilenceComment.tsx b/ui/src/Components/ManagedSilence/SilenceComment.tsx index 02f73737f..fc30486bb 100644 --- a/ui/src/Components/ManagedSilence/SilenceComment.tsx +++ b/ui/src/Components/ManagedSilence/SilenceComment.tsx @@ -80,7 +80,7 @@ const SilenceComment: FC<{ counter={alertCount} themed={false} alwaysVisible={alertCountAlwaysVisible} - defaultColor="primary" + defaultColor="bg-primary" isAppend={false} /> diff --git a/ui/src/Components/Modal/index.test.tsx b/ui/src/Components/Modal/index.test.tsx index e6e323a3e..316229965 100644 --- a/ui/src/Components/Modal/index.test.tsx +++ b/ui/src/Components/Modal/index.test.tsx @@ -34,7 +34,7 @@ describe("", () => { }) ); const tree = mount( - + ); tree.setProps({ isUpper: false }); tree.setProps({ isUpper: true }); diff --git a/ui/src/Components/Modal/index.tsx b/ui/src/Components/Modal/index.tsx index 07e0f45f4..1250c9267 100644 --- a/ui/src/Components/Modal/index.tsx +++ b/ui/src/Components/Modal/index.tsx @@ -10,7 +10,7 @@ import { useHotkeys } from "react-hotkeys-hook"; import { ThemeContext } from "Components/Theme"; const ModalInner: FC<{ - size: "lg" | "xl"; + size: "modal-lg" | "modal-xl"; isUpper: boolean; toggleOpen: () => void; }> = ({ size, isUpper, toggleOpen, children }) => { @@ -36,7 +36,7 @@ const ModalInner: FC<{
void; onExited?: () => void; }> = ({ - size = "lg", + size = "modal-lg", isOpen, isUpper = false, toggleOpen, diff --git a/ui/src/Components/NavBar/FilterInput/History.tsx b/ui/src/Components/NavBar/FilterInput/History.tsx index 018284512..843b35b23 100644 --- a/ui/src/Components/NavBar/FilterInput/History.tsx +++ b/ui/src/Components/NavBar/FilterInput/History.tsx @@ -50,14 +50,14 @@ function ReduceFilter(filter: FilterT): ReduceFilterT { } const ActionButton: FC<{ - color: string; + colorClass: string; icon: IconDefinition; title: ReactNode; action: () => void; afterClick: () => void; -}> = ({ color, icon, title, action, afterClick }) => ( +}> = ({ colorClass, icon, title, action, afterClick }) => (