vue-i18n 延迟加载正在加载所有语言环境
vue-i18n lazy loading is loading all locales
我正在尝试为 vue-i18n 实现延迟加载,我正在按照 https://kazupon.github.io/vue-i18n/guide/lazy-loading.html 的说明进行操作。
但是导入的行为与我预期的不同。我希望它只在调用时加载文件,但是当页面刷新时,即使未执行导入,它也会下载与模式“@i18n/messages/*.js”匹配的所有文件。该行存在于代码中这一事实足以加载所有包。
import(/* webpackChunkName: "lang-[request]" */ `@/i18n/messages/${lang}.js`)
我错过了什么?
我正在使用 vue-cli。
我无法使用文档中的语法指示 webpack 单独打包每个文件,但发现以下解决方法虽然不理想但对我有用。
我正在替换文档中的 loadLanguageAsync(lang) 方法:
export function loadLanguageAsync(lang) {
// If the same language
if (i18n.locale === lang) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language hasn't been loaded yet
return import(/* webpackChunkName: "lang-[request]" */ `@/i18n/messages/${lang}.js`).then(
messages => {
i18n.setLocaleMessage(lang, messages.default)
loadedLanguages.push(lang)
return setI18nLanguage(lang)
}
)
有了这个:
export async function loadLanguageAsync(lang) {
// If the same language
if (i18n.locale === lang) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language hasn't been loaded yet
let messages = null;
switch (lang) {
case 'en':
messages = await import(/* webpackChunkName: "i18n-en" */ `@/i18n/messages/en.js`)
break;
case 'fr':
messages = await import(/* webpackChunkName: "i18n-fr" */ `@/i18n/messages/fr.js`)
break;
case 'de':
messages = await import(/* webpackChunkName: "i18n-de" */ `@/i18n/messages/de.js`)
break;
}
if (messages != null) {
i18n.setLocaleMessage(lang, messages.default)
loadedLanguages.push(lang)
return setI18nLanguage(lang)
}
}
因为这已经困扰我一段时间了,我现在刚刚解决了这里是我的延迟加载解决方案(使用vue 和 typescript)。从 4.5 - 7 mb 减少到 2.6 mb。我延迟加载并且不预取语言。
vue.config.js
...
chainWebpack: config => {
// remove the prefetch plugin
// config.plugins.delete("prefetch");
// or:
// modify its options:
config.plugin("prefetch").tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || [];
options[0].fileBlacklist.push(/lang(.)+?\.js$/);
options[0].fileBlacklist.push(/lang(.)+?\.js.map$/);
return options;
});
},
...
更新
如果使用 vue cli pages 这是一个更动态的预取选择器
vue.config.js
...
chainWebpack: config => {
// remove the prefetch plugin
// config.plugins.delete("prefetch");
// or:
// modify its options:
if (config && config.plugins && config.plugins.store) {
const pluginKeys = Array.from(config.plugins.store.keys());
const prefetchKeys = pluginKeys.filter(x => x.indexOf("prefetch") != -1);
prefetchKeys.forEach(key => {
if (config.plugins.has(key)) {
config.plugin(key).tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || [];
options[0].fileBlacklist.push(/lang(.)+?\.js$/);
options[0].fileBlacklist.push(/lang(.)+?\.js.map$/);
return options;
});
}
}
}
},
...
i18n.ts
import Vue from "vue";
import VueI18n from "vue-i18n";
import { LanguageList } from "@/types/languages";
import messages from "@/locales/en_US.json";
Vue.use(VueI18n);
export const i18n = new VueI18n({
locale:
process.env.VUE_APP_I18N_LOCALE ||
"en_US",
silentTranslationWarn: true,
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en_US",
messages: { en_US: messages }
});
const loadedLanguages = ["en_US"]; // our default language that is preloaded
export function setI18nLanguage(lang: string, load = true) {
if (load) {
/* eslint-disable @typescript-eslint/no-use-before-define */
loadLanguageAsync(lang).then(() => {
return lang;
});
} else {
i18n.locale = lang;
// axios.defaults.headers.common['Accept-Language'] = lang
(document.querySelector("html") as HTMLElement).setAttribute("lang", lang);
return lang;
}
}
export function loadLanguageAsync(lang: string) {
if (
i18n.locale !== lang ||
(!loadedLanguages.includes(lang) && LanguageList.find(l => l.code == lang))
) {
if (!loadedLanguages.includes(lang)) {
return import(
/* webpackChunkName: "lang-[request]" */ `@/locales/${lang}`
).then(msgs => {
debugger;
console.log(msgs.default);
i18n.setLocaleMessage(lang, msgs);
loadedLanguages.push(lang);
return setI18nLanguage(lang);
});
}
return Promise.resolve(setI18nLanguage(lang, false));
}
return Promise.resolve(setI18nLanguage(lang, false));
}
App.vue
<script>
import {setI18nLanguage } from "@/i18n";
...
beforeMount() {
setI18nLanguage(i18n.locale);
}
...
</script>
main.ts
...
import { i18n } from "@/i18n";
...
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount("#app");
languages.ts
export interface LanguageI {
code: string;
language: string;
english: string;
}
export const LanguageList: LanguageI[] = [
{ code: "en_US", language: "English", english: "English" },
//...
];
我正在尝试为 vue-i18n 实现延迟加载,我正在按照 https://kazupon.github.io/vue-i18n/guide/lazy-loading.html 的说明进行操作。
但是导入的行为与我预期的不同。我希望它只在调用时加载文件,但是当页面刷新时,即使未执行导入,它也会下载与模式“@i18n/messages/*.js”匹配的所有文件。该行存在于代码中这一事实足以加载所有包。
import(/* webpackChunkName: "lang-[request]" */ `@/i18n/messages/${lang}.js`)
我错过了什么?
我正在使用 vue-cli。
我无法使用文档中的语法指示 webpack 单独打包每个文件,但发现以下解决方法虽然不理想但对我有用。
我正在替换文档中的 loadLanguageAsync(lang) 方法:
export function loadLanguageAsync(lang) {
// If the same language
if (i18n.locale === lang) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language hasn't been loaded yet
return import(/* webpackChunkName: "lang-[request]" */ `@/i18n/messages/${lang}.js`).then(
messages => {
i18n.setLocaleMessage(lang, messages.default)
loadedLanguages.push(lang)
return setI18nLanguage(lang)
}
)
有了这个:
export async function loadLanguageAsync(lang) {
// If the same language
if (i18n.locale === lang) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language was already loaded
if (loadedLanguages.includes(lang)) {
return Promise.resolve(setI18nLanguage(lang))
}
// If the language hasn't been loaded yet
let messages = null;
switch (lang) {
case 'en':
messages = await import(/* webpackChunkName: "i18n-en" */ `@/i18n/messages/en.js`)
break;
case 'fr':
messages = await import(/* webpackChunkName: "i18n-fr" */ `@/i18n/messages/fr.js`)
break;
case 'de':
messages = await import(/* webpackChunkName: "i18n-de" */ `@/i18n/messages/de.js`)
break;
}
if (messages != null) {
i18n.setLocaleMessage(lang, messages.default)
loadedLanguages.push(lang)
return setI18nLanguage(lang)
}
}
因为这已经困扰我一段时间了,我现在刚刚解决了这里是我的延迟加载解决方案(使用vue 和 typescript)。从 4.5 - 7 mb 减少到 2.6 mb。我延迟加载并且不预取语言。
vue.config.js
...
chainWebpack: config => {
// remove the prefetch plugin
// config.plugins.delete("prefetch");
// or:
// modify its options:
config.plugin("prefetch").tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || [];
options[0].fileBlacklist.push(/lang(.)+?\.js$/);
options[0].fileBlacklist.push(/lang(.)+?\.js.map$/);
return options;
});
},
...
更新
如果使用 vue cli pages 这是一个更动态的预取选择器
vue.config.js
...
chainWebpack: config => {
// remove the prefetch plugin
// config.plugins.delete("prefetch");
// or:
// modify its options:
if (config && config.plugins && config.plugins.store) {
const pluginKeys = Array.from(config.plugins.store.keys());
const prefetchKeys = pluginKeys.filter(x => x.indexOf("prefetch") != -1);
prefetchKeys.forEach(key => {
if (config.plugins.has(key)) {
config.plugin(key).tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || [];
options[0].fileBlacklist.push(/lang(.)+?\.js$/);
options[0].fileBlacklist.push(/lang(.)+?\.js.map$/);
return options;
});
}
}
}
},
...
i18n.ts
import Vue from "vue";
import VueI18n from "vue-i18n";
import { LanguageList } from "@/types/languages";
import messages from "@/locales/en_US.json";
Vue.use(VueI18n);
export const i18n = new VueI18n({
locale:
process.env.VUE_APP_I18N_LOCALE ||
"en_US",
silentTranslationWarn: true,
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || "en_US",
messages: { en_US: messages }
});
const loadedLanguages = ["en_US"]; // our default language that is preloaded
export function setI18nLanguage(lang: string, load = true) {
if (load) {
/* eslint-disable @typescript-eslint/no-use-before-define */
loadLanguageAsync(lang).then(() => {
return lang;
});
} else {
i18n.locale = lang;
// axios.defaults.headers.common['Accept-Language'] = lang
(document.querySelector("html") as HTMLElement).setAttribute("lang", lang);
return lang;
}
}
export function loadLanguageAsync(lang: string) {
if (
i18n.locale !== lang ||
(!loadedLanguages.includes(lang) && LanguageList.find(l => l.code == lang))
) {
if (!loadedLanguages.includes(lang)) {
return import(
/* webpackChunkName: "lang-[request]" */ `@/locales/${lang}`
).then(msgs => {
debugger;
console.log(msgs.default);
i18n.setLocaleMessage(lang, msgs);
loadedLanguages.push(lang);
return setI18nLanguage(lang);
});
}
return Promise.resolve(setI18nLanguage(lang, false));
}
return Promise.resolve(setI18nLanguage(lang, false));
}
App.vue
<script>
import {setI18nLanguage } from "@/i18n";
...
beforeMount() {
setI18nLanguage(i18n.locale);
}
...
</script>
main.ts
...
import { i18n } from "@/i18n";
...
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount("#app");
languages.ts
export interface LanguageI {
code: string;
language: string;
english: string;
}
export const LanguageList: LanguageI[] = [
{ code: "en_US", language: "English", english: "English" },
//...
];