为何TranslateHttpLoader会多次调用翻译JSON文件?(Ionic+ngx-translate)
ngx-translate频繁请求en.json的解决方案
问题场景
我在@ionic/angular 5.9.4环境中使用ngx-translate,app.module的配置代码如下:
import { TranslateModule, TranslateLoader } from "@ngx-translate/core"; import { TranslateHttpLoader } from "@ngx-translate/http-loader"; export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, "./assets/i18n/", ".json"); } @NgModule({ imports: [ TranslateModule.forRoot({ defaultLanguage: "en", loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient], }, }) ] })
登录应用后,浏览器网络面板显示对en.json的请求次数超过100次,请求状态包括:
Request URL: http://localhost:8100/assets/i18n/en.json
Request Method: GET
Status Code: 304 Not Modified
以及:
Request URL: http://localhost:8100/assets/i18n/en.json
Request Method: GET
Status Code: 200 OK
解决方案
1. 规范TranslateService的使用
- 别在组件的
ngOnInit或模板里频繁调用translate.get()或translate.instant(),尤其是循环渲染的列表组件。要是需要大量翻译文本,提前一次性把所需翻译项获取到,存在组件变量里,别每次渲染都调服务方法。 - 检查有没有订阅
TranslateService.onLangChange后没取消订阅的情况,哪怕切换到同一语言,也会重复加载翻译文件。组件销毁时一定要调用unsubscribe()。
2. 调整TranslateModule配置开启缓存
ngx-translate默认会缓存已加载的翻译文件,但可能因为配置或版本问题导致缓存失效。试试显式设置useDefaultLang:
TranslateModule.forRoot({ defaultLanguage: "en", useDefaultLang: true, // 确保默认语言加载后直接复用,不用重复请求 loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient], }, })
3. 优化静态资源缓存头
请求返回304说明浏览器在尝试缓存,但缓存头可能配置有问题。可以给assets/i18n/*.json设置较长的缓存有效期,减少重复请求。本地开发环境可以调整Ionic的静态资源缓存配置,生产环境在服务器端设置。
4. 自定义带缓存的Loader
如果默认的TranslateHttpLoader缓存不好使,自己写个带缓存逻辑的Loader:
import { TranslateLoader } from '@ngx-translate/core'; import { HttpClient } from '@angular/common/http'; import { Observable, of } from 'rxjs'; import { tap } from 'rxjs/operators'; export class CachedTranslateHttpLoader implements TranslateLoader { private cache = new Map<string, any>(); constructor(private http: HttpClient, private prefix: string = './assets/i18n/', private suffix: string = '.json') {} getTranslation(lang: string): Observable<any> { if (this.cache.has(lang)) { return of(this.cache.get(lang)); } return this.http.get(`${this.prefix}${lang}${this.suffix}`).pipe( tap(translations => this.cache.set(lang, translations)) ); } } // 替换app.module里的HttpLoaderFactory export function HttpLoaderFactory(http: HttpClient) { return new CachedTranslateHttpLoader(http, "./assets/i18n/", ".json"); }
5. 检查Ionic页面生命周期触发逻辑
Ionic页面的ionViewWillEnter这类钩子可能会被频繁触发,如果在这些钩子里面调用翻译相关方法,就会导致重复请求。只在必要的生命周期钩子里初始化翻译,别重复执行。
内容的提问来源于stack exchange,提问作者Rand alrand
相关产品推荐
相关产品推荐

