# 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: `

{{msg}}

`, 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` 文件中的 `