fix(www): resolve SSG build issues with font preloads, dark theme and… (#7)
… 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
cd40139eea
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 { 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.
|
* 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:
|
* Designed to be merged with defineServiceConfig() in each service's rsbuild.config.ts:
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
@@ -19,6 +25,30 @@ export function localeRsbuildConfig(): RsbuildConfig {
|
|||||||
const rawLocale = process.env.LOCALE ?? '';
|
const rawLocale = process.env.LOCALE ?? '';
|
||||||
const locale: Locale = isLocale(rawLocale) ? rawLocale : DEFAULT_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 {
|
return {
|
||||||
source: {
|
source: {
|
||||||
define: {
|
define: {
|
||||||
@@ -36,24 +66,7 @@ export function localeRsbuildConfig(): RsbuildConfig {
|
|||||||
},
|
},
|
||||||
assetPrefix: `/${locale}/`,
|
assetPrefix: `/${locale}/`,
|
||||||
},
|
},
|
||||||
tools: {
|
plugins: localePlugins,
|
||||||
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;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ export function ssgPlugin(): RsbuildPlugin {
|
|||||||
preload?: string;
|
preload?: string;
|
||||||
inlineFonts?: boolean;
|
inlineFonts?: boolean;
|
||||||
pruneSource?: boolean;
|
pruneSource?: boolean;
|
||||||
|
reduceInlineStyles?: boolean;
|
||||||
}) => { process(html: string): Promise<string> };
|
}) => { process(html: string): Promise<string> };
|
||||||
|
|
||||||
// critters `path` is the filesystem root that corresponds to publicPath.
|
// critters `path` is the filesystem root that corresponds to publicPath.
|
||||||
@@ -121,9 +122,10 @@ export function ssgPlugin(): RsbuildPlugin {
|
|||||||
const critters = new Critters({
|
const critters = new Critters({
|
||||||
path: webDistPath,
|
path: webDistPath,
|
||||||
publicPath: configuredAssetPrefix,
|
publicPath: configuredAssetPrefix,
|
||||||
preload: 'swap', // <link rel="preload" as="style" onload="this.rel='stylesheet'">
|
preload: 'swap', // <link rel="preload" as="style" onload="this.rel='stylesheet'">
|
||||||
inlineFonts: false, // fonts are handled via separate <link rel="preload"> tags
|
inlineFonts: false, // fonts are handled via separate <link rel="preload"> tags
|
||||||
pruneSource: false, // keep full CSS file for post-hydration correctness
|
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) {
|
for (const entryName of entryNames) {
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { pluginMdx } from '@rsbuild/plugin-mdx';
|
|||||||
import remarkFrontmatter from 'remark-frontmatter';
|
import remarkFrontmatter from 'remark-frontmatter';
|
||||||
import remarkMdxFrontmatter from 'remark-mdx-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(
|
export default defineServiceConfig(
|
||||||
mergeConfig(localeRsbuildConfig(), {
|
mergeConfig(localeRsbuildConfig(), {
|
||||||
@@ -44,6 +45,7 @@ export default defineServiceConfig(
|
|||||||
href: `${fontBase}/lato-400.woff2`,
|
href: `${fontBase}/lato-400.woff2`,
|
||||||
crossorigin: true,
|
crossorigin: true,
|
||||||
},
|
},
|
||||||
|
publicPath: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag: 'link',
|
tag: 'link',
|
||||||
@@ -54,6 +56,7 @@ export default defineServiceConfig(
|
|||||||
href: `${fontBase}/lato-700.woff2`,
|
href: `${fontBase}/lato-700.woff2`,
|
||||||
crossorigin: true,
|
crossorigin: true,
|
||||||
},
|
},
|
||||||
|
publicPath: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag: 'link',
|
tag: 'link',
|
||||||
@@ -64,6 +67,7 @@ export default defineServiceConfig(
|
|||||||
href: `${fontBase}/eb-garamond-var.woff2`,
|
href: `${fontBase}/eb-garamond-var.woff2`,
|
||||||
crossorigin: true,
|
crossorigin: true,
|
||||||
},
|
},
|
||||||
|
publicPath: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user