nuxt2升级nuxt3
记录升级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
这块主要用于一些后端数据相关的操作的扩展,没有用到这块┓( ´∀` )┏