基於SPA的項目,打包出來的文件中只有一個index.html做爲入口,再根據頁面的路由加載對應頁面的js。html
當項目須要支持SEO時,在條件容許的狀況下能夠選擇node做爲同構方案,根據url匹配routes中的components,再經過rendersToString方法打印出內容,放到html模板中。此方案的優勢是能夠支持動態路由、後端獲取數據。缺點是每次訪問都要生成一次、引進了node服務。node
若是在網站被訪問以前就把html預編譯好,多個路由對應多個html。後端
在umi項目中配置預編譯很是簡單
umirc.js瀏覽器
plugins: [['@umijs/plugin-prerender']], ssr: true,
把umirc.js中ssr設置成true後,dist文件夾下就多生成了一個umi.server.js文件,它是以/src/pages/.umi文件爲入口、囊括了其餘全部dist/*.js生成的大文件,而且通過了一些環境上的處理。網站
/src/pages/.umi是每次打包後都會生成的中間結果,查看代碼會發現它是以__IS_BROWSER變量區分瀏覽器、node環境,而umi.server.js則是把__IS_BROWSER變量替換成boolean的結果,所以在業務代碼中,能夠直接使用__IS_BROWSER這一變量區分你的邏輯。例如,頁面中一開始有loading等待緩衝的效果,可使用__IS_BROWSER將loading取消,避免編譯出來的內容無效。url
在預編譯以前,想要給html中放入一些內容,但這些內容又不須要在實際業務中展現。這時能夠選擇給routes下定義的component添加getInitialProps方法插件
function Index(props){ return props.nodeContent || 'hello world' } Index.getInitialProps = ()=>({ nodeContent: '個人seo內容' }) export defalut Index
將不常常更新的內容放到getInitialProps中寫死,生成的內容供seo抓取,不過在js執行後會將其刷新掉。ssr
umi-server在調用umi.server.js時會給global變量附加mock過的window對象,例如,在業務代碼中訪問window.location.url時,獲取到的是瀏覽器環境同樣的結果。code
pre-render插件在umi打包結束後,按照routes裏的url一個個訪問ssr,相似於構造虛擬訪問來生成html。component
routes除非指定了黑白名單,不然將生成全部html
umirc.js
[ '@umijs/plugin-prerender', { include: ['/'], exclude: ['/help'] }, ]
umi默認給圖片加了閾值,當小於這個值時生成的圖片使用base64。但在預編譯時生成的html中會產生大量的base64字符,使得html變大。
這裏能夠設置圖片的閾值,減少html的包袱
umirc.js
chainWebpack(config) { config.module .rule('exclude') .use('url-loader') .tap((options) => { return { ...options, limit: 1, }; }); }
最新的umi版本已經解決了動態路由的問題,例如/:id的路由會生成[id].html。若是項目中的動態路由可枚舉,將動態路由改形成一個個寫死的路由,這樣再生成多個html。這樣作的目的是生成更多的html讓seo引擎抓取。若是項目中的動態路由沒法枚舉,或訪問方式有太多種,則須要藉助後端動態實時生成。