Nuxt.js Vue 服务端渲染SSR入门

编程教程 > WEB (4) 2025-10-16 12:12:57

效果展示

nuxt-demo2

说明:

  • 首页页面 - 名字“张三”是Java后端接口数据
  • 产品介绍页面 - 产品介绍UL列表是动态数据

观察开发工具

Nuxt.js Vue 服务端渲染SSR入门_图示-0dadb10c9bf74731bcd1d4a5edd372ee.png

可以看到首页的用户名是在HTML里面的,说明是服务端渲染

观察上面动图:同一个浏览器窗口内部跳转

可以发现,只请求了一个doc,其他页面都是没有请求doc的,为啥呢?这是nuxt的另一个机制,对seo蜘蛛友好的同时对用户也友好(速度比常规网站快)。

环境说明

  • Nuxt.js 4.1.2
  • 使用nuxt.js pages 模式
  • node 20
  • pnpm

项目创建

下载Nuxt官方starter项目,选中版本4.x即可 GitHub - nuxt/starter at v4

默认项目结构

Nuxt.js Vue 服务端渲染SSR入门_图示-d6f6759068d84df2b27990a443aed764.png

 

Nuxtjs 项目编写

 

项目完整结构

Nuxt.js Vue 服务端渲染SSR入门_图示-71308162935b439bbeddcff8595cab34.png

提示:重点文件已经使用红色框住

 

项目配置 /nuxt.config.ts 

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  compatibilityDate: '2025-07-15',
  devtools: { enabled: true },
  //启用服务器端渲染
  ssr:true,
  //启用pages模式
  pages: true,
  runtimeConfig: {
    // 公共变量,客户端和服务端都可用
    public: {

    },
    // runtimeConfig下,非[runtimeConfig.public]子节点变量均为私有变量,客户端不可用
    apiKey: process.env.NUXT_API_KEY||'123456',
    //process.env.NUXT_API_BASE_URL表示优先读取环境变量NUXT_API_BASE_URL,没有则使用默认值https://api.example.com
    apiBaseURL: process.env.NUXT_API_BASE_URL || 'http://localhost:8080',
  },
  // 修改开发服务器端口
  devServer: {
    host: '0.0.0.0',  // 可选 0.0.0.0 | 标识所有都可以访问
    port: 3000        // 修改端口
  },
  //组件 禁用自动装配
  // components: [
  //   {
  //     path: '~/components',
  //     pathPrefix: false,
  //   },
  // ],
  //自定义打包输出目录,默认.output 修改为output
  nitro: {
    output: {
      dir: './output'
    }
  },

})

 

私有服务代理

私有服务代理,解决web前端直接访问Java服务端(或其他后端)由Nuxt代理访问,增加安全性。

/server/api/[...path].ts

为啥是/server这个目录,请参考nuxtjs4官方文档:server · Nuxt Directory Structure v4

Nuxt.js Vue 服务端渲染SSR入门_图示-ababb5755802488cb9554cc06838070b.png

其他目录定义也可以在这里找到

 

VIP资源,登录后查阅

此处内容需要开通会员后查阅(刷新)

登录/注册

 

页面及导航组件

/app/components/webNav.vue

<script setup lang="ts">

</script>

<template>
  <nav>
    <NuxtLink to="/">
      首页
    </NuxtLink>
    <span style="margin: 0 10px">|</span>
    <NuxtLink to="/product/list">
      产品介绍
    </NuxtLink>
    <span style="margin: 0 10px">|</span>
    <NuxtLink to="/about.html">
      关于我们
    </NuxtLink>
  </nav>
</template>

<style scoped>

</style>

/app/app.vue

<template>
 <div>
   <NuxtPage />
 </div>
</template>

/app/error.vue

<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps({
  error: Object as () => NuxtError
})
</script>

<template>
  <div>
    <h1>错误码:{{ error.statusCode }}</h1>
    <NuxtLink to="/">返回首页</NuxtLink>
  </div>
</template>

/app/pages/index.vue

<template>
  <h1>首页</h1>
  <web-nav/>
  <article>
    <h2>你好[{{userName}}],欢迎来到首页</h2>
  </article>
</template>

<script setup lang="ts">
import webNav from '~/components/webNav.vue';

const {data:userName} = await useAsyncData('user-name',async ()=>{
  try {
    const {data} = await $fetch('/api/nuxt/getName',{
      method:'POST',
    })
    console.log('获取用户名成功:',data)
    return data;
  }catch (err){
    console.error('Failed to load userName:', err)
    return '--'
  }
})

</script>

 

/app/pages/about.vue

<script setup lang="ts">

import WebNav from "../components/webNav.vue";
</script>

<template>
  <h1>关于我们</h1>
  <web-nav/>
  <article>
    <h2>欢迎来到关于我们页面</h2>
  </article>

</template>

<style scoped>

</style>

 

/app/pages/product/list.vue

<template>
  <h1>产品介绍</h1>
  <web-nav/>
  <article>
    <h2>欢迎来到产品介绍</h2>
    <p>
      这里是产品介绍页面
    </p>
    <ul >
      <li v-for="item in products">{{ item }}</li>
    </ul>
  </article>
</template>

<script setup lang="ts">
import WebNav from "../../components/webNav.vue";

const {data:products} = await useAsyncData('products',async ()=>{
  try {
    const {data} = await $fetch('/api/nuxt/product/list',{
      method:'POST',
    })
    console.log('获取产品成功:',data)
    return data;
  }catch (err){
    console.error('Failed to load products:', err)
    return []
  }
})

</script>

项目启动和构建

启动项目

在项目根目录打开终端或打开终端切换到项目根目录

安装依赖

pnpm install 

启动项目

pnpm dev

构建项目

pnpm build

其他工具可参考项目的REAMD.MD文档

 

项目部署

docker 方案

docker-compose.yml配置

version: "3.8"

networks:
  nuxtRouter:

services:
  nuxt-web:
    image: node:20.19.5-alpine
    container_name: nuxt-web
    hostname: nuxt-web
    restart: always
#    ports:
#      - 3080:3080
    networks:
      - nuxtRouter
    volumes:
      - ./output:/app/output
    working_dir: /app
    command: ["node","output/server/index.mjs"]
    environment:
      - NITRO_PORT=3000
    deploy:
      resources:
        limits:
          memory: 512M
    healthcheck:
      test: ["CMD","curl","-f","http://127.0.0.1:3080"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 30s

 

  • 将打包好的output文件夹映射到容器的/app/output 目录
  • working_dir 设置为/app
  • 容器执行启动命令 ["node","output/server/index.mjs"] 特别注意路径

启动

docker-compose up -d

查看日志

docker-compose logs -f 

重启

docker-compose restart

停止

docker-compose down

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
效果展示说明:首页页面 - 名字“张三”是Java后端接口数据产品介绍页面 - 产品介绍UL列表是动态数据观察开发工具可以看到首页的用户名是在HTML里面的,说
前言有时候,我们需要对js的原生对象进行扩展,达到全局使用更方便的效果
在初始化的Vue项目中,我们最先接触到的就是main.js,App.vue,index.html这三个文件,从下面创建的一个空白项目中可以看到:​关于三个文件的说明如下:index.html---主页
vue
vue打包会把vue相关的组件打包到一个文件vendor.*.js(*是个随机数)步骤一 资源引入vue最外层index.html文件引入资源文&lt;body&gtl;     &lt;di...
1.vue项目中创建global.js创建global.js放于main.js同级目录(可自己随意放)export default {   getToken()   {     retur...
vue-router 中 routers 定义写法,讨论 require 的使用与否​首先上 routerindex.jsimport Vue from 'vue'import Router f...
步骤:1、配置文件webpack.config.js:  {     test:/\.css$/,     loader:'style-loader!css-loader'  ...
前言Vue3 + Vite 打包静态资源使用相对路径 默认配置打包后文件预览相对路径绝对路径 Vue3 静态资源相对路径打包配置方法: 在defineConfi
一、函数式写法在vue2中,computed 写法:computed:{ sum(){ return this.num1+ this.num2 }} vue 3
在初始化完一个vue项目(基于vue-cli 和webpack)之后,我们可以通过 npm run dev来让这个项目跑起来
Vue v-if判断数组长度 searchResultDataList为vue定义的data里面的变量&lt;li  v-if="Object.keys(searchResultDataLis...
vue watch监控对象属性变化watch:{ 'object.attr':function attr(value){ //处理操作 } ...
普通写法​vantUI 使用字体图标和文字&lt;template&gtl; &lt;van-tabbar v-model="active" active-color="#07c160"&gtl...
Vue 如何返回上一页(上一个锚点)//...省略 methods:{ goback:function(){ this.$router.go(-1);//...
vue
一、前言Vue 2.x 使用期间,我们会创建众多组件,这里我们将讨论一下各个组件直接的相互通讯问题如何解决