【vite】-【vite介绍】-【vite的基础应用】-【vite的高级应用】-【

vite介绍

一、特点:

  1. 开发时效率极高
  2. 开箱即用,功能完备
  3. 摄取丰富,兼容rollup
  4. 超高速热重载
  5. 预设应用和类库打包模块
  6. 前端类库无关

二、vite是构建工具的高阶封装,内部使用的是其他的工具,最核心的是rollup
三、vite的目标:

  1. 使用简单:配置项少,把能封装的配置都封装好了,不会让你非常深度的接触一些配置;内部集成devServe,不需要像使用web pack那样再加入devServe再配置再使用;
  2. 快:得益于他的底层架构设计
  3. 便于扩展:兼容rollup插件rollup比webpack发布早,使用率高,社区成熟,插件多

四、和传统构建工具的区别:high level api;不包含自己编译能力(vite底层的编译能力源自rollup、esbuild,vite本身不参与编译,他只是集成了rollup的功能,启动了deserve,vite帮我们做一个串联,去管理模块的图谱,监听文件的更新来进行推送);完全基于esm加载方式的开发式

  1. webpack:他希望他可以把所有能考虑的东西都考虑进去,同时他希望他的核心功能能够帮助其他的功能实现,比如可以通过webpack实现webpack dev serve
  2. rollup:诞生就是为了build esm的module,同时他专注于build javascript,而不考虑平台

webpack编译出来的代码中会有很多webpack的工具函数,来帮助我们加载模块,比如在浏览器中我们要import另外的模块,我们通过script标签引入这个js,然后在js加载完后执行回调函数来将模块加载完成,webpack提供了各种帮助函数来帮助我们做这个事,但rollup不会有自己专有的函数,他遵循esm标准,他build出来的代码符合commonjs、umd标准,这是因为rollup更多是为了让工具类库来使用,他的初衷不是为前端项目服务。而vite的目标是工程,是项目开发,而webpack和rollup他们是工具,他们想执行的是构建,vite更上层,更high level
vite是为项目而生,不是为构建而生,他减少了很多配置量,主要减少在于:

  1. dev server:如果使用webpack配置一个项目,一定要配置dev serve,但是通过vite的命令生成的项目会自动集成dev serve,或者说vite的核心就是dev serve,vite中很大一部分是dev serve
  2. 各类loader:在webpack中需要配置css-loader、post-css-loader、ts-loader等,而vite已经通过插件的形式内置了这些内容,开箱即用
  3. build命令:内置了build命令,通过vite build可以build类库,也可以build项目,对于webpack而言需要自己写命令,开发时的配置和生产的配置可能又不一样,又需要做一些处理

五、vite优势:上手简单、开发效率高、社区成本低(兼容rollup插件)、没有复杂晦涩的配置
六、

vite的基础应用

vite创建项目

vite创建vue3项目

vite创建vue2项目

vite创建react项目

vite中使用css的各种功能

一、推荐使用css variable:简单来说就是在css文件中可以进行变量定义
请添加图片描述
:root代表命名空间,在:root下定义的所有变量在所有选择器中都可以使用,也可以对某一类标签进行样式的定义,那这些样式就只能在某一类标签中使用
二、postcss:vite已集成postcss,如果想用的话,新建postcss.config.js,在里面声明要用的postcss
请添加图片描述
该postcss用于在编译css文件时进行输出:
请添加图片描述
三、@import alias:引入文件时,通过@指向某个目录,在vite.config.js中进行如下配置:
请添加图片描述
在css中的import也可以使用:@import url("@styles/other.css")
四、css-modules:如果希望css的类名不根据我们写的类名,而是根据映射关系进行编译,这样类名就变成了无意义的,并且可以作为一个可以收缩的字符串,同时可以进行去重,对应到vite中,只用在创建css时,文件名写:css文件名.module.css
请添加图片描述
使用时:

<script>import classes from "@style/test.module.css";</script>
<div class={`${classes.moduleClass}`}>hello world</div>

五、css预处理器:安装yarn add less即可使用
请添加图片描述

vite中使用ts

一、vite天生支持ts,因为vite使用esbuild,esbuild支持ts语法,值得注意的是,vite值编译,不做校验,也就是说,他只是把ts语法编译成js,让其可在浏览器中运行,但他不会做ts校验,如果需要校验,需要手动使用tsc --noEmit来校验语法但不输出,如果是在vue项目中,应该写:"build": "vue-tsc --noEmit && tsc --noEmit && vite build(记得先yarn add vue-tsc
请添加图片描述

VScode支持ts语法校验,所以就算你写错了,VScode会给你标出来,可以不用

二、isolatedModules:

  1. vite提供的ts编译只针对单文件的语法编译,而ts是可以关联不同文件之间的模块信息,比如a文件export了一个类型,在b文件import了这个类型是可以直接用的,但是vite编译ts的时候不会读其他文件的相关信息,就会导致一些ts的功能无法使用。在tsconfig.js中配置:"isolatedModules": true用于告诉ts当前环境不支持模块间关联的类型校验的,在开发时就会得到vite编译时的错误提醒
    请添加图片描述
  2. ts中,对于const enum会在使用时直接替换成常量,也就是说,编译出来的js中,第10行代码应为:age: 0,而对于vite的esbuild提供ts语法编译,他不认识const enum这种语法,编译时会直接去掉,也就是说,编译出来的js中,第3-6行代码直接没有了,但是第10行还在使用,所以第10行会报错。配置了"isolatedModules": true,在开发时就会得到vite编译时的错误提醒
    请添加图片描述
  3. 文件必须有模块相关的代码:配置了"isolatedModules": true后,ts强制要求我们在每个文件中做export或import

三、client types:

  1. vite提供了很多内置对象,内置对象又有很多作用,比如可以通过import.meta.来引用环境变量等,这就需要ts认识meta类型, 在tsconfig.js中配置:"types": ["vite/client"]即可使用vite的内置对象
    请添加图片描述
    在ts中使用:
    请添加图片描述
  2. ts不认识png文件,配置了"types": ["vite/client"]之后,ts知道这是png文件,也知道import pngUrl from "./assets/logo.png"返回的是个字符串,在项目中可以直接使用

vite中处理静态资源的方法

一、直接使用import导入,然后使用
请添加图片描述
二、vite提供了几个参数让我们更方便的引入文件:

  1. url:把文件放在某个地方,然后返回个url
    请添加图片描述
    用法:在引入的文件后面加?url
    输出:/src/test.ts
  2. raw:返回图片的字符串内容
    用法:在引入的文件后面加?raw
    输出:把文件的内容作为字符串输出
    请添加图片描述
  3. worker/worker inline:用于web worker(帮助我们更高性能的构建应用的工具),javascript是单线程的,如果将计算量很大的代码和javascript渲染进程放在一起,可能会阻塞渲染,导致页面卡顿,如果有个新的线程来处理这些计算的任务,那么在计算的同时,也不影响页面的渲染,web worker就是用来做这个事
    请添加图片描述
    用法:在引入的文件后面加?worker
    worker.js里存放的就是计算量很大的代码,web worker与主线程通过onmessage通信

三、json:

  1. 引入json直接用:
import pkg from "../package.json"
console.log(pkg)// 输出json文件的内容
  1. 引入json的部分内容:
import {version} from "../package.json"
console.log(version)// 输出version的值 0.0.0

四、web assembly:在浏览器中可运行的二进制的内容,在vite中也可以直接import然后后使用,省去了注册、转换、引入等步骤

import init from "./fib.wasm"
init().then((m) => {
	console.log(m.fib(10))
})

vite集成eslint和prettier

一、eslint规范代码的书写习惯,prettier自动做格式化
二、eslint

  1. 安装:yarn add eslint-config-standard eslint-plugin-import eslint-plugin-promise eslint-plugin-node -D
  2. 在根目录下新建eslint的配置文件.eslintrc.js,在其中声明使用什么规则:
module.exports = {
	extends:"standard"
}

如果写的代码不符合规则(比如standard要求使用’'),在开发时就会给你报错,prettier可以帮助我们将规则自动使用到代码中,在保存时就进行格式化
三、prettier

  1. 在vscode中安装prettier插件,并配置在什么时候执行format
    请添加图片描述
  2. 在根目录下新建prettier的配置文件.prettiertrc.js,在里面声明格式化的内容
{
	"semi":false,// 不需要分号
	"singleQuote":true// 使用单引号
}
  1. 点击vscode的code——setting,搜索format on save,打开保存时格式化
    请添加图片描述
  2. 继续搜索formatter,选择默认使用prettier格式化
    请添加图片描述
    四、在package.js中的script中新增"lint": "eslint --ext js src/",以后执行命令npm run lint就可以验证src下所有的代码是否符合eslint的规则
    五、当eslint和prettier冲突时,可以关掉eslint的某项规则,在eslint的配置文件.eslintrc.js中:
module.exports = {
	extends:"standard",
	rules:{
		'space-before-function-paren': 'off'// 关掉这个规则
	}
}

六、先执行eslint检查再打包文件,在package.js中的script中build值的开头新增"buile": "npm run lint && "
七、执行git commit或者git push之前执行eslint检查,检查不通过则不允许提交,使用husky工具:

  1. yarn add husky -D
  2. npx husky install
  3. npx husky add .husky/precommit "npm run lint":在执行commit之前执行npm run lint

vite中的env环境变量

一、通过import.meta.env可查看vite默认存在4个环境变量:

  1. MODE:指明现在处于的模式,一般用他来对不同环境进行区分,比如dev,test
  2. BASE_URL:请求静态资源初始的URL,比如本地调试的localhost:3000,在线上可能是某个具体的域名
  3. PROD:当前环境是否是正式环境
  4. DEV:当前环境是否是dev,与prod互斥
  5. SSR:是否是服务端渲染的环境

二、production replacement:正式环境不能通过import.meta.env获取对象,如果PROD为true,那么编译后的文件import.meta.env会被替换为一个值,比如import.meta.env.MODE会被编译为"production"一个字符串值
三、自定义env:在src文件夹下新建.env文件,来声明一些自定义env:

VITE_TITLE=HELLO

使用:import.meta.env.VITE_TITLE,在import.meta.env也可以看到有这个VITE_TITLE
四、vite中有一个环境变量的工具,他会读各种不同的变量,然后将其放在环境变量里面,他还会根据文件名来区分不同的环境变量,比如在src文件夹下新建.env.development文件:

VITE_aaa=xxx

.env根据不同环境有不同的后缀,开发环境会用到.development文件,即运行npm run dev时会自动读取.env.development文件
五、mode:在指令中可以通过–mode xxx来指定当前环境
请添加图片描述
他会自动读取.env.test文件的内容
六、在使用自定义的env时,发现类型和vite内置的不一致,并且在写代码时,不会给我们提示,可以在vite-env.d.ts中做如下声明:
请添加图片描述

vite的高级应用

vite中的热更新

一、通过vue-cli或者create vue app创建的项目内部都会集成热更新功能,通过vite命令行生成的项目都默认开启了热更新,同时,vite中的热更新是针对不同框架实现的(热更新本身就是跟框架有关的,不是所有框架通用的),vite中有一套自己的hmr api,没有使用rollup的(本身rollup也没有比较好的hmr api),vite将热更新功能放在了import.meta上面
二、在vite的配置里面,热更新通过vueJsx插件在编译时期加进来的,也就是说,热更新功能在vueJsx插件中实现
三、热更新实现:
请添加图片描述

  1. 需要渲染的内容放在render函数中
  2. 通过vite build打包后输出的文件是没有import.meta.hot的,因为发布到线上的代码没必要有hot,所以需要判断有没有import.meta.hot
  3. 执行了代表这个文件会接收自己的热更新,接收后执行回调函数(即箭头函数),回调函数会接收一个newModule对象,newModule对象就是这个文件的module,所以需要将render函数export,导出后才会有module嘛
  4. 直接通过newModule.render()重新渲染。直接写render()调用的是老的module中闭包的module,就是老的render()

这个代码具有针对性,因为我们知道我们将渲染的内容放在了render函数中。如果我们的模块越来越多,export的module越来越多,那么对于每个函数的export都要去写他们各自相应的render

四、页面如何实现hmr:打开开发者工具-》网络-》ws,可以看到连接到了localhost的server(这个 server是vite dev server中的内容),如果改了main.js的代码并保存,会在这里看到一条新的websocket的更新,这条更新的type是update,acceptedPath为修改的代码的文件(即main.js),这样就告诉浏览器我们有这样一个文件更新了,
请添加图片描述
再看js请求,会有main.js的第二次请求,这个第二次请求会带上时间戳,第二次请求的main.js会替换之前的main.js
请添加图片描述

websocket在server端发现文件更新,然后推一个事件到浏览器,浏览器知道哪个文件更新了,然后重新去请求这个文件,然后用新请求的文件替换旧的文件

glob import

glob import:通过一组类似于正则的表达式来引入一组js文件
假如glob文件夹下有a.js,a.json,b.js,b.json,test-1.js,在main.js中引入glob文件夹下的所有文件:

const globModules = import.meta.glob('./glob/*')
// 如果只想引入js文件:import.meta.glob('./glob/*.js')
// 如果只想引入某几个js,可以通过正则表达式来匹配:import.meta.glob('./glob/*-[1-9].js'),则会引入test-9.js文件
console.log(globModules)

打印结果如下,显然获得的是一个建值对,键是文件名,值是该文件的内容:
请添加图片描述
便利每一项,把值当作函数执行,以获得文件的内容,在main.js中:

Object.entries(globModules).forEach(([k,v]) => {
	v().then(m => console.log(k + ':' + m.default))
})

应用场景:做一个多语言的支持,在某个文件夹下放了很多的语言的json文件,你引入了这些语言但是又不希望每次新增一个语言又要在代码中import一下,那你可以根据文件名来区分语言,直接把整个文件夹引入,然后根据文件名来获得文件与语言的对应关系

预编译

一、预编译:对于我们在node_modules中安装的第三方库,vite在启动之前(一般来说在第一次启动之前),vite会把所依赖的包进行编译并放在缓存中,之后所有用到第三方库的包就会直接从缓存里获取
二、在预编译中有一个很重要的点,非ESmodule的文件会被编译成ESModule,因为在开发时,vite全部依赖于浏览器原生的加载方式加载文件,所以必须把非ESmodule的文件转成ESModule,这样才能正常的工作,否则会报以下错误:
请添加图片描述
报错原因:index.js应该是个ESmodule但是他不是
解决方案:在vite.config.js配置文件中的optimizeDeps中可指定哪些文件需要预编译,哪些不需要,需要预编译的文件放在include里,include是个数组,默认情况下vite会扫描所有的依赖,把所有的依赖都加进来,所以大部分情况include不用配置(因为默认都编译嘛);exclude数组用于指定不需要编译的文件,像下面就指定了不需要编译react(示例)
请添加图片描述
如果出现上述报错,需要在include中加入index.js
上述报错出现的时机:有些第三方插件会帮你增加一些依赖,这些依赖不是ESmodule的依赖,vite在项目启动初期扫描源码时,是发现不了这些依赖的,因为他们是由插件产生的
三、预编译还会将一些零散的文件打包到一起,比如像loadsh这样的包,一个loadsh的包里面可能有上百个不同的文件,他把每个函数都拆到不同文件中去了,而如果我们去import一个loadsh,如果我们采用ESmodule的方式去加载loadsh,那么可能会导致我们import了一个loadsh,但是一次性会加载上百个文件的情况,虽然浏览器能处理,但是性能会受影响,vite对此进行了优化,会把他们打包到一起

服务端集成vite

非node服务

一、问题:后端是java/go服务等,这些服务不运行js,所以使用vite启动的项目无法通过代码的形式直接集成在后端服务中
二、将vite启动的项目集成在后端服务中这一需求背景:在一些传统老项目中,数据需要通过后端服务的模版引擎把数据写入html中,然后再返回给前端,比如一些使用jstl模板语法的Java服务,这样我们的入口文件(html)是存在Java服务中的,因为后端要解析模板然后返回html,而前端应用是关于js的文件,其实我们并不怎么关注html,我们关注的是如何将js文件嵌入html中以成为他的标签,那就存在引入路径的问题,在启动前端项目时,webpack/vite会自动将js的路径注入html,但如果html在别的服务中,那就无法做到这个事,所以要在服务端集成vite
三、

vite配置项一览

vite官方文档

常规配置项

base:公共基础路径
mode:development/production
define:定义全局常量替换方式。其中每项在开发环境下会被定义在全局,而在构建时被静态替换
,如:process.env.FOO
plugin:需要用到的插件数组
publicDir:指定作为静态资源服务的文件夹
cacheDir:存放缓存文件的目录,默认为node_modules/.vite
resolve.alias:命名映射
resolve.dedupe:如果项目中安装了两份同样名字的依赖,比如vue2和vue3你都安装了,那么可以使用该项来制定你要用哪个版本
resolve.conditions:(没懂)
resolve.mainFields:我们去发布包的时候,一般会在package.json中声明main属性,main属性表示,如果我们这个包被别的包安装到自己的node_modules中,他(别的包)require我们这个包的时候,他引入的那个文件对应的就是我们这个包中package.json中main指定的文件;他(别的包)import我们这个包的时候,他引入的那个文件对应的就是我们这个包中package.json中module指定的文件
resolve.extensions:一般我们引入一个文件是不会写扩展名的,该配置项用于指定扩展名数组,会从左到右依次匹配
css.module:配置css modules,选项将被传递给postcss-modules插件
css.postcss:用于配置postcss
css.preprocessorOptions:指定传递给css预处理的选项
json.namedExportss:是否支持从.json文件中进行按名导入

我们可以引入json文件的某个字段:import { version } from '../package.json',这是因为vite将json文件解析成了js,json文件里的所有属性也会根据export 属性名 = xx来export出来,如果将该配置项置为false,则会阻止vite的这种行为

json.stringfy:置为true后,vite会把编译json的过程编译成export default JSON.parse("json文件的字符串内容"),这样做的好处是,JSON.parse(“json文件的字符串内容”)的运行效率要比直接写export这个json对象的字面量高很多,在json很大时尤为明显,所以如果有很大的json文件要引入,建议开启该配置项,不过开启该配置项会导致json.namedExportss不能用,因为他不会export对应的这个json对象里面的具体字段。
esbuild:传给esbuild的配置项
assetsInclude:指定其他文件类型作为静态资源处理。如果你需要有一些不同的其他文件类型,比如你要import一个txt文件,那你就可以将这个文件类型(如txt)维护在这里面,就是告诉vite,我们import一个.txt文件时,他也是一个静态资源,vite就会他放到后续编译后的asset的目录下来做一个引入
logLevel:指定控制台输出的级别,默认为info,所有日志都会打印出来

如果指定为error,那么只会打印出error,info和warn不会打印出来

clearScreen:默认为true,vite在终端打印信息时,你重新编译是,vite会把之前打印出来的信息清空掉
envDir:指定.env文件的目录,默认为root

开发服务器选项

server.host:配置域名,如果希望通过ip访问,可配置为0.0.0.0
server.port:指定端口
server.strictPort:设为true,若端口已被占用则会直接退出,而不是尝试下一个可用端口(一般会端口号+1的去查找,比如发现3000端口不能用,会尝试3001)
server.https:配置https启动方式
server.open:启动服务后会自动在浏览器打开对应的页面
server.proxy:配置请求代理,在不使用请求代理的情况下,你如果去访问后端开发的服务,会收到跨域限制,如果配置了请求代理,那么页面上的请求会发送到你自己的服务,然后你的服务再去请求到后端的机器上,此时页面上的请求就是同域的

export default defineConfig({
  server: {
    proxy: {
      // 字符串简写写法:http://localhost:5173/foo -> http://localhost:4567/foo
      '/foo': 'http://localhost:4567',// 可以通过配置具体的某一个路径给他映射到某个ip这种方式来配置
      // 带选项写法:http://localhost:5173/api/bar -> http://jsonplaceholder.typicode.com/bar
      '/api': {// 也可以更详细的配置代理
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
      // 正则表达式写法:http://localhost:5173/fallback/ -> http://jsonplaceholder.typicode.com/
      '^/fallback/.*': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/fallback/, ''),
      },
      // 使用 proxy 实例
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        configure: (proxy, options) => {
          // proxy 是 'http-proxy' 的实例
        }
      },
      // 代理 websockets 或 socket.io 写法:ws://localhost:5173/socket.io -> ws://localhost:5174/socket.io
      '/socket.io': {
        target: 'ws://localhost:5174',
        ws: true,
      },
    },
  },
})

server.cors:跨域配置,你可以配置你启动的vite服务他是一个允许跨域的配置,那么别的人要发api请求就会发到你这里来
server.force:对于依赖的预构建的相关配置,设为true
server.hmr:关于hmr的配置
server.watch:关于我们去watch文件的相关配置,使用的是chokidar包
server.middlewareMode:以中间件模式创建vite服务器,配置为ssr时,vi te不会主动使用index.html文件的内容作为server的
server.fs.strict:默认为false,不会去读这个项目所处的root路径以外的文件
server.fsServe.root:文件资源所serve的root

标准配置

build.target:对应你构建的目标,就是你运行的浏览器的兼容性的目标,比如你想支持IE,那你就可以写IE11之类的版本,就可以告诉vite,编译代码时编译的js要兼容IE11
build.polyfillDynamicImport:是否要动态引入polypill,如果你要引入一些兼容性相关的文件,可以配置该配置项
build.outDir:指定输出路径
build.assetsDir:指定生成静态资源的存放路径
build.assetsInlineLimit:如果我要把图片编译成base64直接放到js/html代码中,该配置项用于指定大小,如果文件的大小小于这个配置项,那么会讲文件编译成base64放在代码里, 如果大于,则会以文件的形式引入
build.cssCodeSplit:css文件是否可拆分,若设为true,假如你有个异步的模块,假如你通过import这个函数来异步引入某个js,然后这个js中引入了css,那么这个css会跟那个异步引入的js一同进行拆分,就是说你在引入这个js时,也会同时引入拆分的css;若设为false,那么你整个项目都只会有一个css文件,这个css文件包含了所有异步模块的css内容
build.sourcemap:构建后是否生成source map文件
build.rollupOptions:传给rollup的配置内容
build.commonjsOptions:传给rollupcommonjs插件的内容
build.dynamicImportVarsOptions:传递给rollup-dynamic-import-vars插件的内容
build.lib:我们导出的是一个库模式而不是一个应用的模式
build.manifest:设为true,侯建侯将会生成manifest.json文件,这个manifest.json文件会包含我们的html引入了哪些js的文件名和css的文件等
build.minify:
build.terserOption:传递给terser的更多minify选项
build.cleanCssOptions:传递给clean-css的构造器选项
build.write:设为false,构建后的文件不会写入磁盘,你可以在内存中读取这个文件,然后把他直接传到cdn上面
build.emptyOutDir:构建时是否主动将Outdir清空然后把新构建的文件放进去,这个一般来说是需要的
build.brotliSize:启用/禁用brotli压缩大小报告,也就是计算你build之后的文件的压缩报告的,开启的话,他在命令行会自动给你打出来
build.chunkSizeWarningLimit:某个js如果超过了500k(默认)那么他就给你提醒
build.watch:是否监听文件变化,相当于文件一变化他就重新build

依赖优化选项

optimizeDeps.entries:告诉vite哪些文件需要pre-build,正常情况下,vite会分析我们项目用到的哪些依赖,它自动会去找
optimizeDeps.exclude:
optimizeDeps.include:

SSR选项

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值