vite+typescript从入门到实战(一):https://developer.aliyun.com/article/1483566
设置默认打开的浏览器
设置server.open默认打开的浏览器
/** * 设置server.open默认打开的浏览器 * npm i open -D */ const open = require('open'); process.env.BROWSER = open.apps.chrome
gzip 压缩配置
/** * gzip 压缩配置 * npm i vite-plugin-compression -D */ import viteCompression from 'vite-plugin-compression' const viteCompressionOptions = { filter: /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i, // 需要压缩的文件 threshold: 1024, // 文件容量大于这个值进行压缩 algorithm: 'gzip', // 压缩方式 ext: 'gz', // 后缀名 deleteOriginFile: true, // 压缩后是否删除压缩源文件 }
使用mockjs
/** * mockjs * yarn add -D cross-env vite-plugin-mock * yarn add mockjsD */ import { viteMockServe } from 'vite-plugin-mock'; // let prodMock = true; // const viteMockServeOptions = { // mockPath: 'mock', // supportTs: false, // ignore: undefined, // watchFiles: true, // localEnabled: command === 'serve', // prodEnabled: command !== 'serve' && prodMock, // injectCode: ` // import { setupProdMockServer } from '../mockProdServer'; // setupProdMockServer(); // `, // prodEnabled=true生效 main.{ts,js} // injectFile: '', // default: path.resolve(process.cwd(),'src/main.{ts,js}') // configPath: '', //default: vite.mock.config.ts // logger: true, //请求是输入日子 // } /** * yarn add vite-plugin-mock-server */ // import mockServer from 'vite-plugin-mock-server' // vite-plugin-mock-server // options.plugins.push(mockServer({ // logLevel: 'info', // urlPrefixes: ['/api/'], // mockRootDir: './mock', // mockJsSuffix: '.mock.js', // mockTsSuffix: '.mock.ts', // noHandlerResponse404: true, // mockModules: [] // }))
完整配置项参数
/** * import.meta.env.VITE_x 在.env[mode]中定义的变量不能访问到要用 loadEnv函数代替 * * * https://github.com/vitejs/awesome-vite#plugins */ import { defineConfig, loadEnv } from 'vite' /** * vue 整合插件 * npm i @vitejs/plugin-vue -D */ import vue from '@vitejs/plugin-vue' const url = require('url') let parseURL = url.parse('http://user:pass@host.com:8080/p/a/t/h?name=zhangsan&age=12#hash', true, true) // 解析路径 const path = require('path') /** * 设置server.open默认打开的浏览器 * npm i open -D */ const open = require('open'); process.env.BROWSER = open.apps.chrome /** * gzip 压缩配置 * npm i vite-plugin-compression -D */ import viteCompression from 'vite-plugin-compression' const viteCompressionOptions = { filter: /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i, // 需要压缩的文件 threshold: 1024, // 文件容量大于这个值进行压缩 algorithm: 'gzip', // 压缩方式 ext: 'gz', // 后缀名 deleteOriginFile: true, // 压缩后是否删除压缩源文件 } /** * mockjs * yarn add -D cross-env vite-plugin-mock * yarn add mockjsD */ import { viteMockServe } from 'vite-plugin-mock'; // let prodMock = true; // const viteMockServeOptions = { // mockPath: 'mock', // supportTs: false, // ignore: undefined, // watchFiles: true, // localEnabled: command === 'serve', // prodEnabled: command !== 'serve' && prodMock, // injectCode: ` // import { setupProdMockServer } from '../mockProdServer'; // setupProdMockServer(); // `, // prodEnabled=true生效 main.{ts,js} // injectFile: '', // default: path.resolve(process.cwd(),'src/main.{ts,js}') // configPath: '', //default: vite.mock.config.ts // logger: true, //请求是输入日子 // } /** * yarn add vite-plugin-mock-server */ // import mockServer from 'vite-plugin-mock-server' // vite-plugin-mock-server // options.plugins.push(mockServer({ // logLevel: 'info', // urlPrefixes: ['/api/'], // mockRootDir: './mock', // mockJsSuffix: '.mock.js', // mockTsSuffix: '.mock.ts', // noHandlerResponse404: true, // mockModules: [] // })) // export default ({ command, mode }) => { // console.log(command, mode); export default defineConfig(({ command, mode }) => { let options = { root: process.cwd(), //项目根目录(index.html 文件所在的位置 base: '/', //开发或生产环境服务的公共基础路径 // mode:'development' 'production' define: { // 定义全局常量,======待研究怎么用====== __PBR_APP_VERSION__: '1.0' }, plugins: [vue()], // 需要用到的插件数组 publicDir: 'public', // 静态资源文件夹,默认访问路径‘/’, 构建是会放在outDir根目录 cacheDir: 'node_modules/.vite', // vite缓存文件目录,--force可以强制重新缓存 resolve: { alias: { // 别名 '@': path.resolve(__dirname, './src'), 'comps': path.resolve(__dirname, './src/components'), 'utils': path.resolve(__dirname, './src/utils'), 'views': path.resolve(__dirname, './src/views'), 'apis': path.resolve(__dirname, './src/apis') }, dedupe: [], // 强制将相同依赖解析为同一副本, ======待研究怎么用====== //package.json 相关 开 conditions: [], // 场景条件, ======待研究怎么用====== mainFields: ['module', 'jsnext:main', 'jsnext'], // 入口点字段列表 //package.json 相关 关 extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'], //导入时想要省略的扩展名列表 }, CSS: { // modules:'', // postcss: '', // preprocessorOptions: {}, }, JSON: { namedExports: true, // 是否支持从 .json 文件中进行按名导入 stringify: false, // 若设置为 true,性能好,单不支持按名导入 }, esbuild: {}, // esbuild配置项,false为关闭esbuild assetsInclude: '', //指定其他静态文件 logLevel: 'info', // 控制台输出级别,默认info,'info' | 'warn' | 'error' | 'silent' clearScreen: true, // 清屏, --clearScreen false envDir: './', //默认 root server: { host: '0.0.0.0', port: 9999, // 端口,若端口被占用时,自动尝试下一个端口 strictPort: true, // 若端口被占用时直接退出 https: false, // 启用 TLS + HTTP/2 配置,注意:当 server.proxy 选项 也被使用时,将会仅使用 TLS。false则关闭 open: '/', // 项目启动时自动打开浏览器,可以设置默认打开的路径 proxy: { // 服务器代理 https://github.com/http-party/node-http-proxy#options '/foo': 'http://localhost:4567/foo', '/apidd': { target: loadEnv(mode, process.cwd()).VITE_APP_SERVER_URL, changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), configure: (proxy, options) => { // proxy 是 'http-proxy' 的实例 }, }, '^/fallback/.*': { // 正则 target: loadEnv(mode, process.cwd()).VITE_APP_SERVER_FALLBACK_URL, changeOrigin: true, rewrite: (path) => path.replace(/^\/fallback/, '') }, }, cors: true, // 跨域,默认允许任何源 或 {origin: 'http://example.com',optionsSuccessStatus: 200} force: false, // 强制依赖预构建 hmr: true, //禁用或配置 HMR 连接 /** * { * protocol?: string, * host?: string, * port?: number, * path?: string, * timeout?: number, * overlay?: boolean, // 屏蔽开发服务器错误提示 * clientPort?: number, * server?: Server * } */ watch: {}, //传递给 chokidar 的文件系统监听器选项 , ======待研究怎么用====== // middlewareMode: 'html', // https://cn.vitejs.dev/guide/ssr.html#setting-up-the-dev-server ======待研究怎么用====== /** * 以中间件模式创建 Vite 服务器。(不含 HTTP 服务器) * 'ssr' 将禁用 Vite 自身的 HTML 服务逻辑,因此你应该手动为 index.html 提供服务。 * 'html' 将启用 Vite 自身的 HTML 服务逻辑。 */ }, build: { // 构建 target: 'modules', // 构建目标格式,默认是modules,也可以是esbuild配置项,https://esbuild.github.io/api/#target outDir: 'dist', // 构建输出路径 assetsDir: 'assets', //静态资源文件夹,和outDir同级 assetsInlineLimit: 4096, // kb, 小于此值将内联base64格式 cssCodeSplit: true, // 运行css文件按chunk拆分,chunk加载时插入,如果false则所有的样式导出为一个css文件 sourcemap: false, // map文件 /* * true,将会创建一个独立的 source map 文件 * 'inline',source map 将作为一个 data URI 附加在输出文件中 * 'hidden' 的工作原理与 'true' 相似,只是 bundle 文件中相应的注释将不被保留。 */ rollupOptions: {}, // rollup打包选项 https://rollupjs.org/guide/en/#big-list-of-options commonjsOptions: {}, // @rollup/plugin-commonjs 插件的选项 dynamicImportVarsOptions: {}, // @rollup/plugin-dynamic-import-vars 的选项 // lib: {}, // 构建为库,https://cn.vitejs.dev/guide/build.html#library-mode /** * entry 是必须的因为库不能使用 HTML 作为入口。 * name 则是暴露的全局变量,在 formats 包含 'umd' 或 'iife' 时是必须的。 * 默认 formats 是 ['es', 'umd'] 。 * fileName 是输出的包文件名,默认 fileName 是 package.json 的 name 选项,同时,它还可以被定义为参数为 format 的函数。 */ manifest: false, // 后端集成, ======待研究怎么用====== minify: 'terser', // 最小化混淆,默认terser,可以是esbuild,或false关闭 TerserOptions: {}, // terser混淆配置项 cleanCssOptions: {}, // clean css 配置项, ======待研究怎么用====== write: true, // 是否允许构建写入磁盘,false一般用在对构建做进一步处理 emptyOutDir: true, // 构建前清库outDir目录 brotliSize: true, //启用/禁用 brotli 压缩大小报告, 大型项目禁用可能提高构建速度 chunkSizeWarningLimit: 500, //chunk 大小警告的限制(以 kbs 为单位 watch: {}, // watchoptions,https://rollupjs.org/guide/en/#watch-options, 设置为 {} 则会启用 rollup 的监听器,代码改变时自动打包 }, optimizeDeps: { // 依赖优化 // entries, '' | [], // 预构建入口 // exclude: [], // 预构建排查的依赖 // include: [], // 不在 node_modules 中的依赖包预构建 // keepNames:false, //打包器有时需要重命名符号以避免冲突 }, ssr: { // 试验型,没做研究 // external: [], //强制外部化的依赖 // noExternal: '', // 防止外部化的依赖 // target:'node', // SSR 服务器的构建目标 } } if (command === 'serve') { // dev & serve //vite-plugin-mock let prodMock = true; const viteMockServeOptions = { mockPath: 'mock', supportTs: false, ignore: undefined, watchFiles: true, localEnabled: command === 'serve', prodEnabled: command !== 'serve' && prodMock, injectCode: ``, // prodEnabled=true生效 main.{ts,js} injectFile: '', // default: path.resolve(process.cwd(),'src/main.{ts,js}') configPath: '', //default: vite.mock.config.ts logger: true, //请求是输入日子 } options.plugins.push(viteMockServe(viteMockServeOptions)) console.log('mock') } else { // build options.plugins.push(viteCompression(viteCompressionOptions)) } return options }) // } /** * jsdoc 方式智能提示 * @type {import('vite').UserConfig} */ export const config = { server: { } }
loadEnv 函数(使用.env文件)
import { loadEnv } from 'vite'; loadEnv('development', process.cwd());
检查process.cwd()路径下.env.development.local、.env.development、.env.local、.env这四个环境文件。
输出NODE_ENV和VITE_开头的键值对。
VITE_开头的键值对后面的不会覆盖前面的。
NODE_ENV的值后面的会覆盖前面的。
项目目录下创建.env.development .dev.production文件
NODE_ENV = 'development' VITE_APP_BASE_API = '/api' // 暴露必须以VITE开头才能被Vite识别
项目使用
import.meta.env.XXXX
if (process.env.NODE_ENV === 'development') { BASE_URL = `${import.meta.env.VITE_APP_BASE_API}` } else if (process.env.NODE_ENV === 'production') { BASE_URL = `${import.meta.env.VITE_APP_BASE_API}` } else { BASE_URL = `${import.meta.env.VITE_APP_BASE_API}` }
Vite.config 使用
import { defineConfig, loadEnv } from 'vite' export default ({ mode }) => { return defineConfig({ server: { proxy: { [`${loadEnv(mode, process.cwd()).VITE_APP_BASE_API}`]: { target: loadEnv(mode, process.cwd()).VITE_TEST_HOST, // 线上 // rewrite: (path:any) => path.replace(/^\/api/, ''), changeOrigin: true, ws: true } } } }) }
import * as dotenv from "dotenv" export interface ViteEnv { VITE_URL: string; VITE_BASE_URL: string; VITE_ZIP_NAME: string; } // 通过dotenv配置 需要加载指定.env文件 这样process.env打印到得就是对应得文件了 // 这里的mode是我们启动时候的参数 npm run dev:prc 得到的mode就是prc export function loadEnv(mode: string): ViteEnv { const ret: any = {}; // 在使用之前我们先指定加载哪个环境变量 dotenv.config({ path: `.env.${mode}` // .env.prc }); for (const envName of Object.keys(process.env)) { let realName = (process.env as any)[envName].replace(/\\n/g, "\n"); ret[envName] = realName; // 向process.env上扩展我们定义的VITE环境变量 process.env[envName] = realName; } return ret } const regExps = (value: string, reg: string): string => { return value.replace(new RegExp(reg, "g"), ""); }; // 根据环境变量返回指定得proxy export function createProxy(targetProxyUrl:string,baseUrl:string) { return { [`${baseUrl}`]: { target: targetProxyUrl, changeOrigin: true, rewrite: (path: string) => regExps(path,`${baseUrl}`) }, } }
# mode是在这里拿到的 export default ({ command, mode }) => {} import { loadEnv, createProxy } from "./src/utils/load-env" const { VITE_URL, VITE_BASE_URL, VITE_ZIP_NAME } = loadEnv(mode) # proxy部分 serve: { port: 8999, proxy: createProxy(VITE_URL, VITE_BASE_URL) }
在其他地方使用 request.ts
在request.ts中我们可以通过 import.meta.env 拿到我们在环境变量文件中的定义的Vite变量
这样在配置axios的时候。
const baseURL = (import.meta.env.VITE_BASE_URL as string) const service: AxiosInstance = axios.create({ baseURL, timeout: 30 * 1000, });
viteBuild.ts 文件
//位置 @/utils/viteBuild.ts import dotenv from 'dotenv'; // 定义接口类型声明 export interface ViteEnv { VITE_PORT: number; VITE_OPEN: boolean; VITE_PUBLIC_PATH: string; } /** * vite 打包相关 * @link 参考:https://cn.vitejs.dev/guide/env-and-mode.html * @returns 返回 `VITE_xxx` 环境变量和模式信息 */ export function loadEnv(): ViteEnv { const env = process.env.NODE_ENV; const ret: any = {}; const envList = [`.env.${env}.local`, `.env.${env}`, '.env.local', '.env']; envList.forEach((e) => { dotenv.config({ path: e }); }); for (const envName of Object.keys(process.env)) { let realName = (process.env as any)[envName].replace(/\\n/g, '\n'); realName = realName === 'true' ? true : realName === 'false' ? false : realName; if (envName === 'VITE_PORT') realName = Number(realName); if (envName === 'VITE_OPEN') realName = Boolean(realName); ret[envName] = realName; process.env[envName] = realName; } return ret; }
使用
import { loadEnv } from './src/utils/viteBuild'; const { VITE_PORT, VITE_OPEN, VITE_PUBLIC_PATH } = loadEnv();
process.cwd()
process.cwd()方法是流程模块的内置应用程序编程接口,用于获取node.js流程的当前工作目录。
vite中引入预处理全局scss文件(全局样式)
cssPreprocessOptions: { scss: { additionalData: '@import "./src/assets/scss/all.scss";' // 添加公共样式 } }
vite+typescript从入门到实战(三):https://developer.aliyun.com/article/1483578