ä»å£¹å¼å§åå端å离 [ Vue2.0+.NetCore2.1] äºåå âClient渲æãServer渲æç¥å¤å°{è¡¥å }...
åè¨
书æ¥ä¸æï¼æ¨å¤©ç®åç说å°äº SSR æå¡ç«¯æ¸²æçç¸å ³å 容ãäºåäºâ忢SSRæå¡ç«¯æ¸²æãï¼ä¸»è¦è¯´æäºç¸å ³æ¦å¿µï¼ä»¥å为ä»ä¹ä½¿ç¨çï¼æ¨å¤©çä¸ä¸ªå°æ åå 为æ¶é´é®é¢ï¼æ²¡æå¥½å¥½çç»å¤§å®¶éºå¼æ¥è®²ï¼ä»å¤©å¢ï¼å±ä»¬å°±ç»§ç»è¯´ä¸ä¸è¿ä¸ª SSR æå¡ç«¯æ¸²æï¼å¹¶ç»åç Client 客æ·ç«¯æ¸²æï¼ä¸èµ·è¯´ä¸è¯´ç¸å ³çå 容ï¼å½ç¶è¿æ¯å´ç»çåçæ¥çï¼å¹¶ä¸æ¯è¦æå»ºé¡¹ç®ï¼é¡¹ç®æä¼å¨ä¸ä¸ä¸ªç³»å说å°ï¼ç»è¿å群éå°ä¼ä¼´çåéï¼å¹¶é纳大家çæè§ï¼æåæ¥èèäºä¸ï¼ä¸ä¸ä¸ªç³»åæä¼è¯´ä¸** Nuxt.js** ç¸å ³å å®¹ï¼ææè§è¿ä¸ªå¾æå¿ è¦ç说ï¼ç°å¨ç½ç«SEOæ¯ç°å¸¸éè¦æ»´ ï¼ï¼ç¶ååä¸ä¸ä¸ªç³»åå°±æ¯æå»ºä¸ä¸ªåè½ä¸°å¯ç åå°ç®¡çç³»ç» ä½ä¸ºå¼æºé¡¹ç®ï¼æéæè´§çå°ä¼ä¼´æ¥ç¾¤éï¼å±ä»¬ä¸èµ·å¼æºå§åååã
è¿ä¸ªæ¶åç»å¿çå°ä¼ä¼´ä¼åç°ï¼æ¯å¤©çé£ä¸ªèå¾ä¸è§äºï¼ååï¼å¹¶æ²¡æï¼èæ¯å¨æä¸è¾¹ï¼çææ«å°±ç¥éäºã
ä¸ãClient æµè§å¨ç«¯æ¸²ææ¯ææ ·è¿è¡ç
为äºä»ç»æµè§å¨æ¸²ææ¯æä¹åäºï¼æä»¬è¿è¡ä¸ä¸npm run build ççæä»¬ä¹åç项ç®ââå°±æ¯æä»¬ç个人å客第ä¸çï¼å¤§å®¶åºè¯¥è¿è®°å¾ã äºåäºâVue宿ï¼ä¸ªäººå客第ä¸ç(axios+router)ãï¼åå¸çæ¬çæä»¶ï¼å°åºæåªäºä¸è¥¿ï¼
æ§è¡
npm run build
è¿éæä»¬éè¿ Webpack æå ï¼å°æä»¬çé¡¹ç®æå ï¼çæä¸ä¸ª dist ç®å½ ï¼æä»¬å¯ä»¥çå°é颿 css+fonts+js æä»¶å¤¹ï¼è¿æä¸ä¸ª index.html éæé¡µé¢ï¼æä»¬æå¼è¿ä¸ªéæé¡µé¢ï¼å¯ä»¥çå°ä¸é¢å 容ï¼
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<link rel=icon href=/favicon.ico>
<title>blogvue3</title>
<link href=/js/about.143cb27a.js rel=prefetch>
<link href=/css/app.51e9ecbc.css rel=preload as= style>
<link href=/css/chunk-vendors.5aa02cc7.css rel=preload as= style>
<link href=/js/app.16d68887.js rel=preload as=script>
<link href=/js/chunk-vendors.1c001ffe.js rel=preload as=script>
<link href=/css/chunk-vendors.5aa02cc7.css rel=stylesheet>
<link href=/css/app.51e9ecbc.css rel=stylesheet>//å
¨é¨é½æ¯æ ·å¼æä»¶ï¼å¯å¿½ç¥ç ç©¶
</head>
<body>
<noscript>
<strong>We're sorry but blogvue3 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id=app />//é¡µé¢æè½½å
¥å£
<script src=/js/chunk-vendors.1c001ffe.js />//vue ç¨å°çåºåæä»¶ï¼vue-cliå
¨å®¶æ¡¶é»è®¤é
ç½®éé¢è¿ä¸ªchunkå°±æ¯å°ææä»node_modules/érequire(import)çä¾èµé½æå
å°è¿é
<script src=/js/app.16d68887.js />//è¿ä¸ªå°±æ¯æä»¬é¡¹ç®çæ ¸å¿å
容ï¼ä¸»è¦å°±æ¯ app.vue çå
容ï¼å°è£
äºæææ¹æ³ï¼å
æ¬è·¯ç±å页颿¸²æä¹ç±»ç
</body>
</html>
大家è§å¯çæçæä»¶ï¼åªæä¸ä¸ªdivæè½½å ¥å£ï¼å¹¶æ²¡æå¤ä½çdomå ç´ ï¼é£ä¹é¡µé¢è¦æä¹åç°å¢ï¼çæ¡æ¯js appendæ¼æ¥ï¼å¯¹ï¼ä¸é¢çé£äº js ä¼è´è´£innerHTMLãèjsæ¯ç±æµè§å¨è§£éæ§è¡çï¼æä»¥å¢ï¼æä»¬ç§°ä¹ä¸ºæµè§å¨æ¸²æï¼ç¸ä¿¡è¿é大家åºè¯¥å¾æç½è¿ä¸ªåçäºï¼åæä»¬å¹³æ¶ç¨ jQuery åå±é¨å¼æ¥å è½½æ¯ä¸æ ·çï¼ä½æ¯ï¼è¿æå 个è´å½ç缺ç¹ï¼
- jsæ¾å¨domç»å°¾ï¼å¦æjsæä»¶è¿å¤§ï¼é£ä¹å¿ ç¶é æé¡µé¢é»å¡ã
- éçæä»¬çä¸å¡éæ±å¢å¤§ï¼æå åç js æä»¶ææ¥æå¤§ï¼é¡µé¢ç½å±æ´å ææ¾ï¼ç¨æ·ä½éªææ¾ä¸å¥½ï¼ç¹å«æ¯é¦é¡µï¼å 个ï¼å å个ç»ä»¶ä¸èµ·æ¸²æï¼å¤©è®·ï¼ä¸æ¢ç¸ä¿¡
- ä¸å©äºSEO
- 客æ·ç«¯è¿è¡å¨èçJavaScript弿ä¸
è¿ä¸ªæ¶åï¼æä»¬å°±æ³å ¶ä»çä¸äºåæ³ï¼æ¯å¦ä¼åç¬ç»æä»¬çé¦é¡µåä¸ä¸ªéæå¤çï¼ä¸ºäºåºå¯¹ç¸åºé度ï¼ä½æ¯è¿ä¸ªå¹¶ä¸æ¯ä¸ä¸ªå¥½çåæ³ï¼æä»¬éè¦å¤ç两å¥é»è¾ï¼åºäºä»¥ä¸çä¸äºé®é¢ï¼æå¡ç«¯æ¸²æå¼ä¹æ¬²åº....
æ»ç»ï¼ç¸ä¿¡å¤§å®¶çå°è¿éåºè¯¥é½è½æç½ï¼å®¢æ·ç«¯æ¸²æçå·¥ä½åçäºï¼å ¶å®å°±æ¯å¼åçæ¶åç»ä»¶åï¼ç¶åéè¿ webpack æå å·¥å ·ï¼å°æä»¬çé»è¾å¤ç js ï¼æå ææä»¶ï¼ç¶ååå端页é¢ä¸èµ·é¨ç½²ï¼è¿æ ·å°±è½è®²æ°æ®å¨ DOM ä¸å±ç¤ºåºæ¥äºã
äºãServer æå¡ç«¯æ¸²ææ¯ææ ·è¿è¡ç
ä¸è¾¹å±ä»¬çäºå®¢æ·ç«¯æµè§å¨æ¸²æï¼æç½äºåçåå¼ç«¯ï¼å±ä»¬è¿ä¸ªæ¶åå°±éè¦ç¨å°æå¡å¨æ¸²æï¼SSR , Server Side Render
çç®ç§°, æå¡ç«¯æ¸²æ. é¦å
æå¡ç«¯æ¸²æçææ³ç±æ¥å·²ä¹
, å¨ ajax
å
´èµ·ä¹å, ææ web åºç¨é½æ¯æå¡ç«¯æ¸²æ, æå¡å¨ç´æ¥è¿å html ææ¬ç»æµè§å¨, ç¨æ·æä½æ¯å¦å¨ç»éé¡µé¢æäº¤è¡¨å, æåå跳转å°é¦é¡µ, æå¡å¨éè¦è¿å两个页é¢. è¿æ ·çå¼ç«¯æ¾èæè§, å å¤§äºæå¡å¨çæ¶èï¼å°äº vue æ¶ä»£ï¼å±ä»¬è½ç¶æ¯éè¿ api è¿åçJsonï¼ä½æ¯éè¦ node æå¡å¨, å¾èè´¹æ§è½, éè¦å好ç¼ååä¼å, ç¸å½äºç©ºé´æ¢æ¶é´ã
è¿éå±ä»¬å 说ä¸åç
ä»è¿ä¸ªå¾é大家åºè¯¥ä¹è½çå°ï¼æä»¬çSSRæå æµç¨ååäºï¼å¨å®¢æ·ç«¯æ¸²æçæ¶åï¼æä»¬ webpack æ¯æå æjs约ææä»¶ï¼ç´æ¥åç»æµè§å¨ï¼ç¶ååè·åæ°æ®æ¸²æDOMï¼
ç½ç»è§£éæç¹å¿ç¾æ¶©é¾æï¼ssr æä¸¤ä¸ªå ¥å£æä»¶ï¼client.js å server.jsï¼ é½å å«äºåºç¨ä»£ç ï¼webpack éè¿ä¸¤ä¸ªå ¥å£æä»¶åå«æå æç»æå¡ç«¯ç¨ç server bundle åç»å®¢æ·ç«¯ç¨ç client bundle. 彿å¡å¨æ¥æ¶å°äºæ¥èªå®¢æ·ç«¯ç请æ±ä¹åï¼ä¼å建ä¸ä¸ªæ¸²æå¨ bundleRendererï¼è¿ä¸ª bundleRenderer ä¼è¯»åä¸é¢çæç server bundle æä»¶ï¼å¹¶ä¸æ§è¡å®ç代ç ï¼ ç¶ååéä¸ä¸ªçæå¥½ç html å°æµè§å¨ï¼çå°å®¢æ·ç«¯å è½½äº client bundle ä¹åï¼ä¼åæå¡ç«¯çæçDOM è¿è¡ Hydration(夿è¿ä¸ªDOM åèªå·±å³å°çæçDOM æ¯å¦ç¸åï¼å¦æç¸åå°±å°å®¢æ·ç«¯çvueå®ä¾æè½½å°è¿ä¸ªDOMä¸ï¼ å¦åä¼æç¤ºè¦å)ã
å¯ä»¥çåºæ¥ï¼æä»¬å¢å äºä¸ä¸ªæ¥éª¤ï¼å°±æ¯ä¹åæä»¬æ¯å¨æµè§å¨éï¼éè¿JavaScriptæ¡æ¶æ¥æ¸²ææ°æ®çï¼ä½æ¯ç°å¨æä»¬ç请æ±ä¸é´èµ°äºä¸é node æå¡å¨ï¼ç¶å node æå¡å¨å¸®æä»¬çæç¸åºç Html çæ®µï¼ç´æ¥åéç»æµè§å¨ï¼é£æµè§å¨è¯å®æ¯è®¤è¯htmlçï¼æä»¥ä¸ç¨åéè¿ js å»è·åæ°æ®æ¸²æäºï¼ç´æ¥å°±æ¸²æäºï¼å¯å¤§æ¦å°±æ¯è¿æ ·ï¼å°±å¥½åå¤äºä¸ä¸ªä¸é´ä»¶ã
ç¸ä¿¡å¤§å®¶çå 容å¯è½ä¸æ¯å¾æ¸ æ¥ï¼å ³é®æ¶åè¿æ¯å¾ä¸ä»£ç æè½è¯´çæ´æ¸ æ°ã
ä¸ãéè¿ä»£ç å®ç°æå¡ç«¯æ¸²æ
客æ·ç«¯æ¸²æå±ä»¬å°±ä¸å代ç äºå§ï¼è¿äºå¤©é½åäºå¾å¤äº
1ãé¦å æä»¬æ°å»ºä¸ä¸ªæä»¶å¤¹ Vue_SSR_Demo å¹¶å¯¹å ¶ node æå¡åå§å
æ§è¡
npm install vue vue-server-renderer --save
ä¼çå°çæä¸ä¸ª node_modules æä»¶å¤¹ å package-lock.json æä»¶ã
ç¶åæ§è¡
npm install express --save
å®è£ express çnodeæå¡ã
2ãç¶åå建ä¸ä¸ª index.html 页é¢ï¼ä½ä¸ºä¸ä¸ªæ¿è½½é¡µé¢ï¼ç±»ä¼¼æä»¬ vue-cli èææ¶ä¸ç index.html
<!-- å¦åvue-cliå建项ç®ä¸çindex.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{title}}</title> {{{meta}}} </head>
<body>
<!--vue-ssr-outlet-->
<!--âââââ æ³¨æä¸è¾¹çæ ¼å¼ä¸å®è¦æï¼å¹¶ä¸ä¸è½å¸¦ç©ºæ ¼ âââââ-->
</body>
</html>
3ãæ°å»ºä¸ä¸ª server.js æä»¶ï¼ç¨ä½æä»¬ç坿å¡å ¥å£
const Vue = require('vue')//å¼å
¥ vue
const server = require('express')()//å¼å
¥ express æå¡æ¡æ¶
const fs = require('fs') //读å html 模ç
const renderer = require('vue-server-renderer').createRenderer({
template: fs.readFileSync('./index.html', 'utf-8')//æä»¶å°åè·¯å¾
}) // æ¤åæ°æ¯vue çæDomä¹å¤ä½ç½®çæ°æ® å¦vueçæçdomä¸è¬ä½äºbodyä¸çæä¸ªå
ç´ å®¹å¨ä¸ï¼ //æ¤æ°æ®å¯å¨headeræ ç¾çä½ç½®æ¸²æï¼æ¯renderer.renderToString()ç第äºä¸ªåæ°ï¼ //第ä¸ä¸ªåæ°æ¯vueå®ä¾ï¼ç¬¬ä¸ä¸ªåæ°æ¯ä¸ä¸ªåè°å½æ°ã
const context = {
title: 'èå¼ çå²å¦',
meta:` <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="vue-ssr">
<meta name="generator" content="GitBook 3.2.3"> `
} //å®ä¹æå¡
server.get('*', (req, res) => { //å建vueå®ä¾ 主è¦ç¨äºæ¿æ¢index.htmlä¸body注éå°æ¹çå
å®¹ï¼ //index.htmlä¸ <!--vue-ssr-outlet-->çå°æ¹ ï¼çº¦å®çæ
const app = new Vue({
data: {
url: req.url,
data: ['C#', 'SQL', '.NET', '.NET CORE', 'VUE'],
title: 'æçæè½å表' }, //template ä¸çææ¬æå¤å±ä¸å®è¦æå®¹å¨å
è£¹ï¼ åvueçç»ä»¶ä¸æ¯ä¸æ ·çï¼ //åªè½æä¸ä¸ªç¶çº§å
ç´ ï¼è¿éæ¯divï¼
template: ` <div>
<p>{{title}}</p>
<p v-for='item in data'>{{item}}</p>
</div> `
}) //å° Vue appå®ä¾æ¸²æä¸ºå符串 (å
¶ä»çAPIèªå·±çç¨æ³æ¯ä¸æ ·ç)
renderer.renderToString(app, context, (err, html) => { if (err) {
res.status(500).end('err:' + err) return } //å°æ¨¡çåéç»æµè§å¨
res.end(html) //æ¯æ¬¡è¯·æ± é½å¨node æå¡å¨ä¸æå°
console.log('success')
})
}) //æå¡ç«¯å£å¼å¯å¹¶çå¬
server.listen(8060, () => {
console.log('server success!')
})
ææ¡£ä¸çè§£éå·²ç»å¾è¯¦ç»äºï¼å¤§å®¶å¯ä»¥èªè¡çä¸çï¼è¿æ ·æä»¬å°±å®ä¹å¥½äºä¸ä¸ª node æå¡ï¼å¹¶éè¿ express æ¡æ¶ï¼å°æä»¬ç vue å®ä¾éè¿ renderer.renderToString() æ¹æ³çæå符串ï¼è¿åå°æµè§å¨ã
4ãå¼å¯ node æå¡
æ§è¡
node server
注æï¼è¿éç server æ¯æä»¬çæä»¶åï¼ä½ ä¹å¯ä»¥ç¨å ¶ä»çï¼æ¯å¦ node aaa.jsï¼æè node aaa
è¿ä¸ªæ¶åï¼æä»¬å°±åç°æä»¬å·²ç»æåçææä»¬ç页é¢å 容è¿åå°äºæµè§å¨ï¼ä¸ºä»ä¹å¢ï¼å 为æä»¬ç页颿ºä»£ç å·²ç»æå 容äºï¼è¯æä¸æ¯éè¿ js åææ¸²æçãbinggoï¼
å¤§å®¶ææ²¡æå¯¹ SSR æå¡ç«¯æ¸²ææä¸å®çä»»ä½åäºè§£ï¼æ¯ä¸æ¯ååºæ¥ä¸ç¹å¿æè§äºï¼è¿ä¸ªè¿æ¯æç®åçä¸ä¸ª node æå¡å¨æ¸²æã
代ç å°±ä¸ä¸ä¼ äºï¼å¤§å®¶ç²è´´å¤å¶å°±è¡ï¼å ¨é¨ç»ææä»¶
åãéè¿ webpack æå ï¼æ¥æ·±å ¥äºè§£æå¡å¨æ¸²æ
dang dang dangï¼å¦æå¤§å®¶çå°è¿éä¸è´¹å²ï¼æè çæåè¾¹çäºï¼å¥½æ»´ï¼ä½ å¯ä»¥çè¿ä¸åäºï¼å¦æä¸è¾¹ç䏿¯å¾æ¸ æ°ï¼æè å¾é¾æï¼å¥½å§ï¼è¿ä¸åå¯è½æ´ç¾æ¶©äºï¼ä¸è¿æ²¡å ³ç³»ï¼æ ¢æ ¢æ¥ï¼
1ãè¿ä¸ªä»£ç æ¯æ¨å¤©çï¼å±ä»¬è¿ééæ°è¯´ä¸ä¸
ç»æå¦ä¸ï¼
âââ dist ãã ã // ä¿åæä»¬çæå
åçæä»¶
âââ node_modules ãã// ä¾èµå
æä»¶å¤¹
âââ entry ãã ã // æå
å
¥å£æä»¶å¤¹
â âââ entry-server.js // æå¡ç«¯ æå
å
¥å£æä»¶
âââ src ãããã // æä»¬ç项ç®çæºç ç¼åæä»¶
â âââ views // viewåæ¾ç®å½
â â âââ about.vue ãããã //about 页é¢
â â âââ like.vue ãããã ã //like 页é¢
â â âââ Home.vue ããã //Home 页é¢
â âââ App.vue ãããããã // Appå
¥å£æä»¶
â âââ main.js ããããã ã // 主é
ç½®æä»¶
â âââ router.js ããããã // è·¯ç±é
ç½®æä»¶
âââ .babelrc // babel é
ç½®æä»¶
âââ package.json // 项ç®ä¾èµå
é
ç½®æä»¶
âââ package-lock.json // npm5 æ°å¢æä»¶ï¼ä¼åæ§è½
âââ server.js // server æä»¶
âââ README.md // è¯´æææ¡£
å±ä»¬ååç说ä¸è¯´
2ãæ®éçapp代ç å
è¿ä¸åï¼å°±æ¯å¯¹åºçæä»¬ src æä»¶å¤¹ä¸ç模æ¿ï¼è¿äºå 容大家ä¸å®å¾çæäºï¼å°±ä¸å¤è¯´äºï¼å°±æ¯ ç»ä»¶çå®ä¹ãè·¯ç±å®ä¹ãappå ¥å£å main.js ä¸»æ¹æ³ï¼è¿ééç¹è¯´ä¸ main.js
å¨ä¹åç main.js æä»¬æ¯ç´æ¥å®ä¾å vue() ï¼ç¶å对 #appp è¿è¡æè½½çï¼ä½æ¯ç°å¨å±ä»¬åæäº æå¡å¨æ¸²æï¼è¿éå°±ä¸è½æè½½äºï¼èæ¯æå建çvueå®ä¾è¿ååºå»ã
//main.js
import Vue from 'vue' import createRouter from './router' import App from './App.vue'
// 导åºä¸ä¸ªå·¥å彿°ï¼ç¨äºå建æ°çvueå®ä¾
export function createApp() { const router = createRouter() const app = new Vue({
router,
render: h => h(App)
}) return app
}
ä½ ä¼é®äºï¼ä½æ¯è¿åç»è°å¢ï¼æ¬¸ï¼ï¼è¿ä¸ªé®é¢å¥½ï¼è¯·å¾ä¸çã
3ã讲æä»¬ç vueå®ä¾å°è£ å° promise
ç½åæ»ç»ï¼æè°Promiseï¼ç®å说就æ¯ä¸ä¸ªå®¹å¨ï¼éé¢ä¿åçæä¸ªæªæ¥æä¼ç»æçäºä»¶ï¼é常æ¯ä¸ä¸ªå¼æ¥æä½ï¼çç»æãä»è¯æ³ä¸è¯´ï¼Promise æ¯ä¸ä¸ªå¯¹è±¡ï¼ä»å®å¯ä»¥è·å弿¥æä½çæ¶æ¯ãPromise æä¾ç»ä¸ç APIï¼åç§å¼æ¥æä½é½å¯ä»¥ç¨åæ ·çæ¹æ³è¿è¡å¤çã
Promise对象æä»¥ä¸ä¸¤ä¸ªç¹ç¹ã
ï¼1ï¼å¯¹è±¡çç¶æä¸åå¤çå½±åãPromise对象代表ä¸ä¸ªå¼æ¥æä½ï¼æä¸ç§ç¶æï¼Pendingï¼è¿è¡ä¸ï¼ãResolvedï¼å·²å®æï¼åç§° Fulfilledï¼åRejectedï¼å·²å¤±è´¥ï¼ãåªæå¼æ¥æä½çç»æï¼å¯ä»¥å³å®å½åæ¯åªä¸ç§ç¶æï¼ä»»ä½å ¶ä»æä½é½æ æ³æ¹åè¿ä¸ªç¶æãè¿ä¹æ¯Promiseè¿ä¸ªååçç±æ¥ï¼å®çè±è¯ææå°±æ¯âæ¿è¯ºâï¼è¡¨ç¤ºå ¶ä»ææ®µæ æ³æ¹åã
ï¼2ï¼ä¸æ¦ç¶ææ¹åï¼å°±ä¸ä¼ååï¼ä»»ä½æ¶åé½å¯ä»¥å¾å°è¿ä¸ªç»æãPromise对象çç¶ææ¹åï¼åªæä¸¤ç§å¯è½ï¼ä»Pendingå为Resolvedåä»Pendingå为Rejectedãåªè¦è¿ä¸¤ç§æ åµåçï¼ç¶æå°±ååºäºï¼ä¸ä¼ååäºï¼ä¼ä¸ç´ä¿æè¿ä¸ªç»æãå°±ç®æ¹åå·²ç»åçäºï¼ä½ å对Promise对象添å åè°å½æ°ï¼ä¹ä¼ç«å³å¾å°è¿ä¸ªç»æãè¿ä¸äºä»¶ï¼Eventï¼å®å ¨ä¸åï¼äºä»¶çç¹ç¹æ¯ï¼å¦æä½ éè¿äºå®ï¼åå»çå¬ï¼æ¯å¾ä¸å°ç»æçã
æäºPromise对象ï¼å°±å¯ä»¥å°å¼æ¥æä½ä»¥åæ¥æä½çæµç¨è¡¨è¾¾åºæ¥ï¼é¿å äºå±å±åµå¥çåè°å½æ°ãæ¤å¤ï¼Promise对象æä¾ç»ä¸çæ¥å£ï¼ä½¿å¾æ§å¶å¼æ¥æä½æ´å 容æã
ç®åæ¥è¯´ï¼å°±æ¯ææä»¬ mainå ¥å£æä»¶ä¸çvueå®ä¾ï¼é½å°è£ å° promiseï¼å°±åå¢å ä¸ä¸ªå¤è¡£ï¼æ¹ä¾¿æä»¬ webpackæå ã对ï¼éç¹æ¥äº
4ãéè¿ Webpack æå¡å¨æå
/* 5ãwebpack.server.js æå¡ç«¯æå
*/
const path = require('path');//è·åè·¯å¾å¯¹è±¡
const projectRoot = path.resolve(__dirname, '..');//æ ¹è·¯å¾ //å®ä¹æ¨¡å
module.exports = { // æ¤å¤åç¥ server bundle ä½¿ç¨ Node 飿 ¼å¯¼åºæ¨¡å(Node-style exports) // è¿éå¿
é¡»æ¯nodeï¼å 为æå
宿çè¿è¡ç¯å¢æ¯nodeï¼å¨node端è¿è¡çï¼ä¸æ¯å¨æµè§å¨ç«¯è¿è¡ã
target: 'node', // entryéè¦æä¾ä¸ä¸ªåç¬çå
¥å£æä»¶
entry: ['babel-polyfill', path.join(projectRoot, 'entry/entry-server.js')], // è¾åº
output: { //æå®libraryTargetçç±»å为commonjs2ï¼ç¨æ¥æå®ä»£ç exportåºå»çå
¥å£çå½¢å¼ã // å¨node.js䏿¨¡åæ¯module.exports = {...}ï¼commonjs2æå
åºæ¥ç代ç åºå£å½¢å¼å°±ç±»ä¼¼äºæ¤ã
libraryTarget: 'commonjs2',
path: path.join(projectRoot, 'dist'), // æå
åºçè·¯å¾
filename: 'bundle.server.js',// æå
æç»çæä»¶åï¼è¿ä¸ªæä»¶æ¯ç» node æå¡å¨ä½¿ç¨ç
},
module: { // å 为使ç¨webpack2ï¼è¿éå¿
é¡»æ¯rulesï¼å¦æä½¿ç¨useï¼ // 伿¥ä¸ªéï¼vue this._init is not a function
rules: [ //è§å1ãvueè§åå®ä¹
{
test: /\.vue$/,
loader: 'vue-loader',
},//jsè§åå®ä¹
{
test: /\.js$/,
loader: 'babel-loader',
include: projectRoot, // è¿é伿node_moduleséé¢çä¸è¥¿æé¤å¨å¤ï¼æé«æå
æç
exclude: /node_modules/, // ES6 è¯æ³
options: {
presets: ['es2015']
}
},//csså®ä¹
{
test: /\.less$/,
loader: "style-loader!css-loader!less-loader" }
]
},
plugins: [],
resolve: {
alias: { 'vue$': 'vue/dist/vue.runtime.esm.js' }
}
}
åºæ¬çå 容就æ¯ä¸è¾¹è¿äºï¼æ³¨éå·²ç»å¾æ¸ æ¥äºï¼å¤§å®¶å¯ä»¥çä¸çï¼è¿ä¸ªæ¶åæä»¬çåå¤å·¥ä½å°±å·²ç»å好äºï¼ä¸ä¸æ¥å°±æ¹æå äº
5ãæ§è¡æå å½ä»¤ï¼çææå¡ç«¯çº¦ææä»¶ bundle.server.js
npm run server
è¿ä¸ªæ¶åï¼ä½ ä¼åç°ï¼æä»¬çdist æä»¶å¤¹å ï¼å¤äºä¸ä¸ª bundle.server.js æä»¶
æä»¬çä¸ä¸çæçæä»¶ï¼é¨åæªå¾ï¼ä¼åç°ï¼æä»¬çè¿ä¸ªæä»¶å å«äºææé¡µé¢å çå 容忹æ³ï¼ä½æ¯è¿ä¸ª bundle.server.js 并䏿¯ç´æ¥è¿åç»å端çï¼èä¸å¨ node æå¡å¨ä½¿ç¨ç
6ãé ç½® node æå¡å¨å¯å¨æä»¶ï¼è¿ä¸ªæ´ç±»ä¼¼æä»¬ä¸æä¸æå°ç server.js æä»¶
/*7ã server.js */
const express = require('express')()//å¼å
¥express æå¡æ¡æ¶
const renderer = require('vue-server-renderer').createRenderer() const createApp = require('./dist/bundle.server.js')['default']//å¼å
¥æä»¬ååæå
æä»¶ // ååºè·¯ç±è¯·æ±
express.get('*', (req, res) => { const context = { url: req.url } // å建vueå®ä¾ï¼ä¼ å
¥è¯·æ±è·¯ç±ä¿¡æ¯
createApp(context).then(app => {
renderer.renderToString(app, (err, html) => { if (err) { return res.state(500).end('è¿è¡æ¶é误') }
res.send(` <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue2.0 SSR渲æé¡µé¢</title>
</head>
<body> ${html} </body>
</html> `)
})
}, err => { if(err.code === 404) { res.status(404).end('æè¯·æ±ç页é¢ä¸åå¨') }
})
}) // æå¡å¨çå¬å°å
express.listen(8089, () => {
console.log('æå¡å¨å·²å¯å¨ï¼')
})
7ãå¯å¨æå¡
node server
è¿ä¸ªæ¶åæä»¬å°±å¯ä»¥çå°ææäº
好å¦ï¼è¿ä¸ªå°±æ¯ SSR æå¡ç«¯æ¸²æçæ´ä¸ªè¿ç¨ã
çªå¤
åå½å¤§å®¶å¥½ï¼å¨è¿éå¿ç¢çæ¥ååå大家è§é¢äºï¼å±ä»¬çåå端系åå ¥é¨ç¯å·²ç» 26 ç¯äºï¼æç §æç计åï¼åºæ¬ç讲解已ç»å°è¿éäºï¼ç¸ä¿¡å¦æå¤§å®¶æç §æåçç³»åï¼è½æå»ºèªå·±çå客系ç»äºï¼çè³å¦æä½ æ¯è¾å害ï¼å·²ç»å¼å§å¼åä¸å项ç®äºååï¼å±ä»¬è¿éå å顾ä¸ç¥è¯ï¼å æ¬ API ï¼Swagger ææ¡£ï¼Sugar æ°æ®æä¹ å±çORMï¼Repositoryä»å¨æ¶æï¼Asyn/Await 弿¥ç¼ç¨ï¼AOPé¢ååé¢ç¼ç¨ï¼IoCæ§å¶å转åDIä¾èµæ³¨å ¥ï¼Dtoæ°æ®ä¼ è¾å¯¹è±¡ï¼Redisç¼åçå端ç¥è¯ï¼è¿æVue åºç¡è¯æ³ãJSé«çº§ãES6ãVue ç»ä»¶ ãçå½å¨æãæ°æ®ç»å®ãå¼åç¯å¢æå»ºãVue-Cli èææ¶ãaxios Http请æ±ãvue-router è·¯ç±åè®®ãwebpack æå ãVuex ç¶æç®¡ççå端ç¥è¯ãè½ç¶é½æ¯ç®åç说äºä¸ç®æ¯ï¼ä¹æ¯é½æ¶µçäºè¿ä¸ªæ¡æ¶å 容ï¼å±ä»¬å¯ä»¥ççå±ä»¬çç»ææ ï¼è¿ä¸ªæ¯å¤©é½ä¼åºç°çåå,è¿ä¸ªå°±æ¯è¿ä¸ä¸ªæå±ä»¬çè¾è¦ï¼ä¹æ¯å¾æåæ¥æ»´ï¼ç¾¤éçå°ä¼ä¼´é½ç ´50äºï¼è¿æ¯ä¸ªå¤§å¾ï¼å¤§å®¶å¯ä»¥ççï¼
æ¬æ¥æ³çè¦æ¢å ¶ä»çç³»åï¼ä½æ¯å¨ç¾¤éå°ä¼ä¼´ç建议ä¸ï¼è¿æ¯å¨æVue好好说说å§ï¼æèäºä¸ï¼å¨å½åºåçæ¶é´åè¯´ä¸ SSR æ¡æ¶ââNuxt.js å§ï¼æè§è¿ä¸ååºè¯¥æ¯è¦ç¨å°çï¼ä¹æ¯èªå¦çä¸ä¸ªå§ï¼è³äºå½åºä¹åï¼åæ ¢æ ¢èèåå ¶ä»çå§ã
QQ群ï¼
867095512 (blod.core)