fix(www): resolve SSG build issues with font preloads, dark theme and RU locale
- Fix depth-dependent duplicate font preload prefixes by using locale-absolute fontBase path and publicPath:false on html.tags to prevent Rsbuild from re-applying assetPrefix (path.posix.join behavior with MPA nested entries) - Fix .dark CSS rule stripped by critters: set reduceInlineStyles:false so critters only processes external stylesheets and leaves inline theme init styles (THEME_INIT_STYLES) intact - Fix NormalModuleReplacementPlugin lost in mergeConfig: refactored locale MDX replacement from tools.rspack function into a proper Rsbuild plugin so mergeConfig concatenates plugin arrays correctly (enables RU locale articles) - Extend Critters type declaration to include reduceInlineStyles option Made-with: Cursor
This commit is contained in:
1 parent
f5e901c131
commit
ce225e3f75
3 files changed
+42
-23
No files matched your search
+32
-19
@@ -1,10 +1,16 @@
|
||||
import { DEFAULT_LOCALE, isLocale, type Locale } from './lib/locale.js';
|
||||
|
||||
import type { RsbuildConfig } from '@rsbuild/core';
|
||||
import type { RsbuildConfig, RsbuildPlugin } from '@rsbuild/core';
|
||||
|
||||
/**
|
||||
* Returns a partial Rsbuild config that enables locale-aware builds.
|
||||
*
|
||||
* The locale MDX replacement is provided as an Rsbuild plugin (rather than a
|
||||
* `tools.rspack` function) so that `mergeConfig` can safely concatenate it
|
||||
* with the service's own `plugins` array. A `tools.rspack` function would be
|
||||
* silently dropped by `mergeConfig` when the service config also defines
|
||||
* `tools.rspack` as a plain object.
|
||||
*
|
||||
* Designed to be merged with defineServiceConfig() in each service's rsbuild.config.ts:
|
||||
*
|
||||
* @example
|
||||
@@ -19,6 +25,30 @@ export function localeRsbuildConfig(): RsbuildConfig {
|
||||
const rawLocale = process.env.LOCALE ?? '';
|
||||
const locale: Locale = isLocale(rawLocale) ? rawLocale : DEFAULT_LOCALE;
|
||||
|
||||
const localePlugins: RsbuildPlugin[] = [];
|
||||
|
||||
if (locale !== DEFAULT_LOCALE) {
|
||||
localePlugins.push({
|
||||
name: 'ermnvldmr:locale-mdx-replacement',
|
||||
setup(api) {
|
||||
// Resolve .en.mdx imports to the locale-specific file when LOCALE != 'en'.
|
||||
// The canonical import is always `.en.mdx`; other locales are resolved here.
|
||||
api.modifyRspackConfig((config, { rspack }) => {
|
||||
config.plugins = [
|
||||
...(config.plugins ?? []),
|
||||
new rspack.NormalModuleReplacementPlugin(
|
||||
/\.en\.mdx$/,
|
||||
(resource: { request: string }) => {
|
||||
resource.request = resource.request.replace(/\.en\.mdx$/, `.${locale}.mdx`);
|
||||
}
|
||||
),
|
||||
];
|
||||
return config;
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
source: {
|
||||
define: {
|
||||
@@ -36,24 +66,7 @@ export function localeRsbuildConfig(): RsbuildConfig {
|
||||
},
|
||||
assetPrefix: `/${locale}/`,
|
||||
},
|
||||
tools: {
|
||||
rspack: (config, { rspack }) => {
|
||||
// Resolve .en.mdx imports to the locale-specific file when LOCALE != 'en'.
|
||||
// The canonical import is always `.en.mdx`; other locales are resolved here.
|
||||
if (locale !== DEFAULT_LOCALE) {
|
||||
config.plugins = [
|
||||
...config.plugins,
|
||||
new rspack.NormalModuleReplacementPlugin(
|
||||
/\.en\.mdx$/,
|
||||
(resource: { request: string }) => {
|
||||
resource.request = resource.request.replace(/\.en\.mdx$/, `.${locale}.mdx`);
|
||||
}
|
||||
),
|
||||
];
|
||||
}
|
||||
return config;
|
||||
},
|
||||
},
|
||||
plugins: localePlugins,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ export function ssgPlugin(): RsbuildPlugin {
|
||||
preload?: string;
|
||||
inlineFonts?: boolean;
|
||||
pruneSource?: boolean;
|
||||
reduceInlineStyles?: boolean;
|
||||
}) => { process(html: string): Promise<string> };
|
||||
|
||||
// critters `path` is the filesystem root that corresponds to publicPath.
|
||||
@@ -121,9 +122,10 @@ export function ssgPlugin(): RsbuildPlugin {
|
||||
const critters = new Critters({
|
||||
path: webDistPath,
|
||||
publicPath: configuredAssetPrefix,
|
||||
preload: 'swap', // <link rel="preload" as="style" onload="this.rel='stylesheet'">
|
||||
inlineFonts: false, // fonts are handled via separate <link rel="preload"> tags
|
||||
pruneSource: false, // keep full CSS file for post-hydration correctness
|
||||
preload: 'swap', // <link rel="preload" as="style" onload="this.rel='stylesheet'">
|
||||
inlineFonts: false, // fonts are handled via separate <link rel="preload"> tags
|
||||
pruneSource: false, // keep full CSS file for post-hydration correctness
|
||||
reduceInlineStyles: false, // preserve theme init styles (prevents .dark rule from being stripped)
|
||||
});
|
||||
|
||||
for (const entryName of entryNames) {
|
||||
|
||||
@@ -6,7 +6,8 @@ import { pluginMdx } from '@rsbuild/plugin-mdx';
|
||||
import remarkFrontmatter from 'remark-frontmatter';
|
||||
import remarkMdxFrontmatter from 'remark-mdx-frontmatter';
|
||||
|
||||
const fontBase = 'static/font';
|
||||
const locale = process.env.LOCALE ?? 'en';
|
||||
const fontBase = `/${locale}/static/font`;
|
||||
|
||||
export default defineServiceConfig(
|
||||
mergeConfig(localeRsbuildConfig(), {
|
||||
@@ -44,6 +45,7 @@ export default defineServiceConfig(
|
||||
href: `${fontBase}/lato-400.woff2`,
|
||||
crossorigin: true,
|
||||
},
|
||||
publicPath: false,
|
||||
},
|
||||
{
|
||||
tag: 'link',
|
||||
@@ -54,6 +56,7 @@ export default defineServiceConfig(
|
||||
href: `${fontBase}/lato-700.woff2`,
|
||||
crossorigin: true,
|
||||
},
|
||||
publicPath: false,
|
||||
},
|
||||
{
|
||||
tag: 'link',
|
||||
@@ -64,6 +67,7 @@ export default defineServiceConfig(
|
||||
href: `${fontBase}/eb-garamond-var.woff2`,
|
||||
crossorigin: true,
|
||||
},
|
||||
publicPath: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user