Nuxt3重构问题总结

一、项目安装

  • 1、检查node版本,建议使用Node.js - v18+

  • 2、使用nvm管理不同版本的node

  • 3、安装nvm - https://github.com/coreybutler/nvm-windows/releases

  • 4、安装指定版本的 node nvm install 18.19.0

  • 5、查看已安装 node nvm ls

  • 6、使用指定版本的 node nvm use 18.19.0

  • 7、创建新的nuxt3项目 npx nuxi@latest init nuxt-demo

  • 8、安装依赖 npm install

  • 9、启动服务 npm run dev

  • 10、配合element-plus、vuex、vue-router使用的完整依赖如下所示:

    json 复制代码
    {
      "name": "nuxt-demo",
      "private": true,
      "type": "module",
      "scripts": {
        "build": "nuxt build",
        "dev": "nuxt dev",
        "generate": "nuxt generate",
        "preview": "nuxt preview",
        "postinstall": "nuxt prepare"
      },
      "dependencies": {
        "@element-plus/icons-vue": "^2.0.10",
        "axios": "^0.21.1",
        "element-plus": "^2.2.27",
        "gsap": "^3.8.0",
        "prismjs": "^1.25.0",
        "vue": "3.2.45",
        "umob": "^0.2.5"
      },
      "devDependencies": {
        "@element-plus/nuxt": "^1.0.6",
        "@nuxt/devtools": "latest",
        "nuxt": "^3.8.0",
        "vite-plugin-prismjs": "^0.0.8",
        "vue": "^3.3.6",
        "vue-router": "^4.2.5",
        "vuex": "^4.0.2"
      }
    }

二、Vue-router使用的注意事项

  • 1、无需createRouter和路由配置,直接使用 import { useRoute } from 'vue-router'const route = useRoute() 即可
  • 2、store内部禁止使用 const route = useRoute(), 不会响应式更新,需放在setup内部。
  • 3、路由全局守卫, middleware 目录下创建 base.global.ts, 内容如下:
javascript 复制代码
export default defineNuxtRouteMiddleware((to, from) => {
	const { name: toName } = to
	const { name: fromName } = from
	console.log(toName, fromName)
})

三、数据获取

  • 1、本地请求代理配置,nuxt.config.ts中的vite部分配置如下所示:
javascript 复制代码
vite: {
    server: { // 本地请求服务器代理
        proxy: {
            '/api': {
                target: 'https://xxxx.com/api',
                changeOrigin: true,
            },
        },
    },
}
  • 2、服务器请求代理配置,nuxt.config.ts中的nitro部分配置如下所示:
javascript 复制代码
nitro: {
    routeRules: { // 服务器请求代理
        '/api/**': {
            proxy: 'https://xxxx.com/api/**',
        },
    },
}
  • 3、数据获取必须在setup内部调用(禁止在store内调用),useFetch会自动避免客户端重复发起请求,这是nuxt实现ssr的重要方式,具体请求如下:

    await Promise.all([
    useFetch('/a/b', {
    query: { id: '01' },
    method: 'get',
    }),
    useFetch('/a/c', {
    query: { id: '02' },
    method: 'get',
    })
    ])

请求完成之后的数据处理与正常请求一致。若出现 Hydration children mismatch in <div>: server rendered element contains more child nodes than client vdom 警告,这可能是初始化时存在某个判断条件,该条件在服务端渲染和客户端时存在不一样的表现,进而导致服务端水合结果与客户端不一致。如:localStorage的判断、onMounted内的数值初始化等

四、如何在head内注入js代码片段?

nuxt.config.ts中的app部分配置如下所示:

javascript 复制代码
head: {
    script: [{
        children: `window.addEventListener('load', function() {
            if ('serviceWorker' in navigator) {
                navigator.serviceWorker.register('/sw.js')
            }
        })`,
    }],
}

五、路由跳转短暂白屏处理

默认情况下,useFetch会在异步函数解析完成之前使用Vue的Suspense进行页面导航,而Suspense的#fallback默认为空,从而造成白屏现象

  • 1、使用 useLazyFetch 可以忽略此功能在客户端导航时的使用。在这种情况下,需要手动处理加载状态。首先,修改请求方法:
javascript 复制代码
const fetchHandle = async (id) => {
    const { data: response, pending } = await useLazyFetch('/a/b/getById', {
        query: { id },
        method: 'get',
        key: 'getById:' + id,
    })
    return {
        response,
        pending,
    }
}
  • 2、在composables目录下新建 index.ts
javascript 复制代码
export const useLazyFetchHandle = (data: any, res: any, key: string) => {
    const { response, pending } = data
    const { data: prevData } = useNuxtData(key)
    if (response.value) {
        // 服务端渲染的数据处理
        res.value = response.value.data
    }

    const isLoading = computed(() => { // 加载中
        if (prevData.value) {
            return !prevData.value.success && pending.value
        }
        return pending.value
    })
    
    watch(response, (newRes) => {
        // 监听路由跳转请求的数据处理
        res.value = newRes.data
    })

    return isLoading
}
  • 3、组件内部调用
javascript 复制代码
const result = ref({})
const isLoading = useLazyFetchHandle(
    await fetchHandle(id),
    result,
    'getById:' + id,
)

六、部署

  • 1、检查node版本, 若出现报错 [nuxt] [request error] [unhandled] [500] _fetch is not a function 则需升级node

可安装NVM升级node,参考链接 https://blog.csdn.net/xhp312098226/article/details/131247719

  • 2、Ubuntu 18.04 出现GLIBC_2.28 not found,则需升级Ubuntu系统版本
shell 复制代码
sudo apt update
sudo apt upgrade
sudo apt full-upgrade
sudo apt autoremove
sudo systemctl reboot
sudo apt install update-manager-core
sudo do-release-upgrade -m desktop -d

升级完成后,mysql也将会被升级至mysql 8,需要重新设置root用户密码和权限

  • 3、执行打包命令 npm run build,并生成 .output文件夹
  • 4、使用pm2管理node服务,PM2 是维持一个 Process 执行的管理器,們可以藉由 PM2 來啟動我們的 Nitro Server,当服务崩溃时能自动的重新启动,以维持服务的正常运作,除此之外 PM2 可以启用集群 (Cluster) 的功能结合请求的负载均衡,来让多核心的机器提升资源的利用率和效能

安装pm2 npm install -g pm2

  • 5、在 Nuxt 目录下放入.output文件夹,并创建 ecosystem.config.js 文件,內容如下:
javascript 复制代码
module.exports = {
    apps: [
        {
            name: 'nuxt-demo',
            exec_mode: 'cluster',
            instances: 'max',
            script: './.output/server/index.mjs',
            env: {
                PORT: 3000,
                HOST: '0.0.0.0',
            }
        }
    ]
}
  • 6、启动服务 pm2 start ecosystem.config.js
  • 7、配置nginx
nginx 复制代码
location / {
    proxy_pass http://127.0.0.1:3000/;
    proxy_set_header HOST $host;
}

七、静态资源404

经排除,问题为以下location导致

nginx 复制代码
location ~ .*.(ttf|woff|webp|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ {
    expires max;
    if_modified_since off;
    add_header Last-Modified "";
    etag off;
}

调整location匹配规则,过滤_nuxt路径下的静态资源

nginx 复制代码
location ~* ^(?!/(_nuxt|favicon))(.+).(ttf|woff|webp|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$ {
    expires max;
    if_modified_since off;
    add_header Last-Modified "";
    etag off;
}

References

[1] Nuxt3文档

[2] https://github.com/element-plus/element-plus-nuxt-starter

[3] Nuxt 3 学习笔记

相关推荐
qq_3901617727 分钟前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
知孤云出岫1 小时前
web 渗透学习指南——初学者防入狱篇
前端·网络安全·渗透·web
贩卖纯净水.1 小时前
Chrome调试工具(查看CSS属性)
前端·chrome
栈老师不回家2 小时前
Vue 计算属性和监听器
前端·javascript·vue.js