Vite该如何使用?Vite学习笔记,持续记录

Vite学习记录

配置文档:https://cn.vitejs.dev/config/,基于ESM;

插件大全:https://github.com/vitejs/awesome-vite

构建工具常用插件
esbuild,eslint,stylelint,prettier,terser,babel,profill,rollup,.editorconfig

通过插件支持低版本浏览器:https://github.com/vitejs/vite/tree/main/packages/plugin-legacy

1.vite使用scss

Vite使用scss预处理器:npm install sass -D,安装后可直接使用。

官方文档:https://cn.vitejs.dev/guide/features.html#css-pre-processors

2.将 js 模块当做 url 导入

如果我们只是想获取脚本的url,不想导入脚本,可以通过在导入路径后添加?url后缀。

import asyncUrl from './async_demo.js?url';
console.log(asyncUrl); /*/importassets/async_demo.js*/
if (true) {
    import(/* @vite-ignore */asyncUrl).then(m => {
        console.log(m) // Module {Symbol(Symbol.toStringTag): "Module"}
    });
}

// 做字符串引入
import shaderString from './shader.glsl?raw'

相关文档:https://zhuanlan.zhihu.com/p/401882229

4.定义一个目录的别名

 /*引入path模块*/
import path from 'path'

/*解析生成指定目录的完整目录*/
function resolve(dir) {
    return path.join(__dirname, dir);
}

/*定义vite的配置*/
export default defineConfig({
    resolve:{
          alias:{
              '@':resolve('src')
          }
    }

})

5.vite编译说明

运行过程中依赖的一些文件会保存在node_modules/.vite文件夹里,有时候出现一些莫名的问题,可以尝试删除这个目录,重新运行试试。

vite配置项

1.常用配置项

  1. root,指定项目根目录。
  2. build.outDir,指定编译的输出目录(相对于根目录)
  3. build.assetsDir,编译后静态文件存放的目录(相对于输出目录)

2.vite配置babel

Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码。注意:Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API。有的同学可能分不清哪些是ES6句法,哪些是API,这个暂时先放一放,后面会讲。

Polyfill的准确意思为,用于实现浏览器并不支持的原生API的代码。

在构建生产时不支持本机 ESM 的旧版浏览器提供支持:https://github.com/vitejs/vite/tree/main/packages/plugin-legacy,插件将进行如下操作:

  • 为最终包中的每个块生成相应的遗留块,使用@babel/preset-env转换并作为SystemJS 模块发出(仍然支持代码拆分!)。
  • 生成一个 polyfill 块,包括 SystemJS 运行时,以及由指定的浏览器目标和包中的实际使用确定的任何必要的 polyfill 。
  • 将标签注入<script nomodule>生成的 HTML 以有条件地仅在没有原生 ESM 支持的浏览器中加载 polyfill 和遗留包。
  • 注入import.meta.env.LEGACYenv 变量,它只会true在旧版生产版本中,false在所有其他情况下。

vite.config.js配置如下,将自动生成babel、profill之后的代码:

import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
    plugins: [
        legacy({
            targets: ['defaults', 'not IE 11']
        })
}

3.vite build 构建选项(支持的ES语法、babel、profill)

  1. build.target,设置最终构建的浏览器兼容目标。默认值是一个 Vite 特有的值——'modules',这是指 支持原生 ES 模块的浏览器。
  2. build.polyfillModulePreload,如果设置为 true,此 polyfill 会被自动注入到每个 index.html 入口的 proxy 模块中。
  3. build.outDir,打包后的资源输出输出目录。、
  4. build.assetsDir,,相对于 build.outDir指定生成静态资源的存放路径。
  5. build.assetsInlineLimit,小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0 可以完全禁用此项。
  6. build.cssCodeSplit,启用/禁用 CSS 代码拆分。当启用时,在异步 chunk 中导入的 CSS 将内联到异步 chunk 本身,并在其被加载时插入。如果禁用,整个项目中的所有 CSS 将被提取到一个 CSS 文件中。
  7. build.minify,设置为 false 可以禁用最小化混淆,或是用来指定使用哪种混淆器。默认为 Esbuild,它比 terser 快 20-40 倍,压缩率只差 1%-2%。
  8. build.terserOptions,传递给 Terser 的更多 minify 选项。

4.同require.context()一样的API(批量导入)

const files = require.context('.', false, /.ts$/);
const modules = {};
files.keys().forEach((key) => {
  if (key === './index.ts') { return; }
  modules[key.replace(/(./|.ts)/g, '')] = files(key).default;
});
export default modules;

官方文档:https://cn.vitejs.dev/guide/features.html#glob-import

4.1 import.meta.glob

Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块:

const modules = import.meta.glob('./dir/*.js')

// vite 生成的代码
const modules = {
  './dir/foo.js': () => import('./dir/foo.js'),
  './dir/bar.js': () => import('./dir/bar.js')
}
提示
Vite3.0已支持传递数组进行批量导入

匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk。

const modules = import.meta.globEager('./dir/*.js')

// vite 生成的代码
import * as __glob__0_0 from './dir/foo.js'
import * as __glob__0_1 from './dir/bar.js'
const modules = {
  './dir/foo.js': __glob__0_0,
  './dir/bar.js': __glob__0_1
}

使用globEager直接引入所有的模块。

5.vite使用PostCss

Vite自身已经集成PostCSS,无需再次安装。另外也无需单独创建PostCSS配置文件,已集成到vite.config.js的css选项中。可直接配置css.postcss选项即可。Vite将自动在*.vue文件中所有的style标签以及所有导入的.css文件中应用PostCSS.

6.导入全局的scss、less样式

export default defineConfig({
  plugins: [vue()],
  css: {
    // css预处理器
    preprocessorOptions: {
      scss: {
      // 此处修改为要被预处理的scss文件地址
        additionalData: '@import "./src/index.scss";'
      }
    }
  }
})
注意
在scss文件中的图片或者字体地址路径尽量使用绝对地址,不然文件可能会找不到。

7.vite配置rollup进行代码拆分

rollup官网:https://www.rollupjs.com/

export default defineConfig({
    build: {
        outDir: "dist",
        rollupOptions: {
            output: {
                manualChunks(id) {
                    if (id.includes('node_modules')) {
                        return id.toString().split('node_modules/')[1].split('/')[0].toString();
                    }
                },
                chunkFileNames: 'assets/js/[name]-[hash].js',
                entryFileNames: 'assets/js/[name]-[hash].js',
                assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
            }
        }
    }
});

7.vite配置terser

build.minify,默认为 Esbuild,它比 terser 快 20-40 倍,压缩率只差 1%-2%。

terser库,用于处理 js 的压缩和混淆 ,官网:https://terser.org/,vite配置如下:

export default defineConfig({
    build:{
        minify: "terser",
        terserOptions:{
            compress: {
                drop_console: true, //去掉所有console
                drop_debugger: true //去掉所有debugger
            }
        }
    }
})
提示
vite3 默认未安装terser,使用之前需手动安装

8.build.cssTarget

默认值与 build.target 一致,此选项允许用户为 CSS 的压缩设置一个不同的浏览器 target,此处的 target 并非是用于 JavaScript 转写目标。

应只在针对非主流浏览器时使用。 最直观的示例是当你要兼容的场景是安卓微信中的 webview 时,它支持大多数现代的 JavaScript 功能,但并不支持 CSS 中的 #RGBA 十六进制颜色符号。 这种情况下,你需要将 build.cssTarget 设置为 chrome61,以防止 vite 将 rgba() 颜色转化为 #RGBA 十六进制符号的形式。

9.build.sourcemap

Sourcemap的作用 简单说Sourcemap构建了处理前以及处理后的代码之间的一座桥梁,方便定位生产环境中出现bug的位置。因为现在的前端开发都是模块化、组件化的方式,在上线前对 js 和 css 文件进行合并压缩容易造成混淆。如果对这样的线上代码进行调试,肯定不切实际,sourceMap的作用就是能够让浏览器的调试面版将生成后的代码映射到源码文件当中,开发者可以在源码文件中 debug,这样就会让程序员调试轻松、简单很多。

build.sourcemap,构建后是否生成 source map 文件。如果为 true,将会创建一个独立的 source map 文件。如果为 'inline',source map 将作为一个 data URI 附加在输出文件中。'hidden' 的工作原理与 'true' 相似,只是 bundle 文件中相应的注释将不被保留。

10.build.cssCodeSplit

默认: true,启用/禁用 CSS 代码拆分。当启用时,在异步 chunk 中导入的 CSS 将内联到异步 chunk 本身,并在其被加载时插入。如果禁用,整个项目中的所有 CSS 将被提取到一个 CSS 文件中。

12.server

  1. host,监听的IP地址
  2. port,监听的端口
  3. https,是否启用https
  4. cors,是否允许跨域
  5. force,强制依赖预构建
  6. hmr,配置热更新的ws服务器({ protocol?: string, host?: string, port?: number, path?: string, timeout?: number, overlay?: boolean, clientPort?: number, server?: Server })
  7. proxy,配置代理,https://cn.vitejs.dev/config/server-options.html#server-proxy

13.让IDE识别Vite配置的别名

在项目根目录下的tsconfig.json,或者jsconfig.json添加如下代码,没有这两个文件就新建一个,添加完成后等待编辑器自动识别即可。

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Vite环境变量和模式

官方文档:https://cn.vitejs.dev/guide/env-and-mode.html

1.环境变量

Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量:

  • import.meta.env.MODE: {string} 应用运行的模式。
  • import.meta.env.BASE_URL: {string} 部署应用时的基本 URL。他由base 配置项决定。
  • import.meta.env.PROD: {boolean} 应用是否运行在生产环境。
  • import.meta.env.DEV: {boolean} 应用是否运行在开发环境 (永远与 import.meta.env.PROD相反)。
  • import.meta.env.SSR: {boolean} 应用是否运行在 server 上。

在生产环境中,这些环境变量会在构建时被静态替换,因此,在引用它们时请使用完全静态的字符串。动态的 key 将无法生效。例如,动态 key 取值 import.meta.env[key] 是无效的。

2.env 文件

Vite 使用 dotenv 从环境目录中的下列文件加载额外的环境变量:

.env                # 所有情况下都会加载
.env.local          # 所有情况下都会加载,但会被 git 忽略
.env.[mode]         # 只在指定模式下加载
.env.[mode].local   # 只在指定模式下加载,但会被 git 忽略
环境加载优先级
一份用于指定模式的文件(例如 .env.production)会比通用形式的优先级更高(例如 .env)。

另外,Vite 执行时已经存在的环境变量有最高的优先级,不会被 .env 类文件覆盖。例如当运行 VITE_SOME_KEY=123 vite build 的时候。

.env 类文件会在 Vite 启动一开始时被加载,而改动会在重启服务器后生效。

加载的环境变量也会通过 import.meta.env 以字符串形式暴露给客户端源码。

为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。例如下面这个文件中:

VITE_SOME_KEY=123
DB_PASSWORD=foobar

只有 VITE_SOME_KEY 会被暴露为 import.meta.env.VITE_SOME_KEY 提供给客户端源码,而 DB_PASSWORD 则不会。

console.log(import.meta.env.VITE_SOME_KEY) // 123
console.log(import.meta.env.DB_PASSWORD) // undefined

如果你想自定义 env 变量的前缀,请参阅 envPrefix

安全注意事项
.env.*.local 文件应是本地的,可以包含敏感变量。你应该将 .local 添加到你的 .gitignore 中,以避免它们被 git 检入。

由于任何暴露给 Vite 源码的变量最终都将出现在客户端包中,VITE_* 变量应该不包含任何敏感信息。 

问题记录

1.打包时不压缩js

打包压缩后的js代码是非常难以阅读的,有时候我们可能需要保留原始代码,修改vite.config.js配置如下:

{
   build:{
       minify:false
   }
}

库开发 

库开发:https://cn.vitejs.dev/config/build-options.html#build-lib

Vite实用插件

1.vite-plugin-restart

作用:通过监听文件修改,自动重启 vite 服务。(现在vite好像自带修改配置后自动重启功能了)

最常用的场景就是监听 vite.config.js 和 .env.development 文件,我们知道,修改 vite 配置文件和环境配置文件,是需要重启 vite 才会生效,通过这个插件,我们将从反复重启中解脱出来。

项目地址:https://github.com/antfu/vite-plugin-restart

npm i vite-plugin-restart -D

vite.config.js配置如下:

// vite.config.js
import ViteRestart from 'vite-plugin-restart'
//Changes to my.config.js or my.config.ts will now restart the server automatically.
export default {
  plugins: [
    ViteRestart({
      restart: [
        'my.config.[jt]s',
      ]
    })
  ],
};

2.unplugin-vue-components

作用:组件自动按需导入。

项目地址:https://github.com/antfu/unplugin-vue-components

npm i unplugin-vue-components -D

vite.config.js配置如下:

import Components from 'unplugin-vue-components/vite'
// ui库解析器,也可以自定义,需要安装相关UI库,unplugin-vue-components/resolvers
// 提供了以下集中解析器,使用的时候,需要安装对应的UI库,这里以vant示例
// 注释的是包含的其他一些常用组件库,供参考
import {
  // ElementPlusResolver,
  // AntDesignVueResolver,
  VantResolver,
  // HeadlessUiResolver,
  // ElementUiResolver
} from 'unplugin-vue-components/resolvers'

export default  ({ mode }) => defineConfig({
  plugins: [
    Components({
      dirs: ['src/components'], // 目标文件夹
      extensions: ['vue','jsx'], // 文件类型
      dts: 'src/components.d.ts', // 输出文件,里面都是一些import的组件键值对
      // ui库解析器,也可以自定义,需要安装相关UI库
      resolvers: [
        VantResolver(),
        // ElementPlusResolver(),
        // AntDesignVueResolver(),
        // HeadlessUiResolver(),
        // ElementUiResolver()
      ],
    })
  ]
})

3.vite-plugin-style-import

作用:当你使用unplugin-vue-components来引入ui库的时候,message, notification,toast 等引入样式不生效。安装vite-plugin-style-import,实现message, notification,toast 等引入样式自动引入

npm i vite-plugin-style-import -D

vite.config.js配置如下:

import {
  createStyleImportPlugin,  
  // AndDesignVueResolve,
  VantResolve,
  // ElementPlusResolve,
  // NutuiResolve,
  // AntdResolve
} from 'vite-plugin-style-import'

export default  ({ mode }) => defineConfig({
  plugins: [
      createStyleImportPlugin({
            resolves: [VantResolve()],
        })
  ]
})

自定义动态引入:

createStyleImportPlugin({
    resolves: [ {
        libraryName: "vant",
        esModule: true,
        /*
        * 更新之后目录变了,.. 回到上层目录
        * 根目录/,是项目根目录,“/.node_modules绝对路径去指定也行”
        * */
        resolveStyle: (name) => {
            return `../es/${name}/style`;
        }
    }],
}),

4.@vitejs/plugin-vue-jsx

作用:此插件支持在vue3中使用jsx/tsx语法

npm i @vitejs/plugin-vue-jsx

5.vite-plugin-vue-setup-extend

作用:setup语法糖name增强,使vue3语法糖支持name属性。vue3语法糖默认是没有name属性的,在我们使用keep-alive的时候需要用到name。

npm i vite-plugin-vue-setup-extend -D

vite.config.js配置如下:

import { defineConfig} from 'vite'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
export default  ({ mode }) => defineConfig({
  plugins: [
    vueSetupExtend()
  ]
}

SFC中使用:

<script setup lang="ts" name="home">
</script>

5.vite-plugin-cdn-import

作用:用于从 CDN 导入模块

项目地址:https://www.npmjs.com/package/vite-plugin-cdn-import

npm install vite-plugin-cdn-import --save-dev

vite.config.js配置如下(使用cdn的同时也需要安装这个软件包,在打包的时候将会自动替换):

import importToCDN, {autoComplete} from 'vite-plugin-cdn-import'
//支持自动导入部分软件包
export default defineConfig({
    plugins: [
        createVuePlugin(),
        importToCDN({
            modules: [
                autoComplete('vue2'),
            ]
        })
    ]
}

6.@vitejs/plugin-legacy

作用:Vite默认的浏览器支持基线是原生ESM。该插件为不支持原生ESM的传统浏览器提供支持。

项目地址:https://github.com/vitejs/vite/tree/main/packages/plugin-legacy

7.@vitejs/plugin-vue

作用:用于支持vite进行vue开发,安装vite时同步安装

import vue from '@vitejs/plugin-vue';
export default defineConfig({
  plugins: [
    vue()
  ]
})

8.unplugin-auto-import

作用:自动引入开发过程中需要使用的API

项目地址:https://github.com/antfu/unplugin-auto-import

npm i -D unplugin-auto-import

vite.config.js 配置如下:

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    AutoImport(
       { 
      imports: ['vue', '@vueuse/core'], //需要自动引入的包
      resolvers: [
        ElementPlusResolver(), //支持组件库自动引入
      ],
      dirs: [
        './composables', //配置文件生成位置
      ],
      dts: './auto-imports.d.ts',//生成文件路径
      vueTemplate: true, //Auto import inside Vue template,
      ...
    }
    ),
  ],
})

9.vite-plugin-vue2

作用:支持在vite上使用vue2.x进行开发。

项目地址:https://github.com/underfin/vite-plugin-vue2

npm install vite-plugin-vue2 -D

vite.config.js配置如下:

// vite.config.js
import { createVuePlugin } from 'vite-plugin-vue2'

export default {
  plugins: [
    createVuePlugin(/* options */)
  ],
}

除此之外,在安装vite的时候选择原生开发(vanilla),然后继续安装:

$ npm install vue@2.x  #安装vue2.x版本
# 2.x版本编译器:https://www.npmjs.com/package/vue-template-compiler
$ npm install vue-template-compiler

10.vite-plugin-inspect

作用:在使用、开发vite插件时,查看插件的中间状态

项目地址:https://www.npmjs.com/package/vite-plugin-inspect

vite.config.js 配置如下:

// vite.config.ts 
import  Inspect  from  'vite-plugin-inspect' 

export  default  { 
  plugins : [ 
    Inspect ( ) ,  // 仅适用于开发模式
  ] , 
}

然后访问localhost:3000/__inspect/来检查模块。

11.vite-plugin-compression

项目地址:https://github.com/vbenjs/vite-plugin-compression/blob/main/README.zh_CN.md

vite.config.js配置如下:

import viteCompression from 'vite-plugin-compression';

export default defineConfig({
    plugins: [
        viteCompression()
    ]
})

12.vite-plugin-html

vite-plugin-html用于压缩打包后的html,以及注入指定的data数据。

项目地址:https://github.com/vbenjs/vite-plugin-html

13.vite-plugin-imagemin

用于压缩项目内的图片资源。

项目地址:https://github.com/vbenjs/vite-plugin-imagemin/blob/main/README.zh_CN.md

14.vite-plugin-wasm

提供对wasm模块导入的支持。

项目地址:https://www.npmjs.com/package/vite-plugin-wasmhttps://github.com/Menci/vite-plugin-wasm

15.vite-plugin-top-level-await

vite-plugin-top-level-await用于支持top-level-await特性

16.vite-plugin-css-injected-by-js

用于打包的时候将css打包到js文件中。

项目地址:https://github.com/Marco-Prontera/vite-plugin-css-injected-by-js

cssInjectedByJsPlugin()