You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让SvelteKit仅加载所需语言文件而非7MB打包文件?

如何在SvelteKit中按需加载语言文件,避免打包全部7MB资源?

我用静态类实现网站本地化,原本希望只加载当前所需的语言文件,测试阶段一切正常,但到生产环境后,每个需要翻译的页面都会打包加载约7MB的语言文件——明明实际只用其中一个。网站有单独的语言切换页面,无需翻译,也不存在同一页面实时切换语言的场景。这些语言文件并非我创建,无法缩小体积,想问怎么配置SvelteKit、Rollup、Vite,让它只提供当前需要的语言文件?

原实现代码:

import cn from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_cn.csv';
import de from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_de.csv';
import en from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_en.csv';
import fr from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_fr.csv';
import id from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_id.csv';
import jp from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_JP.csv';
import kr from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_kor.csv';
import pt from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_pt.csv';
import ru from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_ru.csv';
import sp from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_sp.csv';
import tc from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_tc.csv';
import th from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_th.csv';
import vn from '../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_vn.csv';

const bindings = {
    cn: cn,
    de: de,
    en: en,
    fr: fr,
    id: id,
    jp: jp,
    kr: kr,
    pt: pt,
    ru: ru,
    sp: sp,
    tc: tc,
    th: th,
    vn: vn
};

class Lang {
    // eslint-disable-next-line no-unused-vars
    static Get(str, remove_spaces = false, must_translate = false) {
        if (remove_spaces) {
            str = str.replace(/ /g, '_').toUpperCase();
        }

        try {
            const entry = bindings[Cookies.get('lang')].find((entry) => entry.name === str);
            let composedregex = new RegExp('<[^>]*>', 'g');

            return entry.value.replaceAll(composedregex, '');
        } catch (e) {
            if (must_translate) {
                return null;
            } else {
                try {
                    // Fallback to English
                    const entry = en.find((entry) => entry.name === str);
                    let composedregex = new RegExp('<[^>]*>', 'g');

                    const ret = entry.value.replaceAll(composedregex, '');
                    return ret;
                } catch (error) {
                    // Total failure -> return original string
                    return str;
                }
            }
        }
    }
}
export default Lang;

解决方案:动态导入+代码分割

你当前的问题根源是静态导入所有语言文件,导致Rollup/Vite编译时把所有文件打包进主代码块。改成动态导入后,构建工具会把每个语言文件拆成独立chunk,只有在需要时才加载。

步骤1:重构Lang类,替换静态导入为动态加载

删掉所有静态import,改成运行时根据当前语言动态加载文件:

import Cookies from 'js-cookie';

class Lang {
    static #currentLangData = null;
    static #fallbackLangData = null;

    // 初始化语言数据,页面加载时调用
    static async init(lang = 'en') {
        // 统一处理文件名大小写问题(比如原代码里的JP.csv)
        const normalizedLang = lang.toLowerCase();
        const langFileName = normalizedLang === 'jp' ? 'JP' : normalizedLang;

        try {
            // 动态加载当前语言文件
            const langModule = await import(`../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_${langFileName}.csv`);
            this.#currentLangData = langModule.default;
        } catch (e) {
            console.warn(`Failed to load language ${lang}, falling back to English`);
        }

        // 预加载备用英文,避免回退时的加载延迟
        if (!this.#fallbackLangData) {
            const fallbackModule = await import('../dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_en.csv');
            this.#fallbackLangData = fallbackModule.default;
        }
    }

    static Get(str, remove_spaces = false, must_translate = false) {
        if (remove_spaces) {
            str = str.replace(/ /g, '_').toUpperCase();
        }

        try {
            const entry = this.#currentLangData?.find((entry) => entry.name === str);
            if (!entry) throw new Error('Entry not found');
            
            const composedregex = new RegExp('<[^>]*>', 'g');
            return entry.value.replaceAll(composedregex, '');
        } catch (e) {
            if (must_translate) {
                return null;
            } else {
                try {
                    const entry = this.#fallbackLangData.find((entry) => entry.name === str);
                    const composedregex = new RegExp('<[^>]*>', 'g');
                    return entry.value.replaceAll(composedregex, '');
                } catch (error) {
                    return str;
                }
            }
        }
    }
}

export default Lang;

步骤2:在SvelteKit加载流程中初始化语言

在根layout的load函数里获取当前语言(从Cookie或URL参数),提前完成语言文件加载:

// src/routes/+layout.ts
import Lang from '$lib/Lang';
import Cookies from 'js-cookie';

export async function load() {
    const lang = Cookies.get('lang') || 'en';
    await Lang.init(lang);
    return { lang };
}

步骤3:确保Vite正确分割语言文件

Vite默认会对动态导入做代码分割,无需额外配置,但要注意:

  • 动态导入的路径必须是静态可分析的模板字符串(比如cfg_lang_${lang}.csv),Vite会自动识别所有可能的语言文件,生成对应的独立chunk。
  • 如果语言文件名有大小写不一致(比如JP.csv和其他小写文件名),要在init函数里做兼容处理,避免加载失败。

可选优化:预加载高频语言

如果某些语言使用频率高,可以在根组件里添加预加载标签,减少首次加载延迟:

<!-- src/routes/+layout.svelte -->
<script>
    import { page } from '$app/stores';
</script>

{#if $page.data.lang}
    <link rel="preload" 
          href={`/dumps/files/assets/gameres/dat/cfg/lang/cfg_lang_${$page.data.lang.toLowerCase()}.csv`} 
          as="fetch" 
          crossorigin>
{/if}

内容的提问来源于stack exchange,提问作者xKeeg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:10:36