寫於 2017.01.13html
隨着react
社區的next.js
框架的發佈,vue
社區也終於誕生了屬於本身的先後端同構框架nuxt.js
。在進一步的接觸與使用中,發現nuxt.js
確實極大地方便了vue
項目的開發,其背後的邏輯也值得咱們玩味。關於nuxt
的具體的用法請查閱官方文檔,本文就不一一贅述了。react
本文主要研究nuxt
的運行原理,分析它從接收一條nuxt
指令,到完成指令背後所發生的一系列事情。webpack
在開始本文以前,請讀者務必親自體驗過nuxt.js
的使用,而且具有必定的vue.js
相關開發經驗。web
經過查看nuxt.js
工程目錄下的package.json
文件,咱們能夠看到下列幾條指令:json
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
}
複製代碼
結合官網的介紹,咱們能夠知道不一樣的指令對應着不一樣的功能:後端
指令 | 描述 |
---|---|
nuxt | 開啓一個監聽3000端口的服務器,同時提供hot-reloading功能 |
nuxt build | 構建整個應用,壓縮合並JS和CSS文件(用於生產環境) |
nuxt start | 開啓一個生產模式的服務器(必須先運行nuxt build 命令) |
nuxt generate | 構建整個應用,併爲每個路由生成一個靜態頁面(用於靜態服務器) |
以上幾條指令,也就是本文將要分析的重點:究竟這些指令的背後,nuxt
都作了一些什麼樣的工做呢?api
打開nuxt.js
的工程目錄,進入到到bin
目錄,咱們能夠看到5個文件:bash
|__ nuxt
|__ nuxt-build
|__ nuxt-dev
|__ nuxt-generate
|__ nuxt-start
複製代碼
每一個文件對應着不一樣的指令。下面咱們經過一張圖來分析每一條指令的執行過程:服務器
從上圖可知,每一條指令基本都是作了這麼幾件事情:
nuxt.config.js
文件的配置;Nuxt()
類,並把上一步讀取到的配置覆蓋Nuxt()
類的默認配置;對應代碼以下(節選):
var nuxtConfigFile = resolve(rootDir, 'nuxt.config.js')
var options = {}
if (fs.existsSync(nuxtConfigFile)) {
options = require(nuxtConfigFile)
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
}
var nuxt = new Nuxt(options)
nuxt.build()
複製代碼
第一步讀取配置以及配置的內容能夠查看官網說明,下面咱們將會對第二步和第三步進行深刻探討。
Nuxt()
類進入到nuxt/lib
目錄,咱們能夠看到以下的文件目錄結構:
|__ app
|__ build
|__ index.js
|__ webpack
|__ generate.js
|__ nuxt.js
|__ render.js
|__ server.js
|__ utils.js
|__ views
複製代碼
目錄當中的nuxt.js
文件,就是咱們要實例化的Nuxt()
類的所在,讓咱們來看看它都包含一些什麼內容,以及各自都有些什麼做用:
上圖中每一步均可以在具體的代碼中自行瀏覽。在用戶輸入指令並實例化了Nuxt()
類之後,實例化出來的nuxt
對象就會執行圖中打了綠色對勾的幾個方法:build()
, render()
, renderRoute()
, renderAndGetWindow()
以及generate()
方法。
同時,Nuxt()
類也提供了一個close()
公有方法,用於關閉其所開啓的服務器。
build()
方法build()
方法對應着nuxt/lib/build/index.js
文件,其基本構成以下:
簡單來講,build()
方法在判斷完運行條件後,會先初始化產出目錄.nuxt
,而後經過不一樣目錄下的文件結構來生成一系列的配置,寫入模板文件後輸出到.nuxt
目錄。接下來,則會根據不一樣的開發環境來調用不一樣的webpack配置,運行不一樣的webpack構建方案。
render.js
文件在nuxt/lib
目錄下找到render.js
文件,它包含着咱們即將要分析的三個方法:render()
, renderRoute()
, renderAndGetWindow()
。
經過這張圖片,咱們能夠知道nuxt
對於處理「客戶端渲染」與「服務端渲染」的邏輯實際上是很是清晰的。
首先,在render()
方法在處理完一系列的路徑問題後,會調用renderRoute()
方法,獲取響應所需內容並完成響應。
其中renderRoute()
方法會判斷當前響應是否應執行服務端渲染。若是是,則調用vue
提供的bundleRenderer()
方法,把html內容渲染完畢之後再總體輸出;若是不是,則直接輸出一個<div id="__nuxt"></div>
字符串,交由客戶端渲染。
最後,經過renderAndGetWindow()
來檢查輸出的html是否存在問題,而後發出通知,代表html可用。
generate.js
文件最後咱們來分析一下generate.js
文件。咱們知道nuxt generate
指令會爲page
目錄下的每個頁面文件單獨生成一個html靜態頁面,功能很是貼心。那麼generate.js
究竟是怎麼工做的呢?
在執行nuxt generate
時,它會先執行前文已經分析過的build()
方法,產出編譯後的文件;而後會初始化dist
目錄,調用resolveRouteParams()
方法,讀取產出後的路由配置並整理。而後經過fs.writeFile()
等API,把內容挨個寫入文件並輸出,最後再統計總的generate()
運行時間。
Nuxt
是一個新誕生的項目,官網文檔也還沒有所有完成。從一個使用者的角度來講,這是一個很是有意思的項目,VueJS
的做者尤大也曾褒獎過這個項目,在VueJS的官網也專門爲其進行推薦。
如此interesting的項目實在很值得深刻研究,做者的代碼和註釋也很是清晰詳細。本文受限於我的水平,在分析理解上不免有出錯的地方,歡迎各位讀者指正!