SSR
Vue Server Renderer
服务器端渲染(SSR, Server-Side Rendering)是一种在服务器上生成完整的 HTML 页面,然后将其发送到客户端的技术。Vue.js 提供了一个官方工具 Vue Server Renderer 来实现这一点。以下是一个简单的 Vue SSR 示例。
1. 设置项目
首先,我们需要初始化一个新的 Node.js 项目并安装必要的依赖。
mkdir vue-ssr-example
cd vue-ssr-example
npm init -y
npm install vue vue-server-renderer express
2. 创建 Vue 组件
在 src
文件夹中创建一个 App.vue
文件,这是我们的根组件。
mkdir src
src/App.vue
:
<template>
<div id="app">
<h1>Hello, Server-Side Rendering with Vue!</h1>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3. 创建服务器
在项目根目录中创建一个 server.js
文件,用于设置 Express 服务器和 Vue SSR。
server.js
:
const express = require('express');
const { createBundleRenderer } = require('vue-server-renderer');
const fs = require('fs');
const path = require('path');
const resolve = file => path.resolve(__dirname, file);
const server = express();
// 创建服务器渲染器
const template = fs.readFileSync(resolve('./index.template.html'), 'utf-8');
const serverBundle = require('./dist/vue-ssr-server-bundle.json');
const clientManifest = require('./dist/vue-ssr-client-manifest.json');
const renderer = createBundleRenderer(serverBundle, {
runInNewContext: false,
template,
clientManifest
});
server.use(express.static(path.join(__dirname, 'dist')));
server.get('*', (req, res) => {
const context = { url: req.url };
renderer.renderToString(context, (err, html) => {
if (err) {
if (err.code === 404) {
res.status(404).send('Page not found');
} else {
res.status(500).send('Internal Server Error');
}
} else {
res.send(html);
}
});
});
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
});
4. 创建 HTML 模板
在项目根目录中创建一个 index.template.html
文件,这是用于渲染 Vue 应用的模板。
index.template.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue SSR Example</title>
<!-- 用于插入客户端脚本 -->
<!-- vue-ssr-client-manifest will be auto injected -->
</head>
<body>
<!-- 这是应用挂载点 -->
<div id="app"><!-- server-rendered HTML will be injected here --></div>
<!-- built files will be auto injected -->
</body>
</html>
5. 配置 Webpack
在项目根目录中创建一个 webpack.config.js
文件,用于配置 Webpack 打包。
webpack.config.js
:
const path = require('path');
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
module.exports = {
entry: './src/entry-server.js',
target: 'node',
output: {
libraryTarget: 'commonjs2',
path: path.resolve(__dirname, 'dist'),
filename: 'vue-ssr-server-bundle.json'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['.js', '.vue', '.json']
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
},
plugins: [
new VueSSRServerPlugin()
]
};
// 需要另外配置一个 webpack 配置用于生成客户端文件
const clientConfig = {
entry: './src/entry-client.js',
target: 'web',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['.js', '.vue', '.json']
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpe?g|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]?[hash]'
}
}
]
},
plugins: [
new VueSSRClientPlugin()
]
};
module.exports = [clientConfig, module.exports]; // 返回两个配置
6. 创建入口文件
在 src
文件夹中创建两个入口文件:entry-server.js
和 entry-client.js
。
src/entry-server.js
:
import { createApp } from './app';
export default context => {
return new Promise((resolve, reject) => {
const { app, router } = createApp();
router.push(context.url);
router.onReady(() => {
const matchedComponents = router.getMatchedComponents();
if (!matchedComponents.length) {
return reject({ code: 404 });
}
resolve(app);
}, reject);
});
};
src/entry-client.js
:
import { createApp } from './app';
const { app, router } = createApp();
router.onReady(() => {
app.$mount('#app');
});
src/app.js
:
import Vue from 'vue';
import App from './App.vue';
import router from './router';
export function createApp() {
const app = new Vue({
router,
render: h => h(App)
});
return { app, router };
}
src/router/index.js
:
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: () => import('../App.vue')
}
]
})
7. 构建项目
在项目根目录中运行以下命令来构建项目:
npm install webpack webpack-cli webpack-node-externals babel-loader @babel/core @babel/preset-env vue-loader vue-template-compiler file-loader --save-dev
npx webpack --config webpack.config.js
注意:Webpack 5 用户可能需要调整配置,使用 webpack-cli
而不是全局 webpack
命令。
8. 启动服务器
在项目根目录中运行以下命令来启动服务器:
node server.js
现在,你可以打开浏览器访问 http://localhost:8080
,你应该会看到服务器端渲染的 Vue 应用。
这个示例展示了如何使用 Vue 和 Express 实现简单的服务器端渲染。根据实际需求,你可以进一步扩展和优化这个示例。
Nutx
以下是一个关于Nuxt框架的使用案例,涵盖了从包安装到入门使用的整个过程:
一、Nuxt框架安装
-
确保环境准备:
- 安装Node.js和npm(Node包管理器)。
- 可以通过命令行运行
node -v
和npm -v
来检查它们的版本。
-
全局安装Vue CLI(如果尚未安装):
npm install -g vue-cli
-
创建Nuxt项目:
- 使用Vue CLI(或npx)创建一个新的Nuxt项目。
npx create-nuxt-app my-nuxt-app
- 按照提示完成项目设置,如项目名称、编程语言、包管理器、UI框架等。
- 使用Vue CLI(或npx)创建一个新的Nuxt项目。
-
进入项目目录并安装依赖:
cd my-nuxt-app npm install
二、Nuxt项目入门使用
- 项目目录结构:
pages/
:页面组件目录,每个.vue
文件都会生成对应的路由。components/
:Vue组件目录,用于存放可复用的Vue组件。static/
:静态资源目录,用于存放静态文件如图片、字体等。store/
:Vuex状态管理目录,用于管理应用的全局状态。nuxt.config.js
:Nuxt全局配置文件,用于覆盖默认配置。
- 创建页面组件:
<template> <div> <h1>欢迎来到我的Nuxt应用</h1> </div> </template> <script> export default { // 页面组件的逻辑代码 } </script>
- 运行开发服务器:
- 访问
http://localhost:3000
即可在浏览器中查看Nuxt应用。
- 访问
- 使用asyncData在服务器端获取数据:
- 在页面组件中,可以使用
asyncData
方法在服务器端获取数据,并将数据注入到组件中。<template> <div> <h1>文章列表</h1> <ul> <li v-for="article in articles" :key="article.id">{{ article.title }}</li> </ul> </div> </template> <script> export default { async asyncData({ params }) { const articles = await fetch('https://api.example.com/articles') .then(res => res.json()); return { articles }; } } </script>
配置路由和导航守卫:
- Nuxt会自动根据
pages/
目录下的.vue
文件生成路由。 - 可以在
nuxt.config.js
中配置路由的扩展属性,如中间件、别名等。 - 可以在页面组件中使用
middleware
属性或全局中间件来定义导航守卫。
- Nuxt会自动根据
- 在页面组件中,可以使用
- 使用Vuex进行状态管理:
- 在
store/
目录下创建Vuex模块,如index.js
。 - 在Vuex模块中定义状态、mutations、actions等。
- 在页面组件中通过
this.$store.state
或this.$store.getters
访问状态,通过this.$store.commit
或this.$store.dispatch
修改状态。
- 在
- 构建和部署:
- 使用
npm run build
命令构建生产环境的Nuxt应用。 - 将构建后的文件部署到服务器上,如使用Nginx或Apache等Web服务器。
- 使用
三、总结
通过上述步骤,我们成功安装并入门使用了Nuxt框架。Nuxt框架提供了许多内置的功能和配置,使得开发Vue SSR应用变得更加简单和高效。同时,Nuxt还支持丰富的插件和模块生态系统,可以根据项目需求进行扩展和定制。希望这个使用案例能够帮助你快速上手Nuxt框架的开发。