nuxt2升级nuxt3

发布时间 2023-05-30 22:31:16作者: 庞永胜

记录升级nuxt3.0过程及问题


为什么要升级 ?

  • leader要求的=_=

升级后有什么好处和问题

好处从直观来看有:

  • build出来的文件更小了?
  • 本地开发启动更快了??‍♀️
  • 使用vue3的语法,代码更清晰?
  • 拆分了server层,功能更清晰?
  • 不在集成vuex,可以使用pinia?
  • 支持vue3 ts跟上大家的节奏?
  • 大家都说好?

缺点嘛,由于升级时候正式版发布不长时间

  • 好多东西文档也没有明确方案(目前看正在完善中),具体后面说
  • 好多模块还得查询它用的相关包的文档

怎么升

直接 npx nuxi upgrade , so easy? 当然不是?

正确的做法是,新建个项目,然后做一个代码的搬运工 ?

当然官网也有介绍些什么2.0体验3.0的feature啥的,不过都不是真正的升级,2和3基本是重写了
,所以还是要完全迁移的。

就个人而言,升级主要由以下几部分工作量

  • 首先当然是vue2的代码改写vue3,这块也是工作量最大的部分,不过好在基本是复制粘贴;
  • 配置相关的修改
  • 数据请求相关的修改(3.0整合了server,这块变动也比较大)
  • vuex迁移到pinia

官网也给出迁移的介绍,参考https://nuxt.com/docs/migration/configuration


下面开始具体介绍迁移的细节点

假设你已经新建好了3.0的项目

Configuration

配置这一块内容比较多,些说单纯的配置变化

1、根目录修改

3.0比之前的文件目录更多了,首先建议新建src目录,然后配置srcDir: 'src/'重设根目录

2、文件导入导出

之前module.exports的写法改成了export default,同理你要在配置中引入其他文件要使用import

3、公共的head配置

之前的head配置,要放到app: {head:{}}

4、publicRuntimeConfig、privateRuntimeConfig 改为了runtimeConfig

5、代理相关

之前2.0我们用的@nuxtjs/proxy做代理,3.0可以直接使用nitro配置

nitro: { 
    devProxy: { 
        '/api/': { 
            target: BASIC_URL,
            changeOrigin: true
        }
    } 
}

不过注意不同于@nuxtjs/proxy,如代码所示devProxy,只适用于开发模式,build后是没有代理的

布局(layouts)

布局变化主要是使用语法的变化:如配置使用的布局

<script setup>
definePageMeta({
    layout: "customLayout",
});
</script>

页面和组件(page & components)

这部分约定式路由和约定式组件名称这部分规则没有变化,将组件直接改为vue3的语法即可;

静态资源(assets and public)

  • assets可放置一些style,img,font、svg等资源;
  • public 中的文件会直接在服务器根目录下提供(打包不进行任何处理),主要用于放置类似favicon.ico、robots.txt之类静态的文件;

这块基本把原来的目录迁移过来就行,注意引用方法;

例如2.0中js代码中图片的的引用,require('assets/img/x.png)直接改为 import x from 'assets/img/x.png)即可使用;

中间件(Middleware)

nuxt3.0拆分了client和server,这里的Middleware是client层的,server层的中间件在server目录下介绍,后面的目录同理

Middleware的主要作用就行关于请求路由的基本处理,想拼接过滤参数、重定向之类的功能

获取设备信息重定向路由

获取设备需要安装@nuxtjs/device包,然后在nuxtconfig中配置

modules: [
   '@nuxtjs/device'
]

最后在中间件中使用,note:非重定向非同源地址需配置 { external: true }

const { isMobile, isWindows, isMacOs, ... } = useDevice();
export default defineNuxtRouteMiddleware((to, from) => {
    if(isWindows){
        navigateTo('/win')
    }
    if(isMacOs){
        navigateTo('/mac')
    }
})

使用中间件时 ,直接在对应的页面组件中加入定义代码即可

<script setup>

definePageMeta({

    middleware: ["device"]

    // or middleware: 'device'

})

</script>

混入 (compostables)

这个目录是3.0新增的,该目录下的方法会自动导入项目中,无需引入,可在页面组件、布局组件、插件、中间件中直接使用;

这里我们可以把之前写的一些公共方法迁入进去,或者一些全局保存的状态信息也可以迁入进去,由于我们项目使用了store所以这里只迁移了一些公共方法

例如:composable目录新建文件timeTrans.ts:

type TimeT = (time:Number , format:string ) => string;
export const timeTrans:TimeT = (time, format)=>{
  //...
  
  return "xx: xx"
}

在组件中可直接使用:

const t = timeTrans(10202, "xx:xx")

插件(Plugins)

2.0中我们在nuxtconfig中配置插件是否走ssr,3.0中我们可以直接通过文件命名实现:

如2.0中有插件plugin/a.js不在ssr中执行,我们需配置

plugins: [
    {src: '~/plugins/a.js', ssr:false},
],

在3.0中我们直接在plugins目录新建a.client.ts即可:如使用elementui

import DragArc from 'drag-arc';
export default defineNuxtPlugin((NuxtApp) => {
  return {
    provide: {
      DragArc: DragArc
    }
  }
})

在组件中使用

<script setup>
const { $DragArc } = useNuxtApp();

const DragArc = new $DragArc({
    el: dom,
    value: 10,
    change: (v) => {
        console.log(v)
    },
    ...
})
</script>

存储(store)

Nuxt3.0不再提供Vuex集成,推荐使用pinia。

首先安装pinia yarn add pinia @pinia/nuxt

新建store目录,存放相关文件

import { defineStore } from "pinia";
export default defineStore('main',{
    state(){
        return{
            count: 1
        }
    }
    //...
}) 

pinia确实比vuex好用的多,直接按文件拆分模块,可以使用this,actions支持同步异步,不用再纠结action和mutations。??

服务(Server)

感觉3.0最大的变化就在这块,抽离了服务端的router、plugin、middleware功能到该目录,区分了server层和client层;

api

api目录下的文件用于接口开发,如新建hello.ts

export default defineEventHandler((event) => {
  return {
    api: 'world'
  }
})

请求localhost8000/api/hello,返回world

router

对于所有不带api的请求我们只可以在这个目录下进行处理,

代理全部wx/开的头的请求代理到 http://pyss.top 的域名下,新建xw/[...].ts

import  { sendProxy } from 'h3'
export default defineEventHandler(async (event:any) => {
  let target = new URL(
  event.req.url, 'http://pyss.top');
  return await sendProxy(event, target.toString());
});

关于请求处理我们很多地方要直接用到h3的api,文档在https://github.com/unjs/h3

关于请求的统一处理 我们也可以再这里做处理

如不同环境下域名的配置,nuxt3中给出了四种不同的请求方法,并建议我们去使用这四种方法而不是使用axios,确没有给出统一处理方法

首先我们可以再项目中加入env变量,并配置到runtimeConfig中
env

const env  ={
    test: "https://test",
    rc: "https://rc",
    prod: "https://prod",
}

nuxtconfig

import env from "./env"
runtimeConfig: { 
   public:{
      ...env[<string>process.env.MODE]
   }
}

在相关路由中加入

export default defineEventHandler(async (event:any) => {
  const url = event.req.url;
  const config = useRuntimeConfig();

  const result:any = await $fetch(url, {
    baseURL: config.basicUrl
  })
  
  return result
});

middleware

所有请求处理都会经过middleware,可以对请求做一些处理校验、扩展等功能

例如我们在这可以为请求添加header自定义字段

export default defineEventHandler((event) => {
    event.header.token = "12..."
})

在这里console请求排查问题也很方便?

export default defineEventHandler((event) => {
   console.log(event.node.req.url+': '  event.node.req)
})

plugin

这里的插件主要是对Nitro进行扩展,nitro的文档在这里https://nitro.unjs.io/guide/getting-started

这块主要用于一些后端数据相关的操作的扩展,没有用到这块┓( ´∀` )┏