之前vite2
刚出的时候其实已经自学过一波,但是老实说学起来完全不入脑,一方面本来这方面的基础就很差(指项目配置),另一方面学的时候没有跟着去动手,纯理论的学那完全就是越看越困。最后就是急躁,想一下就学完。所以到现在来说基本上就是零基础。这次痛并思痛,跟着文档一步一步来。
faster and leaner development experience for modern web projects
faster and leaner
、development experience
、modern web projects
是用来干什么的一目了然:提高开发体验感的,并且仅支持标准(现代)浏览器(>= IE 9``?不清楚
9算不算,但是没差,
IE`已经不再维护了)。
注意这里是”(development
)开发“,而打包还是交由rollup
处理。
拥抱ES MODULE
[2] (现代浏览器天然支持)而非CommonJs
[3]。
话不多说,直接上手。如果你不想一步一步配置的话,可以直接看官方的demo
[4] 。
不过学习嘛,还是一步一步来好些。
先创建个文件夹,然后初始化下环境
然后安装下vite
,推荐是全局安装,因为cli
做了各种框架的基础配置,能快速生成项目。
安装完之后我们先什么都不动,仅新增个index.html
文件,记住这里和webpack
不同,直接放根目录,vite
会在根目录里找,这是因为vite
将index.html
当做入口的原因。
然后package.json
中配置下script
然后直接终端执行指令npm run dev
非常简单,非常傻瓜,这样就跑起来啦。
但其实只是起了个koa
[5]服务器而已,和你自己手动起的没差,甚至不需要koa
,直接就http
[6]模块开就行了。
现在我们再给这个index.html
加点js
和css
文件。
index.css
随便搞点样式
index.js
中import
这个index.css
文件
然后重新再跑一下指令npm run dev
。
然后你会发现没有任何变化,因为我们压根没有给他们之间建立联系
直接在index.html
中引入这个index.js
文件,不过需要注意一点,script
的type
需要是module
,这样才能被识别是ES Module
,才能支持export import
等。
然后ctrl + s
自动reload
如果script
的type
不是module
,你在运行的时候浏览器就会报错。
如果你细心的话应该会发现你的index.css
中的样式被打上了scoped-id
:data-vite-dev-id
。如果你之前看过我的文章你会知道这里搞个自定义id
的作用是啥,一是作用域样式不会污染其它模块样式;二则是热更新可以直接找到这个style
标签然后直接覆盖替换。
然后没啥好说的了,我们接着直接来接入框架了。
不过到现在都没用到vite.config.js
,有些憋屈,所以得找个理由改下配置~。
有了,dev
的域名端口太丑~,我们来改下。
我们先在根目录创建vite.config.js
,然后配置下servver
[7]
然后ctrl + s
即可~
vite
虽然可以和其他框架比如react、svelte
等框架配合,但最适合那自然还是vue
(非技术方面,纯感性~)。
先安装vue
以及能让vite
“识别”vue
的plugin
: @vitejs/plugin-vue
[8]
然后在vite.config.js
中引入,配置到plugins
[9]中。
接着我们在根目录创建views
文件夹,然后在里面创建一个App.vue
然后老规矩index.js
中引入
然后老规矩在index.js
中引入vue
组件入口。
最后别忘了index.html
中创建个id
为app
的元素。
不过这里还是遇到了问题,同时配置server.port
和vue
插件时会找不到页面,可能刚没关好,端口还在。。换成port:7777
就正常了。。。
官方还是很推荐vue3 +typescript
的。
老规矩如果嫌麻烦可以直接去看线上的demo
[11] ,不过学习嘛,最好还是都过一遍。
有一点我们需要知道,vite
仅提供.ts
文件的加载识别处理,而类型判断需要IDE
或者通过tsc
等构建过程实现。
可能我说的不是很对。。。。所以还是贴下原文。。。如果说错了麻烦大佬评论里说下,谢谢~
其他就不多说了,直接来配置
先来安装下我们需要的东西,既然用到了typescript
那自然是得先安装它才行,而vue-tsc
刚上面提到了一些,是一个包裹了tsc
[12]的工具,专门用来识别处理vue
[13]文件的。
安装完之后我们来配置下tsconfig.json
文件
compilerOptions
[14]: 顾名思义,编译所需要的配置参数,当然这是可以不配置的,不配置会用默认参数。target
[15]: 编译的目标环境,比如es5
,常见的配置。ESNext
表示最新的ECMA
下一代标准。useDefineForClassFields
[16]: 这是用来告知ts
使用下一代标准runtime
,当然语法还是一样的所以不需要考虑兼容性问题。默认值会根据你的target
的配置改变,如果是ES2022
或者ESNext
也就是最新版或者下一代版本,默认值会是true
,如果不是默认值则是false
。 这里要设置为true
,因为vue
需要。其他框架具体看情况,比如lint-component
就不能是true
。module
[17]: 设置模块规范,大家应该都知道这一块了,commonJs
或者ES2015(ES6)
等。ESNext
下一代ECMA
标准。moduleResolution
[18]: 告知ts
要怎么处理模块。这里用的ESNext
,所以是Node
。resolveJsonModule
[21] : 这个也很好理解,就是告知ts
支持对json
文件的处理,不然当你import
了json
文件之后会报错处理。isolatedModules
[22] : 这个配置还是比较重要的,vite
是基于esbuild
实现的,而esbuild
对typescript
的一些东西并不支持,比如type-only
的导入或者enum
。所以得加上这个字段通知ts
提醒你这些语法不支持。esModuleInterop
[23]: ts
会将commonJs/AMD/CMD
转换成和ES6 module
类似的,因为这层转换,导致存在两个问题:1. ESM
中使用import * as x from 'a'
相当于commonJs
中的const x = require('a')
。乍一看貌似没啥问题,但实际上ESM
的 * as x
是只能用于对象导入的,而对应的CJS
中还可以是function
等,这就会有问题了。2. 你引入的第三方包不一定都有做这两种规范的入口,所以可能会存在第一点中的问题。开启这个字段后,会从两方面来处理这个问题,一是compiler
中,二是导入两个辅助函数。lib
[24]: 类型检测需要的包,默认会检测你的target
,会根据你的target
来判断引入对应的内置api
类型判断以及提示。默认也会有浏览器端代码提示,也就是DOM
提示。skipLibCheck
[25]: 看名字就知道,绕过整个包的检测,只会检测你引入的方法等,可以节省编译的时间。noEmit
[26]: 看名字也很好懂,就是不要输出,比如编译后的源码,sourcemap
等,这样你引入的typescript
就相当于只是类型检测和代码提示的包而已。 然后可以用其它包比如babel
转换。include
[27]: 这个就不多说了,就是限制只转换这部分的文件,其中/**/*.xx
是会检测所有这个文件夹下的文件的,但如果只是*.xx
,没有**/
就只会检测当前这个文件夹下的xx
后缀名字的文件,文件夹会直接绕过。这个要单独说下,这是typescript 3.0
开始支持的一个特性。
简单地说,你的项目可能有多个文件夹,这些文件夹有自己的想法,所以需要做不同的配置来构建单独的output
,而如果没有使用这个特性,你只能是给每个文件夹加上tsconfig.json
文件,并且执行多次tsc
才行。
由于你可能需要不同的配置针对不同的文件夹,但是配置文件只有一个的时候并不能满足这个需求,当然你可以给每个文件夹配置一个自己的conf
文件,但这依旧有一个问题就是tsc
并不能帮你给所有的配置文件都处理,有些地方需要你去手动处理,watch
也并不能一次性监听所有的配置文件,这也就意味着你也得手动添加才行。
针对上面的问题,3.0
开始支持了refercens
,能有效的帮你拆分你的项目,分别执行对应的配置。
path
:指向对应文件夹中的配置文件,如果只写了文件夹名字,比如./src
,那就只会读对应的tsconfig.json
,而如果你的配置文件是自定义名字,请务必加上文件名。
然后我们创建tsconfig.node.json
文件
composite
[30]: 这是个必要字段,只要你是references
的就都需要配置,方便ts
去快速找到output
对应的文件夹。不过如果你的文件位置和文件夹位置不是在同一个地方,那么你可以设置rootDir
去改变。allowSyntheticDefaultImports
[31]: 允许你使用import x from 'a'
替换import * as x from 'a'
include
: 前面提到过include
指向需要参与tsc
构建的文件,这里单独开了一个reference
,就是为了这个vite.config.ts
能被正常处理,一般情况下不参与构建,所以这里得单独指明这个文件也是需要参与构建的。然后我们修改下vite.config.js
为vite.config.ts
。
接着我们新建src
目录,将我们的App.vue
、index.css
迁移到src
下。然后新建main.ts
文件作为入口。
这个时候的App.vue
会有错误下划线,这是因为typescript
并不知道这是什么,我们先不管,稍后会做声明。
然后改下index.html
的引入,这里你应该有些好奇居然可以直接引入ts
文件,那是因为vite
将html
作为入口,也是会参与打包的。
接着我们进入到App.vue
文件中,我们需要写点typescript
的代码
这个时候,handleChangeText
方法中text.value
会有红色下划线,这是因为我们定义了text
是一个string
类型的ref
。
上面说到main.ts
中引入App.vue
时无法识别.vue
文件,那是因为我们并没有对vue-sfc
文件做声明,typescript
自然是不认识的。
我们在src
文件夹下新建vue-env.d.ts
文件
///
这一行代码是通知vite
这是一个client
端声明文件,之前讲vitest
时也有提到过,感兴趣的大佬可以去看下我之前的文章。
声明的代码也很好理解,就是声明*.vue
文件是Component
。
我们之前已经在tsconfig.json
中include
过了.d.ts
文件了,所以这里并不需要我们去哪里给他导入。
这个时候你再回去看main.ts
,发现已经没有报错了。
最后我们来改下package.json
中的一些地方
这样就配置ok
啦,我们在终端运行下npm run dev
。
运行成功!
既然基础已经可以跑通了,那么我们就来搞个小而五脏俱全的。
这就安装完啦,然后我们在src
文件夹下创建一个views
文件夹,然后在里面创建Index.vue
以及创建A.vue
和B.vue
用来测试我们的路由。
随便给A.vue
以及B.vue
写点东西,B
的代码类似,这里就不展示了。
然后我们在src
下创建router
文件夹以及在这个文件夹里新建index.ts
然后我们在这个index.ts
中写下router
的配置。
主路由是Index.vue
然后两个子路由A
和B
然后老规矩将这个router
给vue
use
一下。main.ts
中引入router
然后让我们回过头去到Index.vue
中,我们需要写个click
事件让路由变化。
由于组合式api
不再使用this
,所以这里只能是import
再create
了[33]。
另外别忘了在App.vue
中将路由组件渲染在template
中。
然后就完成啦,我们重新跑下指令npm run dev
运行成功!
没想到vuex
直接被偷家了,目前由于vuex
还是4.x
版本,存在一些问题,比如同步异步分割的问题(老问题了)。
而pinia
完全就是按照vuex5
的预案来实现的,所以说是vuex5
也不为过,目前这个包是官方接手并且推荐的。
总结下就是pinia
轻快好省。 话不多说,感兴趣的可以去看下官方的描述。
Piniapinia.vuejs.org/introduction.html
我们直接来安装
话不多说,先引入pinia
并且给vue
use
下。
然后main.ts
引入
ok
,这就配置完啦~
接着我们来存储一些数据,进入src/store/user.ts
当然如果你不习惯写compositionApi
的话也是可以的,传入一个options
,字段为state, getters, action
[35]
然后让我们去到A.vue
方法中,将这个user
引入
注意如果你用的是对象解构并且这个数据是一个非引用的数据,你就需要用storeToRefs
进行包裹,因为解构导致它失去了响应式,相当于const a = 1
这样。
这样就完成啦~
我们接着准备接入vitest
[37],不过在这之前,我们要配置下别名,不为什么,只是为了少写几个字而已~
话不多说,直接去到vite.config.ts
文件中。 vite
别名配置是基于rollup
的插件@rollup/plugin-alias
[38],所以写法一致。
但是到这里还没有结束,我们还需要告知ts
这个@
字符代表什么意思。
这样就正常啦~,可以安心的将你的绝对路径改成@/xxx
了。
这是一个从vite
中抽出去的一个包,我之前也写过一篇文章学习vitest
的,感兴趣的大佬可以去看下。
话不多说,我们直接配置。这里就不用inline
测试了,感兴趣的大佬可以看下我上面提到的这个文章。 另外下面用到的一些东西我就不解释了,这文章里都有说的。
首先,因为这个包是在src
外的,所以我们需要在tsconfig.json
文件中将他include
了导入文件才能正常。
然后我们直接进入vite.config.ts
中配置下。
这里需要注意几点,如果你是在vite.config.ts
文件中配置的,你需要在文件头配置///
通知vite
这里有配置test
。当然你也可以重开一个vitest.config.ts
,然后把这个vite.config.ts
注释掉,将里面的配置迁移到vitest.config.ts
中。当然你还可以使用mergeConfig
将这两个配置文件中的配置合并,这里就不多说了。
environment
: jsdom
表示我们是在浏览器环境,需要测试dom
。
globals
: 如果是true
你就可以在全局都有vitest
的代码提示了。 如果设置了true
别忘了通知ts
,回到tsconfig.node.json
中配置types
。
然后我们再来安装下我们测试需要的包jsdom
[40]和@vue/test-utils
[41] 。
然后我们进入__tests__/testComponentA.spec.ts
中
最后让我们去到package.json
文件中新增一个script
: "test": "vitest"
然后终端执行npm run test
然而直接报错了。
为什么呢,因为这个时候pinia
没创建实例,这又是为什么呢?因为项目没有跑起来。。。
那么怎么办呢?那只能是将main.ts
也跑了。。另外还发现一个问题,就是点击事件需要异步处理。
这回重新跑npm run test
成功啦~,age
成功变成25
了。
我们来搞个自己的插件玩下。
vite
的plugin
接口是基于rollup
[43]的接口,然后加了一些自己的东西。
我们先在根目录新建一个plugins
的文件夹,然后新建vite-plugin-vue-test.ts
。这里需要注意vite
的plugin
的文件名是一定要vite-plugin-*
[44]的,如果你的plugin
是只想用于某个框架,那就得是vite-plugin-vue/react-*
这样。当然你可以写rollup
的插件,命名和rollup
的规范一致。
先来看下编写规范,和rollup
的其实是一样的。
name
字段,这是必须的,用来标识你的plugin
。resolved、load
都是vite
抛出的hook
,你可以监听他们,然后返回数据来改变某些东西。ok
,基本了解完毕,接下来就是得想一下我们的plugin
要干嘛,就简单的log
下吧。。。学习嘛,就是不要有这么多技术含量doge
(误).
我们来log
下执行过程中的三个hook
,看下都是个啥。
resolveId
[45]: 模块请求中自定义的解释器?可用来代码第三方包的解析。load
[46]: 加载的时候触发,热更新的时候只加载需要的。id
指向文件路径。transform
[47]: 看名字就知道这肯定是和源码有关的。其他的hook
这里就不log
了,知道怎么实现一个plugin
就是我们的目标。
那么到这就结束啦,如果觉得对你有用的话一定要点个赞啊~~谢谢!
编辑于 2023-08-14 09:15・IP 属地广东