构建工具说明

打包

将我们写的浏览器不认识的代码,交给构建工具进行编译处理的过程就叫做打包

构建工具的作用
  1. 支持模块化开发
  2. 集成语法处理工具,编译代码,压缩代码等操作
  3. 热更新(监听文件变化,自动打包)
  4. 具有开发服务器
webpack 和 vite 区别
  1. webpack支持多种模块化语法,commonjs规范 和 es6 module,会读取所有文件将模块化语法转换成统一的函数处理方式,因此项目大之后处理的就慢
  2. vite 只支持 es6 module 语法,且只针对浏览器应用的开发,因此不需要对所有文件进行模块化转换所以处理速度快

创建 vite 项目

使用 vite 脚手架创建项目

当初始化项目调用指令 npm create vite@latest 进行了如下操作

  1. 下载临时工具 create-vite(脚手架工具:此工具将保存在内存中)
  2. 并直接运行脚手架工具,通过其内置模板搭建项目结构和进行相关配置
  3. 手动调用 npm install【npm i】 通过 package.json 安装相关依赖,依赖中就包含 vite 构建工具
直接使用 vite 创建项目
  1. 先初始化项目 npm init
  2. vite 不需要进行额外配置,直接安装 vite 模块即可使用 npm i vite -D
  3. package.jsonscripts 中配置指令 "dev":"vite"
  4. 通过指令 npm run vite 启动 vite

依赖预构建

依赖预构建的-步骤

开发环境下,vite 在引入模块时,会对模块的相关依赖进行预构建,具体步骤如下:

  1. vite 先找到模块对应依赖,然后调用 esbuild,将其他模块语法转换成 ESModule 模块语法
  2. 并且对依赖中的多余引入进行过滤
  3. 并将编译后的模块放在 /node_modules/.vite/deps 目录下
  4. 然后搜索模块时默认会从这个目录下搜索
依赖预构建的-作用
  1. 统一模块语法:不同模块可能使用不同模块语法,都可以编译为 ESModule 模块语法在 vite 中使用
  2. 自动补全模块路径:可以使用模块名称进行引入,默认会补全路径,从 /node_modules/.vite/deps 目录下引入(es6语法中导入模块,只能使用 绝对路径相对路径
  3. 减少文件下载:因为过滤了多余依赖引用,因此减少了多种依赖的相关文件下载

vite命令

vite常用命令

  1. 启动开发服务器
    • vite servevite dev 命令等同于在控制台执行 vite
  2. 构建生产版本
    • vite build

命令参数

--mode xxx:用于指定 模式,即:指定 .env 开头的环境文件

如果不传 --mode 参数,默认 --mode 参数由命令类型决定

  1. 启动开发服务器-命令 :默认 --mode 值为 development
  2. 构建生产版本-命令 :默认 --mode 值为 production

开发配置


vite 语法提示配置

  1. 根目录创建文件 vite.config.js(vite 中的默认配置文件,也可自定义 vite --config my-config.js
  2. 对默认暴露对象(函数)进行相关配置(其他的相关配置都在此暴露对象(函数)中进行)
    1. 方法一:使用 defineConfig 工具函数
      1
      2
      3
      4
      5
      import { defineConfig } from 'vite'

      export default defineConfig({
      // ...
      })
    2. 方法二:通过 IDE 和 jsdoc 的配合
      1
      2
      3
      4
      /** @type {import('vite').UserConfig} */
      export default {
      // ...
      }

环境配置


基础配置

根据不同启动服务器命令(参数),来配置开发环境和生产环境

  1. vite.config.js 文件中,暴露的 必须是个函数。此函数返回值是个对象,对象中进行 vite 相关配置
  2. 暴露的函数有三个参数
    1. command :命令
      1. 参数值由 执行vite命令类型 决定
        1. vite servevite dev 命令等同于在控制台执行 vite,用于 启动开发服务器
        2. vite build,用于 构建生产版本
      2. 获取的值
        1. 启动开发服务器 传入参数为 serve
        2. 构建生产版本 传入参数为 build
    2. mode :模式
      1. 此参数传入的是 执行vite命令 时,携带的 --mode 参数的值 vite serve --mode xxx
      2. 用于指定环境文件的名称 .env.xxx
      3. 执行vite命令 不传 --mode 参数,获取的默认值如下:
        1. 启动开发服务器:默认值为 development
        2. 构建生产版本:默认值为 production
    3. ssr :SSR标志的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { defineConfig } from 'vite'

export default defineConfig(({ command, mode, ssrBuild }) => {
if (command === 'serve') {
return {
// dev 独有配置
}
} else {
// command === 'build'
return {
// build 独有配置
}
}
})

环境

  1. vite 中不同的环境由 .env 开头的文件决定【 全称 “environment”(环境)】
  2. .env 开头的环境文件,其中保存的是多个环境变量
  3. vite 默认环境文件名称
    • .env 文件默认是配置所有环境的环境变量
    • .env.development 文件默认是配置开发环境的环境变量
    • .env.production 文件默认是配置生产环境的环境变量

环境变量

根据当前代码环境的不同改变值的键值对就叫环境变量


载入环境变量

vite命令 和 loadEnv函数 加载环境变量的区别

  1. 都会默认加载 .env 环境文件中的环境变量
  2. vite 命令加载环境变量会放入 import.meta.env 中,浏览器环境中直接通过 import.meta.env 调用【import.meta.env 是只读的】
  3. loadEnv函数加载环境变量,需要在 define 配置项中进行配置,浏览器环境中通过配置的属性进行调用

通过 vite命令 加载环境变量

  1. 默认查找项目根目录下的 .env 文件,解析其中环境变量,放入 import.meta.env
  2. 根据命令的 --mode 参数值【包括默认值】,从项目根目录下查找补全的 .env.xxx 文件,并解析其中环境变量,放入 import.meta.env
1
2
3
4
5
// 执行命令
npx vite --mode xxx

// index.html .js
let env = import.meta.env

通过 loadEnv( )函数 加载环境变量

loadEnv( ) 函数说明

loadEnv( mode, envDir, prefixes )

  1. mode:确定要加载的 .env 文件的名称
    1. 通过 vite.config.js 暴露的函数的 mode 参数获取
    2. 根据控制太 执行vite命令 后面的参数 --mode xxx 进行拼接生成文件全称 .env.xxx
  2. envDir:确定要加载的 .env 文件的目录
    1. 使用 node.js 中的全局对象 process 可以获取当前进程的相关信息
    2. process.cwd() 自动获取当前所在目录地址
    3. 也可以自定义目录地址 /xx/xx/xx
  3. prefixes:过滤环境变量,只保留指定前缀的环境变量
    1. 默认不传:前缀为 VITE_
    2. 值为字符串或字符串数组
    3. 在vite.config.js 暴露对象中配置 envPrefix="xxx_" 可以指定环境变量的默认前缀(以 xxx_开头的变量名称)
loadEnv( ) 函数载入环境变量过程
  1. 直接查找项目根目录下的 .env 文件,解析其中环境变量,放入一个对象
  2. 根据三个参数查找 .env 开头的环境变量文件,解析其中环境变量,放入同一个对象【重复的被替换】
  3. 并将此对象作为返回值
  4. 将此对象配置到 define 配置项中,即可以在浏览器环境任何地方调用此中 环境变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // ---------------vite.config.js

    import { defineConfig, loadEnv } from 'vite'

    export default defineConfig(({ command, mode }) => {

    // 根据 vite 命令的 --mode 参数加载 .env 文件
    // let env = loadEnv(mode,process.cwd(),"")

    // 自定义加载的 .env 环境文件
    let env = loadEnv("test",process.cwd(),"") // 加载解析 .env.test 环境文件,并返回环境变量对象

    // 使用 `env` 中的值来配置插件等
    return {
    define: { // 配置 loadEnv 返回的环境变量对象
    'myEnv': env, // 浏览器中通过直接通过变量名 myEnv 调用环境变量
    },
    }
    })

    // -----------------浏览器环境
    config.log("获取环境变量",myEnv)

浏览器获取环境变量

通过 vite 命令加载的环境变量,浏览器环境中通过 import.meta.env 获取

1
console.log("获取环境变量",import.meta.env.VITE_XXX)

通过 loadEnv 函加载的环境变量,浏览器环境中通过 define 配置的属性获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// ---------------vite.config.js

import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ command, mode }) => {
// console.log("xxxxxxx",process.env)
// 根据当前工作目录中的 `mode` 加载 .env 文件

let env = loadEnv("test",process.cwd(),"")
console.log("xxxxxxxxxx",process.env.VITE_CC)
console.log("yyyyyyyyyy",__APP_ENV__)

// 使用 `env` 中的值来配置插件等
return {
// ...
define: {
'myEnv': env,
},
}
})

// -----------------浏览器环境
config.log("获取环境变量",myEnv)

CSS 处理


postcss

postcss 是一个css后处理工具,用于对 lessscss 编译后的css语法进行兼容性降级或添加前缀等工作

vite.config.js 中配置

1
2
3
4
5
6
7
8
9
10
11
12
import { defineConfig } form "vite"

const postcssPresetEnv = require("postcss-preset-env"); // 引入预处理插件

export default defineConfig({
css:{
postcss:{
// plugins:[postcssPresetEnv] // 两种方式均可
plugins:[postcssPresetEnv({...})] // 添加规则,参数中可以进行额外配置
}
}
})

postcss.config.js

项目根目录下,重新创建一个 postcss.config.js 文件,在此文件中进行配置

1
2
3
4
5
6
const postcssPresetEnv = require("postcss-preset-env"); // 引入预处理插件

module.exports = {
// plugins:[postcssPresetEnv] // 两种方式均可
plugins:[postcssPresetEnv({...})] // 添加规则,参数中可以进行额外配置
}

加载静态资源

vite 对静态资源可以直接使用,静态资源默认放在 assets 目录下(非必须)


json文件

  1. 在 vite 中,通过 import 加载的 json 文件内容直接作为 object 对象,而不是 json 字符串,免去了字符串转换过程
  2. 可以只导入 json 文件中某属性
1
2
3
4
5
import filname from "./src/assets/json/xxx.json"    // 通过 import 加载json文件中对象
import { name1,name2 } from "./src/assets/json/xxx.json" // 通过 import 加载 json 文件中某属性

console.log("josn文件:",filname,name1) // 直接获取json对象


图片文件

  1. 直接使用 import 加载图片,获取的是静态资源图片的绝对路径地址(即默认形式:?url)
  2. 图片地址用 ?raw 结尾,获取的是 Buffer 二进制字符串
1
2
3
4
import imgname from "./src/assets/img/xxx.jpg"    // 通过 import 加载照片,获取图片绝对路径地址
import imgname from "./src/assets/img/xxx.jpg?raw" // 通过 import 加载照片,获取图片的 buffer 二进制字符串

document.getElementByid("img").src = imgname; // 直接使用图片地址

svg文件

svg 是一种新的图片格式,是一种矢量图,有不会失真体积小的特点

  1. 直接使用 import 加载 svg 图片,获取的是静态资源图片的绝对路径地址(即默认形式:?url)
  2. 图片地址用 ?raw 结尾,获取的是 svg 文件中的字符串,可以将获取的字符串直接插入页面,也可以显示图片
1
2
3
4
5
6
7
8
import svgname from "./src/assets/img/xxx.svg"    // 通过 import 加载照片,获取图片绝对路径地址
import svgname from "./src/assets/img/xxx.svg?raw" // 通过 import 加载照片,获取 svg 文件的内容

document.getElementByid("img").src = imgname; // 直接使用图片地址

let svg = document.getElementByid("mydiv")
svg.innerHTML = svgname // 直接将文件内容字符串插入页面,即可显示图片
svgname.style.fill = "red" // 修改 style.fill 可以改变颜色

地址别名

  1. 给指定路径定义别名,简化地址的引用
  2. vite.config.js 文件中 resolve.alias 进行配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { defineConfig } from "vite"
import path from "path" // 获取路径的函数

export default defineConfig({
resolve:{
alias:{
"@":path.resolve("__dirname","./"), // 将根目录路径定义为 @
"@assets":path.resolve("__dirname","./src/assets") // 将目录 ./src/assets 定义为别名 @assets
}
}
})

// 其他页面引入
import imgname from "@assets/img/xxx.jpg"

配置生产环境资源

对打包后的资源进行配置

配置打包到指定目录下
  1. vite.config.js 文件中进行配置
  2. build.outdir 进行配置
1
2
3
4
5
6
7
import { defineConfig } from "vite"

export default defineConfig({
build:{
outDir:"testDist" // 将默认打包目录名改为 testDir
}
})
配置打包后静态文件所在目录
  1. vite.config.js 文件中进行配置
  2. build.assetsDir 进行配置
1
2
3
4
5
6
7
import { defineConfig } from "vite"

export default defineConfig({
build:{
assetsDir:"testAssets" // 将打包后静态文件目录改为 testAssets
}
})

与 TS 的结合

在打包阶段检查代码使用命令 tsc --noEmit && vite build

  1. && 前面的命令执行失败,&& 后面的命令不执行(将不会进行打包)
  2. tsc --noEmit 在打包阶段检查错误
1
npx tsc --noEmit && vite build

构建优化


分包策略

将指定文件在独立的 .js 文件中生成
只要文件内容更改,打包后的文件 hash 名称也会更改,因此浏览器请求时就会重新加载
如果将某些不常改动的文件独立打包,浏览器请求时就不会重新加载了,减少请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineConfig } from "vite"

export default defineConfig({
build:{
rollupOptions:{
output:{
manualChunks:(url)=>{ // 每个文件都会执行一次,获取到的是文件的绝对路径
if(url.includes("node_modules")){ // 文件路径的字符串中包含 node_modules 则独立打包
return "vendor" // 打包后文件名以 vendor 开头
}
}
}
}
}
})

gzip 压缩

浏览器请求服务端,获取的是一个压缩包,浏览器获取到之后进行解压缩获取其中文件

  1. 引入插件 vite-plugin-compression
  2. vite.config.js 进行配置
  3. 后端返回 .gz 压缩包,在响应头配置 content-encoding:gzip
  4. 浏览器获取到 .gz 压缩包,会自动进行解压
1
2
3
4
5
6
7
import viteCompression from "vite-plugin-compression"

export default ()=>{
return {
plugins:[viteCompression()]
}
}

动态导入组件

是 ES6 的一个新语法,常用作路由配置,不用一次性导入所有组件

1
2
3
4
5
6
const routes = [
{
path:"/home",
component:import("./xx/home") // 动态导入组件
}
]

CDN加速

CND 全称 内容分发网络,vite 中通过插件 vite-plugin-cdn-import 从 CDN 上导入模块(js文件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import viteCDNPlugin from "vite-plugin-cdn-import"
import { defineConfig } from "vite"

export default defineConfig({
plugins:[
viteCDNPlugin({
modules:[
{
name:"lodash", // 模块的名称
var:"_", // 赋予模块的导出对象,等同于 import _ from "lodash"
path:"https://cdn.xxx.net/xxx/xx/xxx.js" // 文件在 cnd 的地址
}
]
})
]
}

跨域

开发阶段通过开启代理服务器解决跨域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { defineConfig } from "vite"

export default defineConfig({
plugins:[
server:{ // 开启服务器
proxy:{ // 配置代理
"/api":{ // 配置以 /api 开头的请求
target:"https://www.360.com", // 要请求的地址
changeOrigin:true,
rewrite:(path) => path.replace(/^\/api/,"") // 是否要重写 /api 地址
}
}
}
]
}