Nuxt3 全流程开发+配置+部署+定时任务

11,575 阅读15分钟

【 概述 】

为确保项目开发流程的完整性,作者将开发、配置、部署、服务、遇到的问题 都整理在了这一篇文章里,需要借鉴的同学可以通读一下,或者各取所需,有问题的地方欢迎评论交流!

一. 为什么要使用 Nuxt

  1. 首先我们想实现一个营销项目,需要较好的 SEO 能力,这样更便于公司、项目、产品的推广销售
  2. 介于当前前端技术趋势,更偏向于单页面应用 + 虚拟DOM,为的是开发效率和项目工程化(当然,单页面应用使用 webpack+prerender-spa-plugin 实现预渲染,也可以优化SEO,使项目增加百度曝光和多入口,但是效果肯定是比不上SSR的,想了解的可以看这篇早期文章 Vue项目的SEO优化方案
  3. 综上所述,最终选择使用nuxt(因为公司的技术栈主 vue,如果用的是 react,去看 next,这两个框架都是很优秀的框架,没有谁更好用,服务于不同基础库而已)

二. 版本的选择

  • nuxt@2

    这是比较早的版本,基于vue2,如果说vue2老项目迁移,可以看看这个版本

  • nuxt@3

    虽然@3这个版本是近期版本,但是已趋于稳定,他基于vue3开发,内置支持TSES6,使用它可以去尽情的写代码(这里选用的是@3.5.2版本)

    image.png

  • 由于作者尝试分别安装了这两个版本,所以先说下 nuxt@2

三. Nuxt@2 创建项目

  1. 安装命令 npx create-nuxt-app nuxt-v2
  2. 选择配置项(常规按照此选择,不同需求调整即可) image.png
  3. 解释:模版引擎的选择(Template engine

Nuxt.js 是一个基于 Vue.js 的 SSR (服务器端渲染) 框架,它允许开发者创建具有静态站点生成器功能的应用程序。Nuxt.js 使用了两个模板引擎:HTML 和 Pug。

  • HTML (.vue):

    HTML 是 Nuxt.js 默认使用的模板引擎。它允许你使用 Vue.js 的语法来编写 HTML 代码。这种方式的优点是可以充分利用 Vue.js 的特性,如组件化、数据绑定、指令等。然而,它的缺点是需要学习 Vue.js 的语法,对于不熟悉 Vue.js 的开发者来说可能会有一定的学习成本。

  • Pug (.nuxt):

    Pug 是一个基于 Jade 的模板引擎,它是 Vue.js 官方推荐的模板引擎。Pug 的语法简洁,易于阅读和编写。使用 Pug 编写的代码更接近于传统的 HTML 代码,对于熟悉 HTML 的开发者来说更容易上手。然而,Pug 的语法与 Vue.js 的语法有一定的差异,可能需要一定的学习成本。

  • 总结:

    • 如果你熟悉 Vue.js 的语法,并希望充分利用 Vue.js 的特性,那么 HTML 模板引擎可能更适合你。
    • 如果你希望编写更接近传统 HTML 的代码,并且对 Vue.js 的语法不太熟悉,那么 Pug 模板引擎可能更适合你。
  1. 解释:部署模式的选择(Deployment target

在使用 Nuxt.js 创建项目时,Deployment target 是一个重要的选项,用于指定项目的部署目标。这里有两个选项:serverstatic。它们之间的主要区别在于文件的访问方式和内容。

  • server

    Deployment target 设置为 server 时,Nuxt.js 会在本地服务器上运行项目。这意味着你可以在本地开发环境中访问项目的所有文件,包括静态文件(如 CSS、JavaScript 和图片)。当你在本地运行项目时,这些文件会被自动加载。

    当你将项目部署到服务器时,Nuxt.js 会自动将静态文件(如 CSS、JavaScript 和图片)打包到一个单独的文件夹中,以便在服务器上进行访问。这个文件夹通常位于 dist 目录下。

  • static

    Deployment target 设置为 static 时,Nuxt.js 会将项目的所有静态文件(如 CSS、JavaScript 和图片)打包到一个单独的文件夹中。这个文件夹通常位于 dist 目录下。

    当你将项目部署到服务器时,你需要将这个文件夹上传到服务器的指定位置。这意味着你需要手动处理静态文件的访问,而不是让 Nuxt.js 自动处理。

  • 总结:

    • server:在本地开发环境中,Nuxt.js 会自动加载静态文件。当你将项目部署到服务器时,Nuxt.js 会将静态文件打包到一个单独的文件夹中。
    • static:在本地开发环境中,Nuxt.js 不会自动加载静态文件。当你将项目部署到服务器时,你需要将静态文件上传到服务器的指定位置。
    • 根据你的需求和项目的部署方式,选择合适的 Deployment target 选项。如果你希望在本地开发环境中自动加载静态文件,并在部署时自动打包,请选择 server。如果你希望手动处理静态文件的访问,并在部署时将静态文件上传到服务器,请选择 static

四. Nuxt@3 创建项目

  1. Node版本的要求

NodeJS > 14.16.0

  1. 执行命令创建项目
npx nuxi init nuxt3-app

3. 上面的命令可能会报错,这里整理两种解决方案

  • 方案1:手动clone代码 git clone -b v3 github.com/nuxt/starte… 点击报错提示的url,打开里面tar路径,会自动下载,解压即可。

  • 方案2:为电脑添加hosts

    • www.ipaddress.com中查询 raw.githubusercontent.com 的真实IP

      image.png

    • 终端编辑hosts文件:sudo vi /ect/hosts 写入查询到的 ipv4 队列,然后 :wq 保存

      image.png

  1. 报错解决后,再次执行安装
  2. 安装完成后,会看到为我们创建了一个有配置但不多的目录,但已经够了,我们去下载依赖&启动服务
cnpm i

cnpm run dev

五. 配置代码检查

第一步:初始化 EsLint

  1. 项目目录下执行命令初始化一个.eslintrc.js
npx eslint --init

2. 按步骤选择

image.png

  1. 然后会报一个错,我们可以选择yes或者选no自己安装

image.png

  1. 这里手动安装缺少的依赖
cnpm i -D eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest eslint@latest

5. 在packahe.jsonscripts中添加

"lint": "eslint . --ext .ts,.vue"

6. 然后用命令测试eslint是否生效

npm run  lint

7. 虽然 nuxt3 默认支持了 typescript,但是用 eslint 还是提示Cannot find module ‘typescript’,所以需要再安装 typescript 依赖

cnpm i -D typescript

8. 再次执行 npm run lint 生效

image.png

第二步:针对 nuxt3 的配置

  1. 把配置文件中extends项下的"plugin:vue/essential"替换为"plugin:vue/vue3-recommended"(一个是vue2,一个是vue3的配置)
  2. 安装eslint-plugin-nuxt
cnpm i -D eslint-plugin-nuxt
  1. extends项中增加"plugin:nuxt/recommended",删除"eslint:recommended"(eslint默认校验)

  2. 删除plugins项下的"vue",同时可以选择性在rules项中增加"vue/multi-word-component-names": 0,nuxt中提倡vue文件和组件使用kebab-case(烤肉串式)风格命名,将该规则设为0关闭校验

第三步:配合 Prettier

  1. 安装依赖
cnpm i -D prettier eslint-plugin-prettier eslint-config-prettier
  1. 现在去尝试重新编辑一下代码然后 ctrl+s 保存发现已经会自动格式化了
  2. 设置 prettier 格式化规则,eslint 和 prettier 结合使用可以直接在 eslintrc 中配置prettier不需要单独再新建 .prettierrc.js 了,若提示报错不兼容,则需要单独创建 .prettierrc 文件

第四步:配置Git提交校验钩子

  1. 安装依赖
cnpm i husky lint-staged -D

2. 执行程序命令

npx husky-init && cnpm
npx husky add .husky/pre-commit 'npx lint-staged'

3. 检查 package 是否新增以下这些 scripts,没有的话手动加一下

  • "prepare": "husky install"
  • "lint-staged: {...}"
  • "lint": "eslint --ext .js,.ts,.vue --ignore-path .gitignore ."
  • "lint:fix": "eslint --fix --ext .js,.ts,.vue --ignore-path .gitignore ."
  1. 修改 "lint-staged"
  • "lint-staged": { "*.{js,jsx,vue,ts,tsx}":["yarn lint:fix"]}
  1. 到这 commit 前验证 eslint 就完成了,下面继续 commitlint
  2. 安装:
cnpm i -D @commitlint/cli @commitlint/config-conventional

7. 配置 package 文件:

"commitlint": {
    "extends":["@commitlint/config-conventional"]
}

8. 执行命令程序:

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

9. 配置完成

六. 配置 Sass 和 全局变量

  1. 安装依赖
npm install sass --save-dev
  1. 使用:<style lang="scss" scoped> 标签即可嵌套样式使用

  2. 导入外部文件使用:

<style lang="scss">
@import "~/assets/styles/common.scss";
body {
  background-color: $commonBgColor;
}
</style>

4. 全局配置使用(nuxt.config.ts

image.png

image.png

七. 开发流程参考

下面的内容为个人开发整理,仅供参考,如需更多内容,请查阅 Nuxt官方文档

  1. Nuxt@3 目录约定

框架本身存在一些规则,其目的一个是约束开发规范,另一个目的就是提升开发效率,在项目不复杂或没有特殊需求的情况下,不需要关注繁琐的配置,专心去写业务写页面就好了!

  • /app:可以在文件下增加配置,达到覆盖默认配置的目的
  • /assets:静态资源
  • /components:组件目录(在页面使用组件的时候,不需要引入,按照文件名调用即可)
  • /composables:Hooks目录,封装有状态的行为函数,供页面使用
  • /constants:用来声明常量
  • /env:用来承载环境文件
  • /layouts:布局目录,比如页头页脚内容等布局
  • /page: 目录下的文件在不配置的情况下会按照目录结构自动生成路由和页面,如果配置的话需要去覆盖app配置的route字段
  • /plugins:配置...
  • /public:需要打包输出到根目录的文件放这里
  • /server:服务端目录,接口等...
  • /utils:工具函数封装等...

image.png

  1. Nuxt 的几种渲染方式
  • CSR:客户端渲染(客户端请求接口,客户端拼接DOM,无源码不利于SEO)
  • SSR:服务端渲染(服务端请求接口,服务端拼接DOM,有源码利于SEO)
  • SSG:静态预渲染(客户端请求接口,提前静态生成HTML,有源码利于SEO,但不合适用在动态网站)
  • hybrid rendering:混合渲染
  • edge-side rendering:边缘渲染

结合上面几种方式看一下,只有 SSR 和 SSG 能接着往下说了,这里主要区分下这两种

  • SSR:使用命令nuxt build打包生成.output,在服务器上用PM2启动服务,动态为网站输出拼接好的页面,去做SEO

image.png

  • SSG:使用命令nuxt generate打包实现HTML文件生成,达到静态源码的目的,看下图输出目录的结构即可

image.png

  1. ENV 环境配置
  • 新建两个文件

    image.png

  • 变量内容如下

    image.png

  • 配置 Vite nuxt.config.ts

import { loadEnv } from 'vite'

interface VITE_ENV_CONFIG {
  VITE_PACK_ENV: string
  VITE_API_HOST: string
  VITE_API_PREFFIX: string
}

const envScript = (process.env as any).npm_lifecycle_script.split(' ')
const envName = envScript[envScript.length - 1]
const envData = loadEnv(envName, 'env') as unknown as VITE_ENV_CONFIG

export default defineNuxtConfig({
  runtimeConfig: {
    public: envData
  },
  vite: {
    envDir: '~/env'
  }
})
  • 封装Hook /composables/useApiBaseUrl.ts,用来页面调用获取 BaseUrl(必须用hook形式,因为useRuntimeConfig只能在 setup 中调用)
/**
 * @function useApiBaseUrl
 * @desc 根据不同环境抛出当前API请求地址
 */
export default () => {
  const runtimeConfig = useRuntimeConfig()
  const runtimeConfigPublic = runtimeConfig.public
  const baseUrl = runtimeConfigPublic.VITE_API_HOST + runtimeConfigPublic.VITE_API_PREFFIX
  return {
    baseUrl
  }
}
  • 修改package.json指令, mode 对应上 /env目录下的文件名(这样的话,打包就可以把环境变量打进去)

image.png

  1. 设置 Head 标签的 3 种方式
  • nuxt.config.ts 文件:这里设置不变的标签,并且需要在源码中展示的内容

image.png

  • <Head> 内置标签设置

image.png

  • useHead 接口设置

image.png

八. 部署流程参考

阿里云安装 node 和 npm 环境

!!!如果已经安装,忽略这步就好了

  1. 下载 Linux 版本 NodeJS
wget https://npm.taobao.org/mirrors/node/v14.19.1/node-v14.19.1-linux-x64.tar.xz
// 或者
wget https://nodejs.org/dist/v14.19.1/node-v14.19.1-linux-x64.tar.xz

2. 解压

tar -xvf node-v14.19.1-linux-x64.tar.xz

3. 移动文件夹

mv node-v14.19.1-linux-x64/ /usr/local/node

4. 设置环境变量

echo "export PATH=$PATH:/usr/local/node/bin" >> /etc/profile

5. 重启让配置生效

source /etc/profile

6. 测试输出node版本号

node -v
npm -v

7. 安装cnpm(没权限的话用sudo)
npm install -g cnpm --registry=registry.npm.taobao.org

Jenkins 部署 + Node 服务

  1. 全局安装pm2,用来启动和管理服务(如果已安装,请忽略)
  • sudo cnpm i pm2 -g
  • pm2 -v
  1. 查看当前 Node 版本是否符合要求,不行的话使用n模块去切换掉
  2. Nginx配置网站的域名和80、443端口配置,然后将指向127.0.0.1的3336,这个3336也就是我们要在这个服务器起的 Node 服务端口
  3. 配置 Jenkins 部署流程,新增任务,实现打包递交.output 到服务器网站目录
  4. 在服务器的.output目录同级创建一个当前项目的 pm2 管理文件 ecosystem.config.js,内容参考结尾配置,这个文件就是管理我们要起的这个服务的
  5. 查看当前服务队列(加上 sudo ,要不然看不到 @root 起的服务)

image.png

  1. 启动当前项目的 Node 服务

image.png

  1. 查看端口占用情况(id和列表对应,服务来自于 node,是没问题的)

image.png

Jenkins 部署后自动重启服务

Jenkins交付代码完成后执行启动服务命令(这个流程比较正向,就不需要每次上线,再去手动start服务了)

image.png

九. 定时任务的编写和部署

说明

这一小节是根据研发进度后来补充的,资料不太好找,所以整理出来供大家参考(2023.06.14)

需求概述

项目的 SEO 需要配合 sitemap.txt 文件做映射检索

实现目标

  1. 需要在访问项目地址https://*.*/sitemap.txt的时候拿到映射文件
  2. 需要在服务器端有一个定时任务,每天00:05:00去更新文件的内容

实现流程

  1. 写一个接口文件 /server/api/task.ts

文件内容配合注释我直接写到下面

核心就是node-schedule的定时能力和fs的读写文件能力

这里要注意在服务端运行的读写权限问题,一般运行服务的用户有权限就行

/**
 * @file 定时任务
 * @desc 每天 00:05:00 请求数据 + 执行生成文件
 */

import * as schedule from 'node-schedule'
import * as fs from 'fs'
import useBaseEnv from '../../composables/useBaseEnv'
import { ListItem } from '../../pages/sitemap/index.vue'

const { baseUrl, baseEnv } = useBaseEnv()

// 获取公司列表
const getDataList = async () => {
  const result: any = await $fetch('productList', {
    method: 'GET',
    baseURL: baseUrl
  })
  // 序列化返回值
  const parseRes = JSON.parse(result)
  if (parseRes && parseRes.status === 0 && parseRes?.data?.list?.length) {
    // 拼接文件内容
    const content: string = (parseRes.data.list).reduce((total: any, item: ListItem) => {
      const siteUrl = 'https://s.qimingpian.com/detail?ticket='
      if (total.uuid) {
        return `${siteUrl}${total.uuid}\n${siteUrl}${item.uuid}`
      } else {
        return `${total}\n${siteUrl}${item.uuid}`
      }
    })
    // 声明写入路径
    const writePath = './.output/public/sitemap.txt'
    // 开始写入内容
    fs.writeFile(writePath, content, err => {
      if (err) {
        console.error('Error creating file:', err)
        return
      }
      console.log('File created successfully!')
    })
    // 打开文件
    // const fd = fs.openSync('./public/sitemap.txt', 'w')
    // 写入内容
    // fs.writeSync(fd, content)
    // 关闭文件
    // fs.closeSync(fd)
  }
}

const TaskServer = () => {
  // 非本地环境 才执行定时任务
  if (baseEnv !== 'dev') {
    // 先执行一次 确保文件存在并且可以访问到
    getDataList()

    // 定义规则
    // const rule = new schedule.RecurrenceRule()
    // rule.second = [0, 20, 40] // 每分钟的*秒执行

    // 定义规则
    // 执行时机 每天的凌晨00点5分00秒触发 :'30 1 1 * * *'
    const Rule = '0 5 0 * * *'

    // 启动任务
    const scheduleTask = schedule.scheduleJob(Rule, () => {
      getDataList()
    })
  }
}

// 这里手动调用定时任务(启动服务的时候调用一次即可)
TaskServer()

export default TaskServer
  1. 修改服务器端Node管理文件ecosystem.config.js

你会发现,我在之前文件的基础上,又增加了一个任务,现在就是让一个文件管理两个任务,只不过是执行的目录不一样,

定时任务与常规接口不同

  • 常规接口:会跟随 Nuxt主服务运行,并且需要使用defineEventHandler方法包装函数抛出,页面可以直接useFetch调用接口
  • 定时任务:同为服务端运行文件,但是其需要并且最好是单独运行新的服务,其实本来就是独立的两块内容,也不必混在一起。

image.png

  1. 修改 Nginx 配置

这一步的目的是:因为我们项目中的首页路由是sitemap,这就会影响到文件访问结果,导致 404,所以决定 Ng 直接拦一下,注意写在 location /这一项之前

image.png

  1. 修改 Jenkins 任务

由于现在有两个服务在运行,所以交付的最后一步需要重启两个服务

注意:

修改Jenkins之前先打一个包,把/server/chunks/task.mjs送上服务器,并手动启动ecosystem文件的两个服务;然后再配置 Jenkins 命令,重新打一个包,看看 pm2 的面板 任务有没有被更新

image.png

  1. 验证结果

image.png

  1. 次日查看定时任务是否稳定

这里可以看到,如我们所写,每天00:05:00文件写入数据,并且服务良好,还可以再查看logs/app-err.log没有服务报错就可以了

image.png

十. PM2服务管理文件配置项参考

// ecosystem.config.js

module.exports = {

  // apps是一个json结构的数组 ,每一个数组成员对应一个pm2中运行的应用

  apps: [

    {

      // 应用程序名称

      name: 'qmp_promotion_ssr',

      // 执行文件

      script: './.output/server/index.mjs',

      // 应用程序所在的目录

      // cwd: './',

      // 传递给脚本的参数

      // args: '',

      // 指定的脚本解释器

      // interpreter: '',

      // 传递给解释器的参数

      // interpreter_args: '',

      // 是否启用监控模式,默认是false。如果设置成true,当应用程序变动时,pm2会自动重载。这里也可以设置你要监控的文件。

      watch: true, // watch: './',

      // 不用监听的文件

      ignore_watch: ['node_modules', 'logs'],

      // 应用程序启动模式,默认是fork,或设置的是 cluster_mode(集群)

      exec_mode: 'fork',

      // 应用启动实例个数,仅在cluster模式有效 默认为fork;或者 max

      instances: 1,

      // 最大内存限制数,超出自动重启

      max_memory_restart: '1G',

      // 自定义应用程序的错误日志文件(错误日志文件)

      error_file: './logs/app-err.log',

      // 自定义应用程序日志文件(正常日志文件)

      // out_file: './logs/app-out.log',

      // 设置追加日志而不是新建日志

      merge_logs: true,

      // 指定日志文件的时间格式

      log_date_format: 'YYYY-MM-DD HH:mm:ss',

      // 最小运行时间,这里设置的是60s即如果应用程序在* 60s内退出,pm2会认为程序异常退出,此时触发重启 max_restarts设置数量,应用运行少于时间被认为是异常启动

      min_uptime: '60s',

      // 设置应用程序异常退出重启的次数,默认15次(从0开始计数),最大异常重启次数,即小于min_uptime运行时间重启次数;

      max_restarts: 10,

      // 启用/禁用应用程序崩溃或退出时自动重启,默认为true, 发生异常的情况下自动重启

      autorestart: true,

      // 定时启动,解决重启能解决的问题,crontab时间格式重启应用,目前只支持cluster模式;

      // cron_restart: '',

      // 异常重启情况下,延时重启时间

      restart_delay: 60,

      // 服务的端口

      port: '3336

      // 环境配置

      // env: {

      //   // 公共变量

      //   COMMON_VARIABLE: true

      // },

      // 生产环境配置

      // $ pm2 start app.js --env

      // env: {

        // 环境参数,当前指定为生产环境 process.env.NODE_ENV

        // NODE_ENV: 'production',

        // 当前环境接口地址,如果不用可不配置 process.env.REMOTE_ADDR

        // REMOTE_ADDR: 'http://www.abc.com/'

      // },

      // 开发环境配置

      // $ pm2 start app.js --env_dev

      // env_dev: {

        // 环境参数,当前指定为开发环境 process.env.NODE_ENV

        // NODE_ENV: 'development',

        // 当前环境接口地址,如果不用可不配置 process.env.REMOTE_ADDR

        // REMOTE_ADDR: 'http://www.abc.com/'

      // },

      // 测试环境配置

      // $ pm2 start app.js --env_test

      // env_test: {

        // 环境参数,当前指定为测试环境 process.env.NODE_ENV

        // NODE_ENV: 'test',

        // 当前环境接口地址,如果不用可不配置 process.env.REMOTE_ADDR

        // REMOTE_ADDR: 'http://www.abc.com/'

      // }

    }

  ]

  


  // 环境部署

  // deploy: {

    // 生成环境

    // 1、上传代码到云端仓库

    // 2、部署命令预览:

    // 首次部署: $ pm2 deploy ecosystem.json production setup

    // 更新版本: $ pm2 deploy ecosystem.json production update

    // 返回上一个版本: $ pm2 deploy ecosystem.json production revert 1

    // 3、执行首次部署:$ pm2 deploy ecosystem.json production setup

    // 4、执行部署运行:$ pm2 deploy ecosystem.json production

    // 5、看到 success 成功,报错看错误自行百度

    // production: {

      // ssh的用户名,登录远程服务器的用户名

      // user: 'snow',

      // 要发布的机器,远程服务器的IP或hostname,此处可以是数组同步部署多个服务器

      // host: '10.0.0.0',

      // 服务器端口

      // port: 3000,

      // 要发布的代码分支,远端名称及分支名

      // ref: 'origin/master',

      // 代码Git仓库地址

      // repo: 'git@gitlab.dzm.net:dzm/nuxt-test',

      // 服务器存储代码地址,远程服务器部署目录,需要填写user具备写入权限的目录,也就是服务器存放上面git库代码的地方

      // path: '/usr/local/var/www/production',

      // ssh权限配置

      // 'ssh_options': 'StrictHostKeyChecking=no',

      // ssh_options: ['StrictHostKeyChecking=no', 'PasswordAuthentication=no'],

      // 1、在 setup 前触发,如安装 git

      // 'pre-setup': '',

      // 2、在 setup 后触发,如做一些其他配置

      // 'post-setup': '',

      // 3、在 deploy 前触发,执行本地脚本

      // 'pre-deploy-local': '',

      // 4、在 deploy 前触发,执行远程脚本

      // 'pre-deploy': 'git fetch --all',

      // 5、在 deploy 后触发,执行远程脚本,如 npm install,部署后需要执行的命令

      // 'post-deploy' : 'npm install && pm2 startOrRestart ecosystem.config.js --env production',

      // 'post-deploy': 'npm install && pm2 reload ecosystem.config.js --env production',

      // 环境变量

      // env: {

        // 指定为生成环境

        // NODE_ENV: 'production'

      // }

    // }

  // }

}

十一. PM2 指令参考

  • 解释 pm2 启动模式 fork 和 cluster 的区别

    • fork模式
    1. 单实例多进程,常用于多语言混编,比如php、python等,不支持端口复用,需要自己做应用的端口分配和负载均衡的子进程业务代码。

    2. 缺点就是单服务器实例容易由于异常会导致服务器实例崩溃。

    • cluster模式
    1. 多实例多进程,但是只支持node,端口可以复用,不需要额外的端口配置,0代码实现负载均衡。

    2. 优点就是由于多实例机制,可以保证服务器的容错性,就算出现异常也不会使多个服务器实例同时崩溃。

    • 共同点

    由于都是多进程,都需要消息机制或数据持久化来实现数据共享

  • 启动服务(这里操作进程,需要 sudo 权限)

pm2 start ./ecosystem.config.js // 运行当前目录下的配置文件服务
pm2 start my_node_server // 运行服务列表中名称为 my_node_server 的服务
pm2 start 3 // 运行服务列表中id为 3 的服务
  • 查看服务列表(如果想要查看更高权限的服务,加上 sudo 运行)
pm2 list
  • 重启服务
pm2 restart ${serverId}
pm2 restart ${serverName}
pm2 restart ${serverConfigFile}
  • 停止服务
pm2 stop ${server}
  • 当文件变化时自动重启应用(想要停止监听,只需要先stop,再start即可)
pm2 stop ${server} --watch
  • 启动应用程序并命名为 "qmp_promotion_ssr"
pm2 start ecosystem.config.js --name="qmp_promotion_ssr"
  • cluster mode 模式启动4个当前的应用实例。4个应用程序会自动进行负载均衡
pm2 start ecosystem.config.js -i 4
  • cluster mode 模式:当前电脑有几核就启动几个示例
pm2 start ecosystem.config.js -i 0
  • 把名字叫 qmp_promotion_ssr 的应用扩展到3个实例,注意要加单引号 注意:如果扩展前是fork模式,那么扩展后的所有也是fork模式,不会变成cluster模式
pm2 scale 'qmp_promotion_ssr' 3
  • 显示某个应用程序的所有信息
// 以任务名称进行查看
pm2 show qmp_promotion_ssr
// 以任务ID进行查看
pm2 show 0
  • 显示每个应用程序的CPU和内存占用情况,按键盘上下键切换
pm2 monit
  • 显示所有应用程序的日志
pm2 logs
  • 显示指定应用程序的日志
// 以任务名称进行查看
pm2 logs qmp_promotion_ssr
// 以任务ID进行查看
pm2 logs 0
  • 清空logs
pm2 flush
  • 保存当前应用列表
pm2 save
  • pm2搭建静态文件服务器 (相对绝对路径都可以)
pm2 serve [path] [port]

十二. Linux 操作参考

  • 查看程序包的位置 (配置环境变量、调整环境变量、修改sudoers权限环境变量 的时候会用到)

    • which node
    • which npm
    • which pm2

    image.png

  • 查看环境变量

    • sudo echo $PATH
  • sudoers 配置文件的位置

    • /etc/sudoers
  • 查看可以使用 @root 的用户

    • cat /etc/sudoers

    image.png

  • 当前用户切入到 @root 用户

    • sudo -i
  • sudo 命令找不到,无法运行程序的解决

    • 原因:sudo权限的环境变量没有添加当前运行程序的环境
    • 文件:/etc/sudoers
    • 解决:下图位置增加环境变量(这一步需要管理员设置读写) image.png
  • 如果需要在执行sudo命令的时候避免输入密码,修改/etc/sudoers,添加用户的NOPASSWD:

    image.png

  • 查看 nginx 位置(阿里云ng一般处于:/alidata/server/nginx/conf/vhosts

    • nginx -t
  • 编辑环境变量文件

    • vim /etc/profile
  • 重启环境变量文件

    • source /etc/profile
  • 查看服务器端口占用情况(想看全量的视图,加 sudo 调用)

    • netstat -tunlp
  • 修改NG后需要重启(找到NG程序的位置调用就可以)

    • cd /alidata/server/nginx/sbin
    • sudo ./nginx -s reload

Nuxt如何实现路由访问html指向页面

  1. 配置 agency 为动态路由:/app/router.options.ts
/**
 * 路由配置 (覆盖默认的Pages目录生成)
 */
export default {
  routes: () => {
    return [
      {
        path: '/',
        name: 'sitemap',
        redirect: '/sitemap'
      },
      {
        path: '/sitemap', // 首页
        component: () => import ('~/pages/sitemap/index.vue')
      },
      {
        path: '/company',
        component: () => import ('~/pages/company/index.vue')
      },
      {
        path: '/agency/:id',
        component: () => import ('~/pages/agency/index.vue')
      }
    ]
  }
}
  1. 触发页面跳转的地方 & sitemap文件地址中 写成 /agency/xxxxxx.html
  2. 然后在 agency 页面中拿到 params 参数把 .html 截取掉就可以了

如何查看网站收录情况

  1. 百度统计后台查看( PV / UV / 索引量... )

  2. 百度或谷歌输入框查询( 对应自己网站的域名 ):site:a.b.c

    image.png

    image.png

  3. 查看访问日志看看“”来过

什么是robots文件

请注意,仅当您的网站包含不希望被搜索引擎收录的内容时,才需要使用robots.txt文件。如果您希望搜索引擎收录网站上所有内容,请勿建立robots.txt文件

如何查看访问日志

  1. 各大搜索引擎蜘蛛名称

    • 百度蜘蛛:Baiduspider
    • 谷歌蜘蛛:Googlebot
  2. 找到当前网站的 Nginx配置文件

    • 阿里一般在(xxx对应网站域名):/alidata/server/nginx/conf/vhosts/xxx.conf
  3. cat 命令查看配置,找到 access_log 指向的日志位置,然后进入目录查看指定日期的日志

    image.png

  4. cat ./https.2023-07-05.log 就可以看到百度蜘蛛、谷歌蜘蛛 或者某个ip的访问记录(IP、时间、环境、页面...)

    image.png

    image.png

相关资料参考

  1. 百度Sitemap协议
  2. 百度工具使用手册

END. 遇到的问题和如何解决

  1. pm2 版本冲突的问题
  • 原因:原本服务器是有 pm2 的,结果又安装了一遍,默认拉取了@latest版本
  • 描述:原有@5.2.0,新安装的@5.3.0替换了 local 的版本,所以之前用@5.2.0启动的服务使用的是内存中的版本,并且检测到了版本被替换,所以报冲突

image.png

  • 解决:下载还原版本,并且 kill 清掉现有使用 @5.3.0 版本的服务进程,然后重新启动
sudo cnpm i -g pm2@5.2
  1. 安装 node npm pm2 后,sudo指令进行拼接调用的时候报错:sudo 命令找不到 的问题
  • 原因:sudoers 没有加入新程序的环境
  • 解决:(这一步需要管理员的读写权限)
    • which node 找到 node的上层目录 比如:/use/local/bin
    • /etc/sudoers 文件的 secure\_path= 这一行加上: /use/local/bin
  1. 接入百度统计无数据问题
    1. Nuxt 没有html入口,配置文件的app项其实就是入口,
    • A 的位置加上百度统计的JS全局变量等代码(此代码标注在客户端运行)
    • B 的位置目的是在源码的head中加入script标签并发起百度统计GET请求(此操作是在服务端进行HTML拼接,然后在客户端渲染并请求),这一步的hm请求如果写到 A 的位置源码就没有这个script标签了,如果 Amode 选择 server ,会报错,因为服务端拿不到 windowdocument 对象,无法执行 baidu.js 的插入节点操作

image.png

    1. referer=no-referrer ,这种情况hm的GET请求请求头没有referer字段,影响百度统计判定

image.png