动态导入(import())可按需加载主题包以减少初始体积,核心是用户切换主题时才加载对应样式模块;将主题CSS分离为.css.js模块导出样式字符串,运行时动态加载并注入style标签;SSR需在客户端执行,配合useEffect等确保首次渲染用默认主题;可预加载常用主题并缓存模块引用。

动态导入(import())可以按需加载主题包,避免一次性打包所有 CSS 或主题配置,减少初始体积。核心思路是:用户切换主题时,才加载对应主题的样式或配置模块。
主题样式文件分离为独立模块
把不同主题的 CSS 写成可被 JS 加载的模块(如用 .css.js 文件导出样式字符串,或用 style 标签注入),而不是直接引入全局 CSS。
- 例如创建
themes/dark.css.js:
// themes/dark.css.js
export default `:root {
--bg-color: #1e1e1e;
--text-color: #e0e0e0;
--border-color: #333;
}`;
```
- 同理准备
themes/light.css.js、themes/sepia.css.js等。
运行时动态加载并应用主题
监听主题切换(如 localStorage 变更、UI 按钮点击),调用 import() 加载对应模块,再将 CSS 注入 标签或写入 :root 自定义属性。
- 推荐封装一个
applyTheme(themeName)函数:
async function applyTheme(name) {
// 移除旧主题 style 标签(可选)
document.getElementById('theme-style')?.remove();
try {
const themeModule = await import(`./themes/${name}.css.js`);
const style = document.createElement('style');
style.id = 'theme-style';
style.textContent = themeModule.default;
document.head.appendChild(style);
} catch (err) {
console.warn(`Failed to load theme: ${name}`, err);
}
}
// 切换深色模式
applyTheme('dark');
```
配合 CSS 自定义属性 + 服务端渲染兼容性
若项目支持 SSR(如 Next.js、Nuxt),注意动态导入只在客户端执行。服务端无法运行 import(),所以主题逻辑应放在 useEffect、onMounted 或 window.onload 中。
- 首次渲染用默认主题(如 light),等 JS 加载后再切到用户偏好主题(从
localStorage或prefers-color-scheme读取); - 用
CSS.customProperties配合 JS 更新,比纯 CSS 切换更可控; - 可结合
matchMedia('(prefers-color-scheme: dark)')自动响应系统设置变化。
进阶:预加载与缓存控制
为提升切换体验,可在用户交互前(如悬停主题按钮)预加载常用主题:
import('./themes/dark.css.js').then(() => {}); // 不立即应用,仅触发加载和缓存- Webpack/Vite 会自动将
import()拆包为独立 chunk,无需额外配置; - 加载后可缓存模块引用(如存在
themeCache['dark']),避免重复解析。











