前端實踐 | 基於Webpack的多語言解決方案

前端實踐 | 基於Webpack的多語言解決方案

4 人贊了文章

Webpack是目前非常流行的前端工程化解決方案。通過Webpack,可以非常方便的將前端的組件整合成儘可能少的文件,並且進行混淆壓縮,達到上線的要求。也可以用Webpack對LESS等CSS類語言進行編譯。在ES6/ES7流行的今日,也可以通過Babel等Loader,將ES6的語法轉換為ES5,提前讓前端工程師們感受到語法糖的美妙。

i18n(Internationalization,即國際化)是前端工程師非常容易遇到的問題。在傳統的頁面渲染中,一般是由後端的框架中,調用i18n模塊直接渲染生成頁面,這一部分內容基本上不需要前端工程師來考慮。但是在當下的諸多MVVM的框架構建的前端工程中,頁面模版是由前端生成的,在這個情況下,多語言,也成為了前端工程師面對的一個問題。

在雲極星創的雲平台產品上,我們從一開始架構的時候,就把多語言作為我們平台的標配,因此i18n也成為雲極星創前端開發過程中必須直面和解決的問題。我們的前端開發團隊在經歷了幾輪的方案測試推翻再測試後,最終用Webpack的方式解決了多語言的問題。

方案一

一般來說,i18n文件都是以key/value的JSON格式存儲。

在我們的項目構建的第一天,就在項目中引入了i18n。當時項目中採用的是requirejs來載入js代碼,並且在項目發布的時候,通過r.js打包成一個單獨的文件(其實當時並沒有涉及到Webpack)。

當時的代碼,看起來,大致是這樣的:

define([lang.json],function(__) {

var language = getLanguage(); //獲取當前的語言選項。

var label = __[language][label];

/* 然後將該文案應用於程序中。*/

});

其中lang.json大致長這樣:

{

"en": {

"label": "Label"

},

"zh-CN": {

"label": "文案"

}

這個方案從當時看來還是比較不錯的方案,把i18n和代碼完全剝離,方便文案的修改。這個方案最大的問題是,多種語言同時被require。在用r.js打包時,所有的文案會被打包進入一個文件。

想像一下,如果需要支持五種語言,那需要到js里的多語言的數量。隨著時間的推移,代碼量的增長,這個問題越來越突出。

方案一 OUT

方案二

然後,我們對代碼做了一次重構,用上了Webpack來打包。淘汰了requirejs。在重構的過程中,我們使用了另外一種方法來處理i18n。

這個方案的大致的思路如下:

1.將所有的i18n的配置分別存到不同的文件里。

比如zh-CN.lang.json的內容大致如下:

{

"label": "文案"

}

2. 然後每次編譯只打包一個語言並生成js文件。

3. 在開始編譯之前,將1中的zh-CN.lang.json複製生成lang.json。

4. 在代碼中,統一require生成的lang.json文件。

const __ =require(./lang.json);

constlabel = __.label;

5. 由於在開始編譯之前,lang.json已經變成我們需要的語言文件,因此4中可以直接require到我們需要的i18n文件。

這樣,每個語言會通過打包生成一個js文件。在客戶端載入的時候,不需要載入沒有用到的多語言文件,從而實現了瘦身。

然而,這個方案很快又暴露了問題。

首先,這個文件是一個全局的文件,在寫組件的時候,不能基於組件級別去定製一個i18n文件。

其次,這個文件是全局的,在具體的開發過程中,會遇到key值衝突的情況。

為了解決key值衝突的情況,我們進行了很多的調研,當時使用了namespace來臨時性的解決了這個問題。

最後,這個方案還需要在正式開始打包前,先複製語言文件,導致多種語言的打包不能同時開始。

方案二OUT

方案三

我們又進行了一輪探討和思考。終於,找到了相對完美的一種解決方案—— Loader。

相信很多朋友看到這個標題就已經明白我們的解決方案了。

在Webpack中,Loader是用來對require的代碼進行預處理的,Loader可以在載入代碼過程中做很多預處理,比如可以把CoffeScript編譯成JavaScript,把ES6的代碼編譯成ES5。這些都是非常典型的Loader的作用。

首先,我們還原了JSON文件為一開始的模樣:

{

"en": {

"label": "Label"

},

"zh-CN": {

"label": "文案"

}

並且將lang.json文件拆分開和各個組件存放在一起,這樣修改i18n的時候,思路就會比較清晰,也不需要考慮Key重名的問題了。

然後在代碼中,直接require:

const __ =require(lang.json);

constlabel = __.label;

...

在Webpack的配置文件中,直接啟用我們為此寫的Loader。

最後,只需要每次打包編譯的時候,直接在環境中制定語言信息,Loader會讀整個JSON文件,只留下當前語言的內容,將這些內容打包進入代碼中。

通過這種方法,優雅的解決了所有的i18n中遇到的大大小小的問題。

方案三 PASS

現在我們已經將該Loader開源,在npm上提供下載,歡迎大家下載使用:

lang-loader

作者簡介

蔣琦 雲極星創聯合創始人兼產品開發部總監,有超過十年的前端開發經驗以及超過三年的雲計算相關產品的前端開發經驗。長期關注前端社區的開發,自動化測試以及自動化流程的管理。

推薦閱讀:

非洗不可加深與阿里雲合作:成為同行業內首批物聯網市場合作夥伴
Salesforce的Einstein都能幹些什麼?
計算機論文精選-20180802
阿里雲王牌架構師二問開發者:容器和虛擬化你會怎麼選?
上雲安全 中機助力

TAG:雲計算 | 前端開發 | 多語言 |