前端框架載入腳本
1. vue 框架怎麼才能先渲染頁面 後載入腳本
我們在使用Vue.js的時候,最基本的一個使用,就是在HTML引入Vue.js的庫文件,並寫如下一段代碼:
1.var app = new Vue({
2. el: '#app',
3. data: {
4. message: 'Hello Vue!'
5. }
6.})
new Vue,本質就是生成一個Vue的對象,我們來了解一下這個生成Vue對象的過程是怎樣的:
首先,Vue的入口是/src/entries/web-runtime-with-compiler.js,這是由config.js配置文件決定的。
這個入口文件中import了很多文件,其中有一條主要的脈絡:
/src/entries/web-runtime-with-compiler.js
引用了/src/entries/web-runtime.js
引用了/src/core/index.js
引用了/src/core/instance/index.js
2. 項目復盤:通過動態腳本,實現按需載入語言包
大家好,我是前端西瓜哥,是一名前端開發。
最近做了一個將按需載入語言包的需求,有不少收獲,這里記錄一下。
原來項目是將所有的語言包合並在一起,放到一個 JSON 文件里然後被引入。
打包後的腳本里,有完整的語言包的代碼,導致打包文件非常大。理論上用戶只會使用一種語言,其他的語言沒有載入的必要。
目前來說項目只支持兩種語言,每個語言有文案 4000 多條。如果還是使用全量載入的話,以後支持的語言每多一個,打包後的文件就要膨脹一圈。
做語言包的拆分還是很有必要的。它可以減少載入資源的大小,減少首次頁面載入時間,提高用戶體驗。
實現按需載入語言包的方式很多,我了解到的有三種:
請求 HTML 時,後端做渲染工作,給 HTML 加上語言包的內容。
前端沒有什麼改造的工作量,但問題是不能利用緩存。但這個問題其實也可以解決,就是後端生成好語言包 js 文件,將嵌入語言包內容的方式改為 cdn 引入的方式,可以利用好緩存。
但這讓模板引擎的邏輯變得很重,cdn 上傳到哪裡,如何維護也是個問題。
使用 React 等框架打包出來單頁面應用的文件通常很大,下載需要不少時間。
動態 import 必須在腳本整個下載完後,再執行,所以這是一個串列下載的邏輯。
如果可以的話,我們希望語言包可以和業務代碼同時下載。此外,更重要的一點是,在 動態 import 前,我們不能調用獲取文案的方法 getText 。
我在改造項目代碼時,發現在我動態 import 語言包並 ReactDOM.render() 之前,有些模塊文件調用了getText 方法,因為它們作為枚舉指直接暴露出來,沒有用函數封裝,被 import 時就直接執行了。
語言包都沒載入,你執行 getText 是拿不到文案的,這個方案我果斷放棄。
這種方案利用了腳本里創建腳本的方式。能在更前面的位置載入語言包腳本。
優點是我們可以不需要做後端渲染的工作,讓選擇語言包的邏輯交給前端。但涉及到前端工程化,需要寫插件改變原來的載入腳本形式。
我們的項目使用了 webpack,如果用這個方案,就需要寫一個 webpack 插件去改造 HtmlWebpackPlugin 的構建流程。
目前來說,方案 1 和 方案 3 都是不錯的。
但考慮到我們公司的前後端是分離的,後端的代碼實現對我來說其實是黑盒,我沒有許可權也沒有能力去寫後端代碼。而項目是前端項目,最好還是讓前端來掌控維護。所以我最終選擇了方案 3。
方案1 和方案 2 的更具體介紹,可以看我的這篇文章:前端國際化,該如何實現按需載入語言包?
原來項目打包後的 html 文件大致如下。
app.js 里有全量語言包的內容。
改造後的 html 文件如下:
我們語言包將 app.js 從中提取出來,並且分為多個語言包放到 js 文件,如 zh-CN.js、en-US.js,在 app.js 之前執行。
我們先確認用戶使用的語言是什麼。
如果我們不支持持久化設置,可以通過 navigator.language 或前端的其他地方獲取。
但通常用戶可以設置語言,這個語言標識就要後端給,再請求一次用戶信息可太離譜了,所以這里還是需要後端給我們往 html 里嵌入用戶選擇的語言。然後我們從語言 cdn 列表裡選我們需要的語言。
script 元素默認會將 async 設置為 true,效果是腳本下載完立即執行。需要將其改為 false,保證多個動態腳本順序執行。
文件名使用了哈希,是為了解決瀏覽器緩存問題。
執行後,就會將語言包文案暴露在全局變數中。
業務代碼 app.js 也得改成動態載入形式,如果原來的非動態寫法,執行時機就會早於語言包腳本 。
這里涉及到了 script 的執行時機,具體規則可以看我的這篇文章:script 的三種載入模式:默認載入、defer、async
這樣我們就能保證先執行語言包腳本,再執行 app.js。
app.js 中的業務代碼執行時,使用 getText 方法就能正常通過 key 獲取到對應的文案。
這里 app.js 改為動態的寫法後,需要腳本解析執行後才下載腳本,可以考慮加個 link preload 提前下載腳本。
link 的 preload 作用可以看我的這篇文章。
思路並不復雜,但改造過程中做了很多工作,遇到了不少問題。這里簡單列舉一下,不展開講了,到時候會考慮另寫文章討論。
行文有點倉促,想到什麼寫什麼,希望對你做按需載入語言方案有一定的幫助。
我是啥都寫寫的前端西瓜哥,歡迎關注我。