# vue_ssr
**Repository Path**: ifercarly/vue_ssr
## Basic Information
- **Project Name**: vue_ssr
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2021-09-20
- **Last Updated**: 2022-06-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: SSR
## README
## 01. 渲染一个 Vue 实例
```bash
npm init -y
npm i vue vue-server-renderer
```
`server.js`
```js
const Vue = require('vue')
const renderer = require('vue-server-renderer').createRenderer()
const app = new Vue({
template: `
{{msg}}
`,
data() {
return {
msg: '牛批',
}
},
})
renderer.renderToString(app, (err, html) => {
if (err) throw err
console.log(html)
})
```
## 02. 结合到 Web 服务中
```bash
npm i express
```
`server.js`
```js
const Vue = require('vue')
const express = require('express')
const renderer = require('vue-server-renderer').createRenderer()
const server = express()
server.get('/', (req, res) => {
const app = new Vue({
template: `
{{msg}}
`,
data() {
return {
msg: '牛批',
}
},
})
renderer.renderToString(app, (err, html) => {
if (err) {
return res.status(500).end('Internal Server Error.')
}
res.setHeader('Content-Type', 'text/html; charset=utf8')
res.end(`
Document
${html}
`)
})
})
server.listen(3000, () =>
console.log('Server running at http://localhost:3000')
)
```
## 03. 使用 HTML 模板
`server.js`
```js
const fs = require('fs')
const Vue = require('vue')
const express = require('express')
const renderer = require('vue-server-renderer').createRenderer({
template: fs.readFileSync('./index.template.html', 'utf-8'),
})
const server = express()
server.get('/', (req, res) => {
const app = new Vue({
template: `
{{msg}}
`,
data() {
return {
msg: '牛批',
}
},
})
renderer.renderToString(app, (err, html) => {
if (err) {
return res.status(500).end('Internal Server Error.')
}
res.setHeader('Content-Type', 'text/html; charset=utf8')
res.end(html)
})
})
server.listen(3000, () =>
console.log('Server running at http://localhost:3000')
)
```
`index.template.html`
```html
Document
```
## 04. 在模板中使用外部数据
`server.js`
```js
const fs = require('fs')
const Vue = require('vue')
const express = require('express')
const renderer = require('vue-server-renderer').createRenderer({
template: fs.readFileSync('./index.template.html', 'utf-8'),
})
const server = express()
server.get('/', (req, res) => {
const app = new Vue({
template: `
{{msg}}
`,
data() {
return {
msg: '牛批',
}
},
})
renderer.renderToString(
app,
{
title: 'SSR',
meta: '',
},
(err, html) => {
if (err) {
return res.status(500).end('Internal Server Error.')
}
res.setHeader('Content-Type', 'text/html; charset=utf8')
res.end(html)
}
)
})
server.listen(3000, () =>
console.log('Server running at http://localhost:3000')
)
```
```html
{{{meta}}}
{{title}}
```
## 05. 【构建配置】问题展示
`server.js`
```js
const fs = require('fs')
const Vue = require('vue')
const express = require('express')
const renderer = require('vue-server-renderer').createRenderer({
template: fs.readFileSync('./index.template.html', 'utf-8'),
})
const server = express()
server.get('/', (req, res) => {
const app = new Vue({
template: `
`,
data() {
return {
msg: '牛批',
}
},
methods: {
handleClick() {
console.log('两横一竖')
},
},
})
renderer.renderToString(
app,
{
title: 'SSR',
meta: '',
},
(err, html) => {
if (err) {
return res.status(500).end('Internal Server Error.')
}
res.setHeader('Content-Type', 'text/html; charset=utf8')
res.end(html)
}
)
})
server.listen(3000, () =>
console.log('Server running at http://localhost:3000')
)
```
## 06. 【构建配置】源码结构
`src/app.js`
```js
import Vue from 'vue'
import App from './App.vue'
export function createApp() {
const app = new Vue({
render: (h) => h(App),
})
return { app }
}
```
`src/App.vue`
```html
```
`src/entry-client.js`
```js
import { createApp } from './app'
const { app } = createApp()
app.$mount('#app')
```
`src/entry-server.js`
```js
import { createApp } from './app'
export default (context) => {
const { app } = createApp()
// 服务端的路由处理、数据预取...
return app
}
```
## 07. 【构建配置】安装依赖
```bash
npm i cross-env # 可以通过 npm scripts 设置跨平台的环境变量,以区分打包环境
```
```bash
npm i -D webpack webpack-cli webpack-merge webpack-node-externals @babel/core @babel/plugin-transform-runtime @babel/preset-env babel-loader css-loader url-loader file-loader rimraf vue-loader vue-template-compiler friendly-errors-webpack-plugin
```
## 08. 【构建配置】Webpack
`build/webpack.base.config.js`
```js
/**
* 公共配置
*/
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const path = require('path')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const resolve = (file) => path.resolve(__dirname, file)
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
mode: isProd ? 'production' : 'development',
output: {
path: resolve('../dist/'),
publicPath: '/dist/', // 打包结果的路径前缀
filename: '[name].[chunkhash].js',
},
resolve: {
alias: {
// 路径别名,@ 指向 src
'@': resolve('../src/'),
},
// 当省略扩展名的时候,按照从前往后的顺序依次解析
extensions: ['.js', '.vue', '.json'],
},
devtool: isProd ? 'source-map' : 'cheap-module-eval-source-map',
module: {
rules: [
// 处理图片资源
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
},
// 处理字体资源
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader'],
},
// 处理 .vue 资源
{
test: /\.vue$/,
loader: 'vue-loader',
},
// 处理 CSS 资源
// 它会应用到普通的 `.css` 文件
// 以及 `.vue` 文件中的 `