From c4a99dd39d666b04edae8fa7d42f9cb7a3a446ac Mon Sep 17 00:00:00 2001 From: Yevhen Uzhva Date: Tue, 8 Jul 2025 22:45:23 +0300 Subject: [PATCH 1/2] feat: html preload css webpack plugin, solves CSS blinking during SSR --- .../html-preload-css-webpack-plugin.mts | 55 +++++++++++++++++++ .../src/webpack-config/plugins/index.mts | 1 + .../src/webpack-config/webapp.ssr.config.mts | 2 + 3 files changed, 58 insertions(+) create mode 100644 packages/bundler-webpack/src/webpack-config/plugins/html-preload-css-webpack-plugin.mts create mode 100644 packages/bundler-webpack/src/webpack-config/plugins/index.mts diff --git a/packages/bundler-webpack/src/webpack-config/plugins/html-preload-css-webpack-plugin.mts b/packages/bundler-webpack/src/webpack-config/plugins/html-preload-css-webpack-plugin.mts new file mode 100644 index 0000000..cc58f09 --- /dev/null +++ b/packages/bundler-webpack/src/webpack-config/plugins/html-preload-css-webpack-plugin.mts @@ -0,0 +1,55 @@ +import type { HtmlTagObject } from 'html-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import type { Compilation, Compiler } from 'webpack'; + +/** + * HtmlPreloadCssWebpackPlugin + * Removes blinking CSS during SSR (Server-Side Rendering) by preloading CSS files. + * + * This plugin modifies the HTML output to add preload tags for CSS files. + * It hooks into the HtmlWebpackPlugin to alter the asset tag groups. + * + * The tag format will be: + * + * + * Added before: + * + */ +class HtmlPreloadCssWebpackPlugin { + apply(compiler: Compiler) { + compiler.hooks.compilation.tap( + 'HtmlPreloadCssWebpackPlugin', + (compilation: Compilation) => { + HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync( + 'HtmlPreloadCssWebpackPlugin', + (data, cb) => { + const newHeadTags: HtmlTagObject[] = []; + + data.headTags.forEach((tag) => { + if ( + tag.tagName === 'link' && + tag.attributes?.rel === 'stylesheet' + ) { + newHeadTags.push({ + ...tag, + attributes: { + ...tag.attributes, + rel: 'preload', + as: 'style', + }, + }); + } + + newHeadTags.push(tag); + }); + + data.headTags = newHeadTags; + cb(null, data); + }, + ); + }, + ); + } +} + +export { HtmlPreloadCssWebpackPlugin }; diff --git a/packages/bundler-webpack/src/webpack-config/plugins/index.mts b/packages/bundler-webpack/src/webpack-config/plugins/index.mts new file mode 100644 index 0000000..e217889 --- /dev/null +++ b/packages/bundler-webpack/src/webpack-config/plugins/index.mts @@ -0,0 +1 @@ +export { HtmlPreloadCssWebpackPlugin } from './html-preload-css-webpack-plugin.mjs'; diff --git a/packages/bundler-webpack/src/webpack-config/webapp.ssr.config.mts b/packages/bundler-webpack/src/webpack-config/webapp.ssr.config.mts index fc406a4..b71e02d 100644 --- a/packages/bundler-webpack/src/webpack-config/webapp.ssr.config.mts +++ b/packages/bundler-webpack/src/webpack-config/webapp.ssr.config.mts @@ -6,6 +6,7 @@ import path from 'path'; import { devWebpackConfigFragment } from './config-fragments/dev.fragment.mjs'; import { prodWebpackConfigFragment } from './config-fragments/prod.fragment.mjs'; import { ssrWebappWebpackConfigFragment } from './config-fragments/ssr-webapp.fragment.mjs'; +import { HtmlPreloadCssWebpackPlugin } from './plugins/index.mjs'; import ssrServerEnvBasedConfig from './server.ssr.config.mjs'; const ssrWebappGeneralConfig = merge(ssrWebappWebpackConfigFragment, { @@ -14,6 +15,7 @@ const ssrWebappGeneralConfig = merge(ssrWebappWebpackConfigFragment, { template: path.join(runtimePathById.src, 'index.template.html'), filename: 'server.html', }), + new HtmlPreloadCssWebpackPlugin(), ], }); From 4b00fbdc4e4ffe0a664cc395e7c66c4439a47369 Mon Sep 17 00:00:00 2001 From: Yevhen Uzhva Date: Tue, 8 Jul 2025 22:46:22 +0300 Subject: [PATCH 2/2] release: bundler-webpack@0.2.1 --- packages/bundler-webpack/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bundler-webpack/package.json b/packages/bundler-webpack/package.json index fcc4355..c899c1b 100644 --- a/packages/bundler-webpack/package.json +++ b/packages/bundler-webpack/package.json @@ -1,6 +1,6 @@ { "name": "@mainset/bundler-webpack", - "version": "0.2.0", + "version": "0.2.1-rc.1", "description": "Bundler for web apps", "homepage": "https://github.com/mainset/dev-stack-fe/tree/main/packages/bundler-webpack", "bugs": {