From e212e979fc8b54ca77d96008f64de6afb707e485 Mon Sep 17 00:00:00 2001 From: Kendell R <KTibow@users.noreply.github.com> Date: Thu, 12 Oct 2023 02:26:02 +0000 Subject: [PATCH 1/5] Switch to Lightning CSS --- build-scripts/bundle.cjs | 12 ++-- build-scripts/gulp/entry-html.js | 2 + build-scripts/lightningcss.cjs | 55 ++++++++++++++++ package.json | 1 + yarn.lock | 110 +++++++++++++++++++++++++++++++ 5 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 build-scripts/lightningcss.cjs diff --git a/build-scripts/bundle.cjs b/build-scripts/bundle.cjs index b359a0737487..4870d3f0a88e 100644 --- a/build-scripts/bundle.cjs +++ b/build-scripts/bundle.cjs @@ -1,6 +1,7 @@ const path = require("path"); const env = require("./env.cjs"); const paths = require("./paths.cjs"); +const lightningcss = require("./lightningcss.cjs"); // GitHub base URL to use for production source maps // Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version @@ -69,9 +70,6 @@ module.exports.htmlMinifierOptions = { decodeEntities: true, removeComments: true, removeRedundantAttributes: true, - minifyCSS: { - compatibility: "*,-properties.zeroUnits", - }, }; module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({ @@ -116,8 +114,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({ ignoreModuleNotFound: true, }, ], - // Minify template literals for production - isProdBuild && [ + [ "template-html-minifier", { modules: { @@ -129,7 +126,10 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({ "@polymer/polymer/lib/utils/html-tag": ["html"], }, strictCSS: true, - htmlMinifier: module.exports.htmlMinifierOptions, + htmlMinifier: { + ...module.exports.htmlMinifierOptions, + minifyCSS: lightningcss.getMinifyCSS({ latestBuild, isProdBuild }), + }, failOnError: true, // we can turn this off in case of false positives }, ], diff --git a/build-scripts/gulp/entry-html.js b/build-scripts/gulp/entry-html.js index dd6285c3103a..a7d5dda9f9e7 100644 --- a/build-scripts/gulp/entry-html.js +++ b/build-scripts/gulp/entry-html.js @@ -8,6 +8,7 @@ import path from "path"; import { htmlMinifierOptions, terserOptions } from "../bundle.cjs"; import env from "../env.cjs"; import paths from "../paths.cjs"; +import { getMinifyCSS } from "../lightningcss.cjs"; const renderTemplate = (templateFile, data = {}) => { const compiled = template( @@ -35,6 +36,7 @@ const minifyHtml = (content, ext) => { return minify(begTag + content + endTag, { ...htmlMinifierOptions, conservativeCollapse: false, + minifyCSS: getMinifyCSS({ latestBuild: false, isProdBuild: true }), // Transpile and minify minifyJS: terserOptions({ latestBuild: false, // Shared scripts should be ES5 isTestBuild: true, // Don't need source maps diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs new file mode 100644 index 000000000000..b820d1ff0637 --- /dev/null +++ b/build-scripts/lightningcss.cjs @@ -0,0 +1,55 @@ +const CleanCSS = require("clean-css"); +const browserslist = require("browserslist"); +const lightningcss = require("lightningcss"); + +const cleanCSS = new CleanCSS({ compatibility: "*,-properties.zeroUnits" }); +const decoder = new TextDecoder(); +function wrapCSS(text, type) { + if (type === "inline") return `#a{${text}}`; + if (type === "media") return `@media ${text}{#a{top:0}}`; + return text; +} +function unwrapCSS(text, type) { + if (type === "inline") return text.match(/^#a\{([\s\S]*)\}$/)[1]; + if (type === "media") return text.match(/^@media ?([\s\S]*?) ?{[\s\S]*}$/)[1]; + return text; +} + +module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { + const cssTargets = lightningcss.browserslistToTargets( + browserslist( + browserslist.loadConfig({ + path: ".", + env: latestBuild ? "modern" : "legacy", + }), + { throwOnMissing: true, mobileToDesktop: true } + ) + ); + return (text, type) => { + if (!text) return text; + const input = wrapCSS(text, type); + const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input); + if (errors.length > 0) { + console.error("[CCSS] Errors while transforming CSS:", ...errors); + } + if (w1.length > 0) { + console.warn("[CCSS] Warnings while transforming CSS:", ...w1); + } + if (text.includes("babel-plugin-template-html-minifier")) { + const output = unwrapCSS(ccss, type); + return output; + } + const { code, warnings: w2 } = lightningcss.transform({ + filename: "style.css", + code: Buffer.from(input), + minify: isProdBuild, + targets: cssTargets, + }); + if (w2.length > 0) { + console.warn("[LCSS] Warnings while transforming CSS:", ...w2); + } + const lcss = decoder.decode(code); + const output = unwrapCSS(lcss, type); + return output; + }; +}; diff --git a/package.json b/package.json index 5434f52d3a75..e1b863e8ed31 100644 --- a/package.json +++ b/package.json @@ -220,6 +220,7 @@ "husky": "8.0.3", "instant-mocha": "1.5.2", "jszip": "3.10.1", + "lightningcss": "1.22.0", "lint-staged": "14.0.1", "lit-analyzer": "2.0.0-pre.3", "lodash.template": "4.5.0", diff --git a/yarn.lock b/yarn.lock index 3a4c90ab742b..6e18fd574373 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7506,6 +7506,15 @@ __metadata: languageName: node linkType: hard +"detect-libc@npm:^1.0.3": + version: 1.0.3 + resolution: "detect-libc@npm:1.0.3" + bin: + detect-libc: ./bin/detect-libc.js + checksum: daaaed925ffa7889bd91d56e9624e6c8033911bb60f3a50a74a87500680652969dbaab9526d1e200a4c94acf80fc862a22131841145a0a8482d60a99c24f4a3e + languageName: node + linkType: hard + "detect-node@npm:^2.0.4": version: 2.1.0 resolution: "detect-node@npm:2.1.0" @@ -9788,6 +9797,7 @@ __metadata: jszip: 3.10.1 leaflet: 1.9.4 leaflet-draw: 1.0.4 + lightningcss: 1.22.0 lint-staged: 14.0.1 lit: 2.8.0 lit-analyzer: 2.0.0-pre.3 @@ -11371,6 +11381,106 @@ __metadata: languageName: node linkType: hard +"lightningcss-darwin-arm64@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-darwin-arm64@npm:1.22.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-x64@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-darwin-x64@npm:1.22.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-freebsd-x64@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-freebsd-x64@npm:1.22.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-linux-arm-gnueabihf@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.22.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"lightningcss-linux-arm64-gnu@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-linux-arm64-gnu@npm:1.22.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-arm64-musl@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-linux-arm64-musl@npm:1.22.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-linux-x64-gnu@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-linux-x64-gnu@npm:1.22.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-x64-musl@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-linux-x64-musl@npm:1.22.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss-win32-x64-msvc@npm:1.22.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"lightningcss@npm:1.22.0": + version: 1.22.0 + resolution: "lightningcss@npm:1.22.0" + dependencies: + detect-libc: ^1.0.3 + lightningcss-darwin-arm64: 1.22.0 + lightningcss-darwin-x64: 1.22.0 + lightningcss-freebsd-x64: 1.22.0 + lightningcss-linux-arm-gnueabihf: 1.22.0 + lightningcss-linux-arm64-gnu: 1.22.0 + lightningcss-linux-arm64-musl: 1.22.0 + lightningcss-linux-x64-gnu: 1.22.0 + lightningcss-linux-x64-musl: 1.22.0 + lightningcss-win32-x64-msvc: 1.22.0 + dependenciesMeta: + lightningcss-darwin-arm64: + optional: true + lightningcss-darwin-x64: + optional: true + lightningcss-freebsd-x64: + optional: true + lightningcss-linux-arm-gnueabihf: + optional: true + lightningcss-linux-arm64-gnu: + optional: true + lightningcss-linux-arm64-musl: + optional: true + lightningcss-linux-x64-gnu: + optional: true + lightningcss-linux-x64-musl: + optional: true + lightningcss-win32-x64-msvc: + optional: true + checksum: 6b9a04846243a2161ac12ee098f9c2143a1a06fb683228ef0433473257751a709b0bafa195efa8d3d8f1556ca60c54f5434caeb172874a8daced552dedcbed93 + languageName: node + linkType: hard + "lilconfig@npm:2.1.0": version: 2.1.0 resolution: "lilconfig@npm:2.1.0" From d8180851b50c21fb8112fd9755d3d4c3cf771c1d Mon Sep 17 00:00:00 2001 From: Kendell R <KTibow@users.noreply.github.com> Date: Thu, 12 Oct 2023 02:35:56 +0000 Subject: [PATCH 2/5] Some "fixes" --- build-scripts/lightningcss.cjs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs index b820d1ff0637..109542091a53 100644 --- a/build-scripts/lightningcss.cjs +++ b/build-scripts/lightningcss.cjs @@ -28,16 +28,20 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { return (text, type) => { if (!text) return text; const input = wrapCSS(text, type); - const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input); - if (errors.length > 0) { - console.error("[CCSS] Errors while transforming CSS:", ...errors); - } - if (w1.length > 0) { - console.warn("[CCSS] Warnings while transforming CSS:", ...w1); - } if (text.includes("babel-plugin-template-html-minifier")) { - const output = unwrapCSS(ccss, type); - return output; + const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input); + if (errors.length > 0) { + console.error("[CCSS] Errors while transforming CSS:", ...errors); + } + if (w1.length > 0) { + console.warn("[CCSS] Warnings while transforming CSS:", ...w1); + } + try { + return unwrapCSS(ccss, type); + } catch (e) { + console.error("[CCSS] Invalid output", { text, type, output: ccss }); + return text; + } } const { code, warnings: w2 } = lightningcss.transform({ filename: "style.css", @@ -49,7 +53,11 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { console.warn("[LCSS] Warnings while transforming CSS:", ...w2); } const lcss = decoder.decode(code); - const output = unwrapCSS(lcss, type); - return output; + try { + return unwrapCSS(lcss, type); + } catch (e) { + console.error("[LCSS] Invalid output", { text, type, output: lcss }); + return text; + } }; }; From 6a37e2257cbabb4055aa41dd45364ed5af6db8ac Mon Sep 17 00:00:00 2001 From: Kendell R <KTibow@users.noreply.github.com> Date: Thu, 12 Oct 2023 02:54:28 +0000 Subject: [PATCH 3/5] Fix test builds --- build-scripts/lightningcss.cjs | 50 ++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs index 109542091a53..8a82b55900be 100644 --- a/build-scripts/lightningcss.cjs +++ b/build-scripts/lightningcss.cjs @@ -10,8 +10,9 @@ function wrapCSS(text, type) { return text; } function unwrapCSS(text, type) { - if (type === "inline") return text.match(/^#a\{([\s\S]*)\}$/)[1]; - if (type === "media") return text.match(/^@media ?([\s\S]*?) ?{[\s\S]*}$/)[1]; + if (type === "inline") return text.match(/^#a ?\{([\s\S]*)\}$/m)[1]; + if (type === "media") + return text.match(/^@media ?([\s\S]*?) ?{[\s\S]*}$/m)[1]; return text; } @@ -28,36 +29,39 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { return (text, type) => { if (!text) return text; const input = wrapCSS(text, type); - if (text.includes("babel-plugin-template-html-minifier")) { - const { styles: ccss, errors, warnings: w1 } = cleanCSS.minify(input); + if (!text.includes("babel-plugin-template-html-minifier")) { + const { code, warnings: w1 } = lightningcss.transform({ + filename: "style.css", + code: Buffer.from(input), + minify: isProdBuild, + targets: cssTargets, + }); + if (w1.length > 0) { + console.warn("[LCSS] Warnings while transforming CSS:", ...w1); + } + const lcss = decoder.decode(code); + try { + return unwrapCSS(lcss, type); + } catch (e) { + console.error("[LCSS] Invalid output", { text, type, output: lcss, e }); + return text; + } + } + if (isProdBuild) { + const { styles: ccss, errors, warnings: w2 } = cleanCSS.minify(input); if (errors.length > 0) { console.error("[CCSS] Errors while transforming CSS:", ...errors); } - if (w1.length > 0) { - console.warn("[CCSS] Warnings while transforming CSS:", ...w1); + if (w2.length > 0) { + console.warn("[CCSS] Warnings while transforming CSS:", ...w2); } try { return unwrapCSS(ccss, type); } catch (e) { - console.error("[CCSS] Invalid output", { text, type, output: ccss }); + console.error("[CCSS] Invalid output", { text, type, output: ccss, e }); return text; } } - const { code, warnings: w2 } = lightningcss.transform({ - filename: "style.css", - code: Buffer.from(input), - minify: isProdBuild, - targets: cssTargets, - }); - if (w2.length > 0) { - console.warn("[LCSS] Warnings while transforming CSS:", ...w2); - } - const lcss = decoder.decode(code); - try { - return unwrapCSS(lcss, type); - } catch (e) { - console.error("[LCSS] Invalid output", { text, type, output: lcss }); - return text; - } + return text; }; }; From be58762349e922dcfe56d9b41c62374f290c7d57 Mon Sep 17 00:00:00 2001 From: Kendell R <KTibow@users.noreply.github.com> Date: Fri, 13 Oct 2023 00:27:58 +0000 Subject: [PATCH 4/5] Reduce output size, make code more clear --- build-scripts/lightningcss.cjs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs index 8a82b55900be..90f3a3011bee 100644 --- a/build-scripts/lightningcss.cjs +++ b/build-scripts/lightningcss.cjs @@ -1,6 +1,6 @@ const CleanCSS = require("clean-css"); const browserslist = require("browserslist"); -const lightningcss = require("lightningcss"); +const { transform, browserslistToTargets, Features } = require("lightningcss"); const cleanCSS = new CleanCSS({ compatibility: "*,-properties.zeroUnits" }); const decoder = new TextDecoder(); @@ -17,7 +17,7 @@ function unwrapCSS(text, type) { } module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { - const cssTargets = lightningcss.browserslistToTargets( + const cssTargets = browserslistToTargets( browserslist( browserslist.loadConfig({ path: ".", @@ -30,14 +30,18 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { if (!text) return text; const input = wrapCSS(text, type); if (!text.includes("babel-plugin-template-html-minifier")) { - const { code, warnings: w1 } = lightningcss.transform({ + const { code, warnings: ws } = transform({ filename: "style.css", code: Buffer.from(input), minify: isProdBuild, targets: cssTargets, + exclude: Features.DirSelector, }); - if (w1.length > 0) { - console.warn("[LCSS] Warnings while transforming CSS:", ...w1); + const warnings = ws.filter( + (w) => w.message !== "Unknown at rule: @apply" + ); + if (warnings.length > 0) { + console.warn("[LCSS] Warnings while transforming CSS:", ...warnings); } const lcss = decoder.decode(code); try { @@ -48,12 +52,12 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { } } if (isProdBuild) { - const { styles: ccss, errors, warnings: w2 } = cleanCSS.minify(input); + const { styles: ccss, errors, warnings } = cleanCSS.minify(input); if (errors.length > 0) { console.error("[CCSS] Errors while transforming CSS:", ...errors); } - if (w2.length > 0) { - console.warn("[CCSS] Warnings while transforming CSS:", ...w2); + if (warnings.length > 0) { + console.warn("[CCSS] Warnings while transforming CSS:", ...warnings); } try { return unwrapCSS(ccss, type); From 18ef4109607fe45c4dfce8a725669a3100ad78e0 Mon Sep 17 00:00:00 2001 From: Kendell R <KTibow@users.noreply.github.com> Date: Fri, 13 Oct 2023 01:08:38 +0000 Subject: [PATCH 5/5] Don't mess up @apply --- build-scripts/lightningcss.cjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build-scripts/lightningcss.cjs b/build-scripts/lightningcss.cjs index 90f3a3011bee..a90828334713 100644 --- a/build-scripts/lightningcss.cjs +++ b/build-scripts/lightningcss.cjs @@ -29,7 +29,10 @@ module.exports.getMinifyCSS = ({ latestBuild, isProdBuild }) => { return (text, type) => { if (!text) return text; const input = wrapCSS(text, type); - if (!text.includes("babel-plugin-template-html-minifier")) { + if ( + !text.includes("babel-plugin-template-html-minifier") && + !text.includes("@apply") + ) { const { code, warnings: ws } = transform({ filename: "style.css", code: Buffer.from(input),