Vue 서버 렌더링(Vue SSR)
Vue.js는 클라이언트 응용 프로그램을 구축하는 프레임워크이지만, 같은 구성 요소를 서버의 HTML 문자열로 렌더링하여 브라우저에 직접 보내고, 마지막으로 정적 표시를 클라이언트에서 완전히 상호작용할 수 있는 응용 프로그램으로 '활성화' 할 수도 있다.서버가 렌더링하는 Vue.js 응용 프로그램도'동구'또는'통용'이라고 할 수 있으며 프로그램의 대부분 코드는 서버와 클라이언트에서 실행될 수 있다.
서버 렌더링이 필요합니까?
기존 SPA에 비해 SSR의 주요 장점은 다음과 같습니다.
beforeCreate
와 created
갈고리 함수만 호출된다. 이 두 생명주기 함수에서 전역 부작용이 발생하는 코드를 피해야 한다. 예를 들어 그 중에서 사용setInterval
으로timer를 설정하는 것을 피해야 한다.서버 렌더링이 필요하다면 다음 사용법을 계속 보십시오.
기본용법
설치하다.
npm install vue vue-server-renderer --save
참고:
vue-servier-renderer
및 vue
버전 일치 필요 1. 포털 파일 만들기
클라이언트 응용 프로그램과 서버 응용 프로그램 모두 웹 패키지로 두 개의 버블을 포장해야 한다. 서버는 서버 렌더링에 서버 버블을 필요로 하고 클라이언트 버블은 브라우저에 보내서 정적 표시를 혼합하는 데 사용한다.
하나의 기본 항목은 다음과 같다.
src
├── components
│ ├── Foo.vue
│ └── Baz.vue
├── App.vue
├── app.js # entry(universal entry)
├── index.template.html
├── entry-client.js #
└── entry-server.js #
단일 루틴 메커니즘으로 인해 서버 렌더링에서 단일 루틴과 유사한 조작이 있기 때문에 모든 요청이 이 단일 루틴의 조작을 공유하기 때문에 공장 함수를 사용하여 모든 요청 간의 독립성을 확보해야 한다.
app.js
는 주로 exportcreateApp
함수이다.유사하게 store
와 router
는 모두 이런 공장 함수를 내보내야 한다.# app.js
import Vue from 'vue';
import App from './App.vue';
import { createStore } from './store';
import { createRouter } from './router';
export const createApp = () => {
const store = createStore();
const router = createRouter();
const app = new Vue({
router,
store,
render: h => h(App)
});
return { app, router, store };
};
클라이언트 entry에서 응용 프로그램을 만들고 DOM에 마운트합니다.
# entry-client.js
import { createApp } from './app';
const { app, router, store } = createApp();
if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__);
}
router.onReady(() => {
# , asyncData.
# resolve , (double-fetch) 。
# `router.beforeResolve()`, resolve。
router.beforeResolve((to, from, next) => {
...
});
app.$mount('#app');
});
서버 entry는
default export
함수를 내보내고, 렌더링할 때마다 이 함수를 반복합니다.여기서 서버 사이드 루트 일치(server-side route matching)와 데이터 추출 논리(data-pre-fetching logic)를 실행할 수 있습니다.# entry-server.js
import { createApp } from './app';
export default context => {
# , Promise,
# 。
return new Promise((resolve, reject) => {
const { app, router, store } = createApp();
router.push(context.url);
router.onReady(() => {
#
...
}, reject);
});
};
2. 웹팩 구축 구성
구성 파일 구조는 다음과 같습니다.
build
├── dev-server.js
├── setup-dev-server.js
├── webpack.base.conf.js
├── webpack.client.conf.js
├── webpack.dev.conf.js
├── webpack.prod.conf.js
└── webpack.server.conf.js
package.json
패키지 명령:"scripts": {
"dev": "NODE_ENV=dev node server/index.js",
"build:client": "webpack --config build/webpack.client.conf.js --progress --hide-modules --progress",
"build:server": "webpack --config build/webpack.server.conf.js --progress --hide-modules --progress",
"build:prod": "NODE_ENV=prod npm run build:client && NODE_ENV=prod npm run build:server",
},
3. 서버 통합 개발
개발 서비스는 Koa를 사용하고 구성 참조:
import Koa from 'koa';
import koaRouter from 'koa-router';
import { createBundleRenderer } from 'vue-server-renderer';
const app = new Koa();
const router = koaRouter();
const createRenderer = (bundle, options) => {
return createBundleRenderer(
bundle,
{...options, { runInNewContext: false }
);
};
const renderData = (ctx, renderer) => {
const context = {
url: ctx.url
};
return new Promise((resolve, reject) => {
renderer.renderToString(context, (err, html) => {
if (err) {
reject(err);
}
resolve(html);
});
});
};
let renderer;
require('../build/setup-dev-server.js')(app, (bundle, options) => {
renderer = createRenderer(bundle, options);
});
# proxy api request
const proxy = require('koa-server-http-proxy');
# ...
router.get('*', async (ctx, next) => {
if (!renderer) {
ctx.type = 'html';
return (ctx.body = 'waiting for compilation...');
}
let html;
try {
html = await renderData(ctx, renderer);
} catch (e) {
#
...
}
ctx.body = html;
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(80, '0.0.0.0', () => {
console.log(`server is running...`);
});
4. 온라인 서버 통합
온라인 서비스는 Egg를 사용합니다.js, 참조 구성은 다음과 같습니다.
# app/controller/home.js
const Controller = require('egg').Controller;
const path = require('path');
const { createBundleRenderer } = require('vue-server-renderer');
const serverBundle = require('../public/vue-ssr-server-bundle.json');
const clientManifest = require('../public/vue-ssr-client-manifest.json');
const template = require('fs').readFileSync(
path.resolve(__dirname, '../public/index.html'),
'utf-8'
);
const renderer = createBundleRenderer(serverBundle, {
runInNewContext: false,
template,
clientManifest
});
class HomeController extends Controller {
async index() {
const ctx = this.ctx;
const context = { url: ctx.url };
try {
# context
renderer.renderToString(context, (err, html) => {
if (err) {
throw err;
}
ctx.status = 200;
# template, html
ctx.body = html;
});
} catch (error) {
ctx.status = 500;
ctx.body = 'Internal Server Error';
}
}
}
module.exports = HomeController;
라우팅 일치:
router.get(/^(?!\/api\/)/, controller.home.index);
이렇게 하면 개발과 생산 환경 설정에 따라 기본적인 서버 렌더링을 실현할 수 있다.편폭이 제한되어 큰 코드가 잠시 붙지 않았으며, 후속으로 원본 코드 예시를 개방할 것입니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.