1、vite快速入门
- vite 处理 css 资源无需配置,直接导入 css 资源即可。
- vite 处理 less 资源,只需安装 less即可,无需配置,导入 less 资源即可。
- vite 处理 scss 资源,只需安装 sass 即可,无需配置,导入 scss 资源即可。
- vite 处理 stylus 资源,只需安装 stylus 即可,无需配置,导入 stylus 资源即可。
- vite 处理样式的浏览器前缀,需安装 postcss 和 post-preset-env,配置 postcss.config.js 即可。
// 安装依赖
npm install -D postcss post-preset-env
// postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')
]
}
- vite 处理 ts 资源无需配置,直接导入使用即可。
- vite 处理图片资源无需配置,直接导入使用即可。
- vite 处理 .vue 单文件组件。需要安装 @vitejs/plugin-vue ,并配置 vite.config.js。
// 安装依赖
npm isntall -D vue
npm install @vitejs/plugin-vue -D
// 配置 vite.config.js
import vue from '@vitejs/plugin-vue'
export default {
plugins: [
vue()
]
}
// 如果报错 Error: Cannot find module 'node:xx' , 则配置 package.json。
{
"type": "module"
}
//如果报错 [vite] Internal server error: Failed to load PostCSS config,则配置 postcss.config.js。
//修改 postcss.config.js -> postcss.config.cjs
- dev server:利用浏览器的ESM能力来提供源文件,具有丰富的内置功能并具有高效的HMR
- 生产构建:生产环境利用Rollup来构建代码,提供指令用来优化构建过程
2、vite中封装svg组件
// 1.安装:vite-plugin-svg-icons
// 2.vite.config.js中配置plugins
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
// 要缓存的图标文件夹
iconDirs: [path.resolve(__dirname, '../common/svgIcon/assets')],
// 执行 icon name 的格式
symbolId: 'icon-[name]'
})
]
}
// 3.编写svgIcon组件和批量导入代码
// 批量导入所有svg文件
import SvgIcon from './index.vue'
const files = import.meta.globEager('./assets/*.svg') // vite
const modules = {}
const requireAll = (files) => {
for (const key in files) {
if (Object.prototype.hasOwnProperty.call(files, key)) {
modules[key.replace(/(\.\/|\.svg)/g, '')] = files[key].default
}
}
}
requireAll(files)
export function registerSvgIconComp(app) {
app.component('SvgIcon', SvgIcon)
}
// 4.main.ts中执行批量到代码和vite-plugin-svg-icons
import { registerSvgIconComp } from '@rootCommon/svgIcon/svgIcon.ts'
import 'virtual:svg-icons-register'
// ...
registerSvgIconComp(app)
// 4.如果报错找不到fast-glob插件,安装插件
3、vite中动态导入
- 问题:vite中使用import(‘xx/xx.vue’)在dev模式正常,但是build时,会报错,需要改成import.meta.glob动态导入
- 方案:使用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')
}
// 支持多个路径导入
const modules = import.meta.glob(['./dir/*.js', './dir/*/*.js'])
4、vite模块联邦
- 使用vite-plugin-federation插件实现模块联邦,可以与 Webpack Module Federation 兼容,参考。
- 使用
- 步骤一:Remote端配置暴露的模块
此处ams-demo即为Remote端配置
// ams-demo的vite.config.js import federation from "@originjs/vite-plugin-federation"; export default { plugins: [ federation({ name: 'ams-demo', filename: 'remoteEntry.js', // 需要暴露的模块 exposes: { './Button': './src/Button.vue', './GswbjjList': './src/views/gswbjj/index.vue', './GswbjjAdd': './src/gswbjj/addView.vue', './FundOrg': './src/fund/index.vue' }, remotes: {}, shared: ['vue'] }) ] }
- 步骤二:Host端配置远程模块入口
此处ams-base即为Host端
// vite.config.js import federation from "@originjs/vite-plugin-federation"; export default { plugins: [ federation({ name: 'host-app', // 依赖的远程模块 remotes: { // 注意:remotes对象的key为字符串 'ams-demo': 'http://localhost:8002/assets/remoteEntry.js' }, shared: ['vue'] }) ] }
- 步骤三:Host端使用远程模块
<template> <div class="page-view home-page"> <!-- 测试vite模块联邦:<RemoteButton /> --> <RemoteButton /> </div> </template> <script> import { defineComponent } from 'vue' import RemoteButton from 'ams-demo/Button' export default defineComponent({ name: 'Home' components: { RemoteButton } }) </script>
- 运行:1.对所有remote执行yarn build,然后yarn preview;对host执行yarn dev,即可在host中使用remote的组件
- 步骤一:Remote端配置暴露的模块
- 使用限制:
- remote只有build & preview模式运行才能被host读取到remoteEntry.js,无法在双方都处于dev模式进行模块联邦使用。
- Vite 使用 Webpack 组件相对容易,但是 Webpack 使用 vite-plugin-federation 组件时最好使用 esm 格式,因为其他格式暂时缺少完整的测试用例
5、打包报 Top-level await is not available in the configured target environment
- 问题:「ECMAScript」提案 Top-level await 由 Myles Borins 提出,它可以让你在模块的最高层中使用 await 操作符。在这之前,你只能通过在 async 函数或 async generators 中使用 await 操作符。Top-level await 是个新特性,打包不支持此特性
- 方案:引入vite-plugin-top-level-await
npm install vite-plugin-top-level-await -D
// 在vite.config.js配置此插件
import topLevelAwait from 'vite-plugin-top-level-await'
export default defineConfig({
plugins: [
topLevelAwait({
// The export name of top-level await promise for each chunk module
promiseExportName: '__tla',
// The function to generate import names of top-level await promise in each chunk module
promiseImportName: i => `__tla_${i}`
})
]
})
6、vite中不支持require
- 问题:报错ReferenceError: require is not defined
- 解决方案:使用vite-plugin-require-transform
import requireTransform from 'vite-plugin-require-transform'
export default defineConfig({
plugins: [
vue(),
requireTransform({
// 支持require
fileRegex: /.js$|.vue$/
})
],
// ...
}
7、vite打包报错:“default“ is not exported by “node_modules/…
- 原因:vite不支持commonjs语法,需要使用@rollup/plugin-commonjs插件,用于将CommonJS模块转换为ES6模块的Rollup插件
- 解决方案:使用@rollup/plugin-commonjs插件
import commonjs from '@rollup/plugin-commonjs'
export default defineConfig({
plugins: [
commonjs(),
vue(),
// ...
}
8、vite中处理less全局变量
9、vite.config.ts详细配置
//vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
export default defineConfig({
//项目根目录
root: process.cwd(),
//项目部署的基础路径
base: "/",
//环境配置 'development'|'production'
mode: "development",
//全局常量替换 Record<string, string>
define: {
"": "",
user: "users",
},
//插件
plugins: [vue()],
//静态资源服务的文件夹
publicDir: "public",
//存储缓存文件的目录
cacheDir: "node_modules/.vite",
resolve: {
//别名
alias: {
"@": path.resolve(__dirname, "/src"),
comps: path.resolve(__dirname, "/src/components"),
},
dedupe: [],
//解决程序包中package.json配置中的exports 字段
conditions: [],
//解析package.json中字段的优先级
mainFields: ["module", "jsnext:main", "jsnext"],
//导入时想要省略的扩展名列表
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json"],
//使Vite通过原始文件路径而不是真正的文件路径确定文件身份
preserveSymlinks: false,
},
css: {
//配置 CSS modules 的行为。选项将被传递给 postcss-modules。
modules: {},
// PostCSS 配置(格式同 postcss.config.js)
// postcss-load-config 的插件配置
postcss: {},
//指定传递给 CSS 预处理器的选项
preprocessorOptions: {
scss: {
additionalData: `$injectedColor: orange;`,
},
},
//开发过程中是否启sourcemap
devSourcemap: false,
},
json: {
//是否支持从 .json 文件中进行按名导入
namedExports: true,
//若设置为 true,导入的 JSON 会被转换为 export default JSON.parse("...") 会比转译成对象字面量性能更好,
stringify: false,
},
//继承自 esbuild 转换选项。最常见的用例是自定义 JSX
esbuild: {
jsxFactory: "h",
jsxFragment: "Fragment",
jsxInject: `import React from 'react'`,
},
//静态资源处理 字符串|正则表达式
assetsInclude: ["**/*.gltf"],
//调整控制台输出的级别 'info' | 'warn' | 'error' | 'silent'
logLevel: "info",
//设为 false 可以避免 Vite 清屏而错过在终端中打印某些关键信息
clearScreen: true,
//加载 .env 文件的目录
envDir: "",
//envPrefix开头的环境变量会通过import.meta.env暴露客户端源码
envPrefix: "VITE_",
//设置'spa' | 'mpa' | 'custom'应用操作
appType: "spa",
//服务
server: {
//服务器主机名
host: "localhost",
//端口号
port: "5173",
//设为 true 时若端口已被占用则会直接退出,而不是尝试下一个可用端口
strictPort: true,
//https.createServer()配置项
https: "",
//服务器启动时自动在浏览器中打开应用程序。
open: "/docs/index.html",
//自定义代理规则
proxy: {
// 字符串简写写法
"/foo": "http://localhost:4567",
// 选项写法
"/api": {
target: "http://jsonplaceholder.typicode.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
// 正则表达式写法
"^/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' 的实例
},
},
// Proxying websockets or socket.io
"/socket.io": {
target: "ws://localhost:3000",
ws: true,
},
},
//开发服务器配置 CORS
cors: {},
//指定服务器响应的 header ,类型OutgoingHttpHeaders
header: {},
//禁用或配置 HMR 连接
hmr: {},
//传递给 chokidar 的文件系统监视器选项
watch: {},
//中间件模式创建 Vite 服务器,'ssr' | 'html'
middlewareMode: "ssr",
//HTTP请求中预留此文件夹,用于代理 Vite 作为子文件夹时使用。
base: "",
fs: {
//限制为工作区 root 路径以外的文件的访问
strict: true,
//限制哪些文件可以通过 /@fs/ 路径提供服务
allow: [
// 搜索工作区的根目录
searchForWorkspaceRoot(process.cwd()),
// 自定义规则
"/path/to/custom/allow",
],
//限制Vite开发服务器提供敏感文件的黑名单
deny: [".env", ".env.*", "*.{pem,crt}"],
},
//定义开发调试阶段生成资产的url
origin: "http://127.0.0.1:8080",
},
//构建
build: {
//浏览器兼容性 "esnext"|"modules"
target: "modules",
//否自动注入 module preload 的 polyfill
polyfillModulePreload: true,
//输出路径
outDir: "dist",
//生成静态资源的存放路径
assetsDir: "assets",
//小于此阈值的导入或引用资源将内联为 base64 编码,以避免额外的 http 请求。设置为 0 可以完全禁用此项
assetsInlineLimit: 4096,
//启用/禁用 CSS 代码拆分
cssCodeSplit: true,
//不同的浏览器target设置CSS的压缩
cssTarget: "",
//构建后是否生成 source map 文件
//boolean | 'inline' | 'hidden'
sourcemap: false,
//自定义底层的 Rollup 打包配置
rollupOptions: {
//要打包的文件路径
input: "src/main.js",
//文件输出位置
output: {
//打包生产文件路径
file: "dist/index.js",
//打包输出格式
// "amd", "cjs", "system", "es", "iife" or "umd
format: "cjs",
//包的全部变量名称
name: "bundleName",
//声明全局变量
globals: {
jquery: "$",
},
},
//插件
plugins: [],
//不需打包的文件
external: ["lodash"],
},
//@rollup/plugin-commonjs 插件的选项
commonjsOptions: {},
//@rollup/plugin-dynamic-import-vars 选项
dynamicImportVarsOptions: {},
//构建的库
lib: {
entry: path.resolve(__dirname, "lib/main.js"),
//暴露的全局变量
name: "mylib",
//'es' | 'cjs' | 'umd' | 'iife'
formats: "es",
//输出的包文件名
fileName: "my-lib",
},
//当设置为 true,构建后将会生成 manifest.json 文件
manifest: false,
//当设置为 true,构建后将会生成SSR的manifest.json 文件
ssrManifest: false,
//生成面向 SSR 的构建
ssr: "undefined",
//设置为 false 可以禁用最小化混淆,
//boolean | 'terser' | 'esbuild'
minify: "esbuild",
//传递给 Terser 的更多 minify 选项。
terserOptions: {},
//设置为 false 来禁用将构建后的文件写入磁盘
write: true,
//默认情况下,若 outDir 在 root 目录下,则 Vite 会在构建时清空该目录。
emptyOutDir: true,
//启用/禁用 gzip 压缩大小报告
reportCompressedSize: true,
//触发警告的 chunk 大小(以 kbs 为单位)
chunkSizeWarningLimit: 500,
//设置为 {} 则会启用 rollup 的监听器
watch: null,
},
//开发服务器
preview: {
//开发服务器主机名
host: "localhost",
//开发服务器端口号
port: "5173",
//设为 true 时若端口已被占用则会直接退出,而不是尝试下一个可用端口
strictPort: true,
//https.createServer()配置项
https: "",
//服务器启动时自动在浏览器中打开应用程序。
open: "/docs/index.html",
//开发服务器,自定义代理规则
proxy: {
// 字符串简写写法
"/foo": "http://localhost:4567",
// 选项写法
"/api": {
target: "http://jsonplaceholder.typicode.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
// 正则表达式写法
"^/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' 的实例
},
},
// Proxying websockets or socket.io
"/socket.io": {
target: "ws://localhost:3000",
ws: true,
},
},
//开发服务器配置 CORS
cors: {},
},
//依赖优化选项
optimizeDeps: {
//检测需要预构建的依赖项
entries: [],
//预构建中强制排除的依赖项
exclude: ["jquery"],
//默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。
include: [],
//部署扫描和优化过程中传递给EsBuild
esbuildOptions: {},
//设置为 true 可以强制依赖预构建,而忽略之前已经缓存过的、已经优化过的依赖
force: true,
},
//SSR 选项
ssr: {
//列出的是要为 SSR 强制外部化的依赖
external: [],
//列出的是防止被 SSR 外部化依赖项。
noExternal: [],
//SSR 服务器的构建目标
target: "node",
//SSR 服务器的构建语法格式 'esm' | 'cjs'
format: "esm",
},
worker: {
//worker 打包时的输出类型 'es' | 'iife'
format: "iife",
// worker 打包的 Vite 插件
plugins: [],
//打包 worker 的 Rollup 配置项
rollupOptions: {},
},
});
感谢阅读!
今天就到这,下次想到再更新!么么哒~