---
title: 浅谈Vite        
date: 2022/5/2515:00:00
tags:                    
- vite
- package.json            
author: 张芳利        
---

<a name="Sxg5O"></a>
# 1. Vite 简介
<a name="GUv9u"></a>
## 1.1 Vite是什么？

Vite是一个由原生 ES Module 驱动的 Web 开发前端构建工具，它能显著改善前端开发体验；<br />要由两部分组成：

- 一个开发服务器，它基于 [原生 ES 模块](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) 提供了 [丰富的内建功能](https://vitejs.cn/guide/features.html)，如速度快到惊人的 [模块热更新（HMR）](https://vitejs.cn/guide/features.html#hot-module-replacement)。
- 一套构建指令，生产环境，它使用 [Rollup](https://rollupjs.org/) 打包你的代码，并且它是预配置的，可输出用于生产环境的高度优化过的静态资源。
<a name="V0wyB"></a>
## 1.2 Vite的特性

- 💡 **极速的服务启动：** 使用原生 ESM 文件，无需打包！
- ⚡️ **轻量快速的热重载：** 无论应用程序大小如何，都始终极快的模块热重载（HMR）
- 🛠️ **丰富的功能：** 对 TypeScript、JSX、CSS 等支持开箱即用。
- 📦 **优化的构建**：可选 “多页应用” 或 “库” 模式的预配置 Rollup 构建
- 🔩 **通用的插件**： 在开发和构建之间共享 Rollup-superset 插件接口。
- 🔑 **完全类型化的API**：灵活的 API 和完整 TypeScript 类型
<a name="Vv04S"></a>
# 2. Vite概念及设计思想

**打包：**使用工具抓取、处理并将我们的源码模块串联成可以在浏览器中运行的文件。
<a name="vmIab"></a>
## 2.1 和webpack 的区别

1. **打包和速度：**

webpack: 分析依赖=> 编译打包=> 交给本地服务器进行渲染。首先分析各个模块之间的依赖，然后进行打包，在启动webpack-dev-server，请求服务器时，直接显示打包结果。webpack打包之后存在的问题：随着模块的增多，会造成打出的 bundle 体积过大，进而会造成热更新速度明显拖慢。<br />
![webpack](/yifu-study-front-share/images/viteImg/webpack.png)

vite: 启动服务器=> 请求模块时按需动态编译显示。是先启动开发服务器，请求某个模块时再对该模块进行实时编译，因为现代游览器本身支持ES-Module，所以会自动向依赖的Module发出请求。所以vite就将开发环境下的模块文件作为浏览器的执行文件，而不是像webpack进行打包后交给本地服务器。<br />
![vite](/yifu-study-front-share/images/viteImg/vite1.png)

2. **工具定位：**

webpack：是偏底层的东西，进行配置化，灵活度极高的工具,具有丰富的生态圈<br />vite: 是开箱即用，使用更简单的工具，但是目前是属于起步阶段

结论：

1. Vite主打特点就是轻快冷服务启动。冷服务的意思是，在开发预览中，它是不进行打包的。
1. 开发中可以实现热更新，也就是说在你开发的时候，只要一保存，结果就会更新。
1. 按需进行更新编译，不会刷新全部DOM节点。这功能会加快我们的开发流程度。

<a name="rEfXe"></a>
## 2.2 Esm 加载对比

1. esm 文件中，创建index.js , 引入main.js
```jsx
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ESM Brower</title>
  <!-- type 是module -->
  <script src="main.js" type="module"></script>
</head>
<body>
  
</body>
</html>
```

2. 安装 lodash的包

`yarn add lodash-es`

3. 引入loadsh，并利用她的fiter 功能
```jsx
console.log('测试esm');

import {filter} from 'loadsh'

const arr = [{name:'张小张',age:'22'},{name:"王小王",age:'18'}]
const newArr = filter(arr,item=>item.age>20)

console.log(newArr);
```
报错：<br />Uncaught TypeError: Failed to resolve module specifier "loadsh". Relative references must start with either "/", "./", or "../".<br />浏览器原生解析路径的问题，所以换一下引入方式<br />node_modules中找到lodash-es,找到她的package,json，查看找到 "main": "lodash.js"
```jsx
import { filter } from './node_modules/lodash-es/lodash.js'
```

4. 利用**Live Server** 插件，项目启动

![live server启动](/yifu-study-front-share/images/viteImg/vite2.png)

5. 我们能看到打印出来的东西：

![打印1](/yifu-study-front-share/images/viteImg/vite3.png)<br />![打印2](/yifu-study-front-share/images/viteImg/vite4.png)<br />![打印2](/yifu-study-front-share/images/viteImg/vite5.png)
<br />从上面看到只是用到了一个过滤但是其他的模块等也都进行了请求，浪费了时间

**vite是怎么做的呢？**

1. 创建一个vite-esm 文件

`yarn create vite`

2. 同样 安装lodash-es
2. main.js 中同样操作 
```jsx
console.log('测试esm');

import { filter } from 'lodash-es'

const arr = [{name:'张小张',age:'22'},{name:"王小王",age:'18'}]
const newArr = filter(arr,item=>item.age>20)

console.log(newArr); 
```

4. yarn dev 后，页面中看到

![打印3](/yifu-study-front-share/images/viteImg/vite6.png)<br />![打印4](/yifu-study-front-share/images/viteImg/vite7.png)<br />对比之下可以看到，页面清爽了很多，很多没有必要的请求也没有了。
<a name="vXvPP"></a>
# 3. vite 的使用
> Vite 需要 [Node.js](https://nodejs.org/en/) 版本 >= 12.0.0。

-  **npm **
```jsx
npm init vite-app <project-name>
cd <project-name>
npm install
npm run dev
```
或者
```jsx
npm init @vitejs/app 项目名称
npm init vite@latest 

```
这个命令安装就是一步步自己选择一下是react还是vue,以及ts 等。如果选择vue,都是vue3.0的。


- **yarn**
```jsx
yarn create vite-app <project-name>
cd <project-name>
yarn
yarn dev
```
或者
```jsx
yarn create @vitejs/app 项目名称
```
使用yarn有个问题 ：文件名、目录名或卷标语法不正确<br />解决方法：[https://juejin.cn/post/6844904111570190349](https://juejin.cn/post/6844904111570190349) 

vite中还会有一些模板可以选择，指定的所有相关项目模板都可以在[ https://github.com/vitejs/awesome-vite#templates]() 仓库中找到
> 一般都是默认创建的是vue3的项目，所以如果创建vue2,需要做一些修改之类的或者在模板库中查找使用

<a name="z548o"></a>
## 3.1 遇到的问题
 控制台会显示 user --host to expose（使用 --host 暴露网络） <br />![host问题](/yifu-study-front-share/images/viteImg/vite8.png)<br />解决方法：

1. 在根目录下的 vite.config.js 文件中添加以下内容
```jsx
import vue from '@vitejs/plugin-vue'

/**
 * https://vitejs.dev/config/
 * @type {import('vite').UserConfig}
 */
export default {
  plugins: [vue()],
  server: {				// ← ← ← ← ← ←
    host: '0.0.0.0'	// ← 新增内容 ←
  }						// ← ← ← ← ← ←
}


```

2. 通过 Vite CLI 配置

执行 npx vite --host 0.0.0.0 命令后，就可以通过 http://10.56.116.128:3000/ 访问了。

3. 修改npm 脚本

修改 package.json 文件中 scripts 节点下的脚本，如下
```jsx
"scripts": {
  "dev": "vite --host 0.0.0.0",
  "build": "vite build",
  "serve": "vite preview --host 0.0.0.0"
}
```
<a name="R0yEc"></a>
## 3.2 项目目录
```jsx

|-node_modules      -- 项目依赖包的目录
|-public            -- 项目公用文件
  |--favicon.ico    -- 网站地址栏前面的小图标
|-src               -- 源文件目录，程序员主要工作的地方
  |-assets          -- 静态文件目录，图片图标，比如网站logo
  |-components      -- Vue3.x的自定义组件目录
  |--App.vue        -- 项目的根组件，单页应用都需要的
  |--index.css      -- 一般项目的通用CSS样式写在这里，main.js引入
  |--main.js        -- 项目入口文件，SPA单页应用都需要入口文件
|--.gitignore       -- git的管理配置文件，设置那些目录或文件不管理
|-- index.html      -- 项目的默认首页，Vue的组件需要挂载到这个文件上
|-- package-lock.json --项目包的锁定文件，用于防止包版本不一样导致的错误
|-- package.json    -- 项目配置文件，包管理、项目名称、版本和命令
|--vite.config.js   -- 配置文件
```
<a name="mLpTv"></a>
## 3.3 vite插件
Vite 旨在为常见的 web 开发工作提供开箱即用的支持。你可以使用插件进行扩展功能。<br />地址：[https://github.com/vitejs/awesome-vite#plugins](https://github.com/vitejs/awesome-vite#plugins)<br />例如：为传统浏览器提供支持

1. 下载
```jsx
 npm i -D @vitejs/plugin-legacy
```

2. 需要将它添加到项目的 devDependencies 并在 vite.config.js 配置文件中的 plugins 数组中引入它
```jsx
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11']
    })
  ]
})
```
<a name="YkAyf"></a>
## 3.4 vite.config.js 

1. 是否自动在浏览器打开

`open: true`

2. 在生产中服务时的基本公共路径

`base: './',`

3. 与“根”相关的目录，构建输出将放在其中。如果目录存在，它将在构建之前被删除

`outDir: 'dist'`

4. 更改默认端口

`port:8080,`

5. 开启热更新

`hmr:true`

6. 配置别名路径
```jsx
resolve:{
    alias:{
      "@":resolve(__dirname,"src"),
      "@c":resolve(__dirname,"src/components"),
    }
  },
```

7. 设置便捷图片路径引用
```jsx
resolve:{
    alias:{
    "/img":"src/assets/images/"
    //这里不能通过path模块解析路径的写法
    }
  },
```

8. 把vite打包以后的js,css和img资源分别分门别类在js/css/img文件夹中
```jsx
build:{
    assetsDir:"static",
    rollupOptions:{     //自定义底层的 Rollup 打包配置,从 Rollup 配置文件导出的选项相同
      input:{
        index:resolve(__dirname,"index.html"),
        project:resolve(__dirname,"project.html")
      },
      output:{
        chunkFileNames:'static/js/[name]-[hash].js',
        entryFileNames:"static/js/[name]-[hash].js",
        assetFileNames:"static/[ext]/name-[hash].[ext]"
      }
    },
  },
```

8. 跨域
```jsx
server: {
    port: '3000',
    open: false, //自动打开 
    base: "./ ", //生产环境路径
    proxy: { // 本地开发环境通过代理实现跨域，生产环境使用 nginx 转发
      // 正则表达式写法
      '^/api': {
        target: 'http://xxx.xxx.xxx.xxx:9999', // 后端服务实际地址
        changeOrigin: true, //开启代理
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  },
```
<a name="agldq"></a>
## 3.5 给项目配置多个环境

1. 在项目根目录下分别新建.env.development,.env.test,.env.production文件
```jsx
//.env.devopment文件内容
NODE_ENV="development"
VITE_APP_BASEAPI="https://www.dev.com"

//.env.test文件内容
NODE_ENV="test"
VITE_APP_BASEAPI="https://www.test.com"

//.env.production文件内容
NODE_ENV="production"
VITE_APP_BASEAPI="https://www.production.com"
```

2. package.json
```jsx
"scripts": {
    "dev": "vite --mode development",
    "build": "vite build --mode production",
    "test": "vite build --mode test",
    "preview": "vite preview"
  },
```

3. 项目中通过Import.meta.env.VITE_APP_BASEAPI来获取对应环境的值
```jsx
<template>
  <div>
    <Item></Item>
  </div>
  
</template>
<script setup>
    import { defineComponent, onMounted, ref } from 'vue'
    import Item from "@c/item.vue"
    console.log("env", import.meta.env.VITE_APP_BASEAPI)
    console.log("可选链", obj?.gender || "male")
})
</script>
```

<a name="pgCX0"></a>
# 4. npm init vite@latest做了什么？
<a name="HsCxP"></a>
## 4.1 npm init
npm init :初始化一个简单的package.json文件，执行该命令后终端会依次询问 name, version, description 等字段<br />查询[文档](https://docs.npmjs.com/cli/v7/commands/npm-init)得知：<br />**npm init <initializer>：**can be used to set up a new or existing npm package.（可以用来建立一个新的或现有的NPM包）
<a name="oLGN9"></a>
## 4.2 npm init <initializer>
initializer in this case is an npm package named create-<initializer>, which will be installed by [npm-exec](https://docs.npmjs.com/cli/v7/commands/npm-exec), and then have its main bin executed -- presumably creating or updating package.json and running any other initialization-related operations.<br />（initializer 在这种情况下是一个名为 create-<initializer> 的 npm 包，这个包将由 [npm-exec](https://link.juejin.cn?target=https%3A%2F%2Fdocs.npmjs.com%2Fcli%2Fv7%2Fcommands%2Fnpm-exec)(也就是 **npx**) 来安装，然后执行 package.json 中 bin 属性对应的脚本，运行任何其他与初始化相关的操作。

init命令转化为对应的npm exec操作如下：

- npm init foo->npm exec create-foo
- npm init @usr/foo->npm exec @usr/create-foo
- npm init @usr->npm exec @usr/create

由上面得知：<br />npm init vite@latest => npx create-vite
<a name="ExHkk"></a>
## 4.3 查询create-vite
通过 [npmjs.com](https://link.juejin.cn/?target=http%3A%2F%2Fnpmjs.com) 查找 create-vite 或在 Vite 源代码中的 [packages](https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fvitejs%2Fvite%2Ftree%2Fmain%2Fpackages) 文件夹（如下图）中可以看到有 [create-vite](https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fvitejs%2Fvite%2Ftree%2Fmain%2Fpackages%2Fcreate-vite) 包
<br />![create-vite1](/yifu-study-front-share/images/viteImg/vite9.png)
<br />![create-vite2](/yifu-study-front-share/images/viteImg/vite10.png)
<br />查看在 create-vite 文件夹下的 package.json 中发现 [bin 入口](https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fvitejs%2Fvite%2Fblob%2Fmain%2Fpackages%2Fcreate-vite%2Fpackage.json%23L7)：
<br />![create-vite3](/yifu-study-front-share/images/viteImg/vite11.png)
<a name="OVWEq"></a>
# 









