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文档](https://nuxt.com.cn/docs/getting-started/introduction) \[2\] \[3\] [Nuxt 3 学习笔记](https://ithelp.ithome.com.tw/users/20152617/ironman/5934)

相关推荐
黄毛火烧雪下22 分钟前
React Native (RN)项目在web、Android和IOS上运行
android·前端·react native
fruge28 分钟前
前端正则表达式实战合集:表单验证与字符串处理高频场景
前端·正则表达式
baozj32 分钟前
🚀 手动改 500 个文件?不存在的!我用 AST 撸了个 Vue 国际化神器
前端·javascript·vue.js
用户40993225021241 分钟前
为什么Vue 3的计算属性能解决模板臃肿、性能优化和双向同步三大痛点?
前端·ai编程·trae
海云前端142 分钟前
Vue首屏加速秘籍 组件按需加载真能省一半时间
前端
蛋仔聊测试43 分钟前
Playwright 中route 方法模拟测试数据(Mocking)详解
前端·python·测试
零号机1 小时前
使用TRAE 30分钟极速开发一款划词中英互译浏览器插件
前端·人工智能
疯狂踩坑人1 小时前
结合400行mini-react代码,图文解说React原理
前端·react.js·面试
Mintopia1 小时前
🚀 共绩算力:3分钟拥有自己的文生图AI服务-容器化部署 StableDiffusion1.5-WebUI 应用
前端·人工智能·aigc
街尾杂货店&1 小时前
CSS - transition 过渡属性及使用方法(示例代码)
前端·css