阅读 781

vite + Vue3 遇到的一些问题汇总

啰嗦一下,vitevue3已经出来很长一段时间了,一直没生产实践过,之前一直都是使用 vue2,通过这次实践,个人感觉还是喜欢使用那经典且深入人心的 vue2,或许这是众多顽固派不愿跟随技术更新的最后的倔强吧。不过 vue3 的<script setup>语法糖挺好使的,可以减少许多代码,不用在 return 出去。

1. 项目开始的准备

  1. 熟悉下vue3 文档 和 vite 文档

  2. vsoce 编辑器安装Vue Language Features (Volar)拓展

2. 关于 vite 遇到的一些问题

vite 的最大感觉就是“快”,本地开发比 webpack 快很多,因为不用打包所有看模块再启动,浏览器原生支持 ES 模块,文件修改后即生效,即使修改vite.config.js配置文件,也可以监听到,自动重启生效。

2.1 关于打包成 ES5 代码

通过build.target配置项指定构建目标,传统浏览器可以通过插件@vitejs/plugin-legacy来支持,最低仅支持到es2015,即es6,不能打包成es5的代码。打包出来的代码<script type=module></script>type=module属性,可以直接在里面使用模块化调用。有知道怎么处理成 es5 的,可以分享出来给大家。

// vite.config.js import { defineConfig } from "vite"; // https://github.com/vitejs/vite/tree/main/packages/plugin-legacy import legacy from "@vitejs/plugin-legacy"; export default defineConfig({   plugins: [     legacy({       targets: ["ie >= 11"],       additionalLegacyPolyfills: ["regenerator-runtime/runtime"],     }),   ],   build: {     target: "es2015", // 默认 "modules"   }, }); 复制代码

2.2 vite 中使用css预处理器等

  1. vite 中使用 less/scss/sass/stylus 等 css 预处理器

    vitejs.cn/guide/featu… 直接进行安装,不用像 webpack 那样安装 loader 和配置

npm install -D less 复制代码

<style> /* use less */ </style> 复制代码

  1. vite 中使用 postcss

    vitejs.cn/config/#css… vite 中已集成了 postcss,无需再单独安装

  2. vite 中使用 autoprefixer

import autoprefixer from "autoprefixer"; export default defineConfig({   css: {     postcss: {       plugins: [autoprefixer],     },   }, }); 复制代码

2.3 vite 打包将 js 和 css 文件夹分离

默认打包后,js 和 css 是全部混在一起的,对强迫症很难受

github.com/vitejs/vite…

export default defineConfig({   build: {     rollupOptions: {       output: {         chunkFileNames: "static/js/[name]-[hash].js",         entryFileNames: "static/js/[name]-[hash].js",         assetFileNames: "static/[ext]/[name]-[hash].[ext]",       },     },   }, }); 复制代码

2.4 vite 根目录vite.config.js配置文件异步配置

官方默认是支持的

cn.vitejs.dev/config/#asy…

export default defineConfig(async ({ command, mode }) => {   const data = await asyncFunction();   return {     // 构建模式所需的特有配置   }; }); 复制代码

2.5 vite 根目录vite.config.js配置文件读取env变量

在配置文件中直接使用import.meta.env.xxx这样读取是报错的,不过有了上面的异步配置,读取env变量就方便了,我们可以直接使用fs直接获取

  • .env文件

# PROXY_URL VITE_PROXY_URL=http://xxxxxx/ # DBPATH_ENV DBPATH_ENV=XXXX 复制代码

  • vite.config.js文件

const fs = require("fs"); const path = require("path"); const { promisify } = require("util"); const fsState = promisify(fs.stat); const readFile = promisify(fs.readFile); // 定义一个函数,读取.env文件中的内容 async function getEnvConfig(vite_env_key) {   const envFilePath = path.resolve(__dirname, "./.env");   const [notExistEnvFile, existEnvFile] = await fsState(envFilePath)     .then((data) => [null, data])     .catch((e) => [e, null]);   if (notExistEnvFile || existEnvFile.size <= 0) return;   const envContent = await readFile(envFilePath, "utf8");   if (!envContent) return;   const envContentArr = envContent     .split("\n")     .filter((str) => !str.startsWith("#")) // 过滤掉注释行     .filter(Boolean);   const resultKey = envContentArr.find((item) => item.includes(vite_env_key));   return resultKey ? resultKey.split("=")[1] : null; } const resolveConf = async () => {   // 读取 .env 文件中的VITE_PROXY_URL的值   const PROXY_URL = await getEnvConfig("VITE_PROXY_URL");   return {     server: {       host: "0.0.0.0",       port: 3000,       open: true,       proxy: {         "/api": {           target: PROXY_URL,           changeOrigin: true,           // rewrite: (path) => path.replace(/^\/api/, ""),         },       },     },   }; }; export default defineConfig(resolveConf()); 复制代码

2.6 vite 项目index.html中使用env环境变量

如何像webpack项目的html-webpack-plugin那样使用<%= htmlWebpackPlugin.options.title %>,这种方式动态注入变量,vite 中可以使用vite-plugin-html来完成。

  1. 安装

npm i vite-plugin-html -D 复制代码

  1. 使用(比如不同环境下动态注入高德地图的key)

  • vite.config.js配置文件

import { minifyHtml, injectHtml } from "vite-plugin-html"; const AMAP_KEY = "xxx"; export default defineConfig({   plugins: [     injectHtml({       data: {         title: "hello",         // 高德地图         injectAMapScript: `<script src="https://webapi.amap.com/maps?v=1.4.15&key=${AMAP_KEY}"></script>`,       },     }),   ], }); 复制代码

  • index.html中使用 ejs 模板引擎动态注入

<!DOCTYPE html> <html lang="en">   <head>     <title><%- title %></title>   </head>   <body>     <div id="app"></div>     <script type="module" src="/src/main.js"></script>     <%- injectAMapScript %>   </body> </html> 复制代码

2.7 引用静态资源和 public 目录

cn.vitejs.dev/config/#pub…

  1. 引用静态资源

在 vue 文件中templatestyle中以相对路径和绝对路径两种方式引用静态资源

<template>   <!-- 相对路径 -->   <img src="./assets/img/test.png" />   <!-- 绝对路径 -->   <img src="/src/assets/img/test.png" /> </template> <style scoped> #app {   background-image: url("./assets/img/test.png"); } </style> 复制代码

  1. public 目录

    cn.vitejs.dev/guide/asset…

  • 放在public目录下的文件应使用绝对路径引用,例如public/icon.png应该使用/icon.png

  • public中的资源不应该被JavaScript文件引用

<img src="/logo.png" /> 复制代码

2.8 打包生产环境移除 console 和 debugger

export default defineConfig({   build: {     // 生产环境移除console     terserOptions: {       compress: {         drop_console: true,         drop_debugger: true,       },     },   }, }); 复制代码

2.9 异步 import 如何像 webpack webpackChunkName 那样支持自定义 chunkname

github.com/vitejs/vite…

// 这里如何像webpack那样支持自定义自定义chunkname,打包后文件名是自定义的名字 const Login = () => import("@/views/Login"); 复制代码

未解决,知道的,麻烦分享一下

3. 关于 vue3 遇到的一些问题

3.1 深度选择器

v3.cn.vuejs.org/api/sfc-sty…

之前的 '>>>' 已经被废弃,现在使用:deep()伪类

<style scoped> .a :deep(.b) {   /* ... */ } </style> 复制代码

3.2 vue-router4.x路由 404 匹配

捕获所有路由或 404 Not found 路由

import { createRouter, createWebHistory } from "vue-router"; const Result = () => import("@/views/Result"); const router = createRouter({   history: createWebHistory(),   routes: [     {       // 注意这里,404页面匹配规则和以前不相同,要采用这种配置方式才行       path: "/:pathMatch(.*)*",       component: Result,       name: "Result",     },   ], }); export default router; 复制代码

3.3 <script setup>特性中使用vant3.x组件

vant-contrib.gitee.io/vant/v3/#/z…

<script setup>中可以直接使用 Vant 组件,不需要进行组件注册

<template>   <Button /> </template> <script setup> import { Button } from "vant"; </script> 复制代码

3.4 vite 启动后关于defineEmits的警告

defineEmits is a compiler macro and no longer needs to be importe

删掉defineEmits的引用即可

- import { reactive, defineEmits } from 'vue'; + import { reactive } from 'vue'; // 直接使用defineEmits const emit = defineEmits(['test1', 'test2']); emit('test1', 'hello1'); 复制代码

3.5 vue3 和echarts5动态更新数据报错

barPolar.js:63 Uncaught TypeError: Cannot read properties of undefined (reading 'type')

  • 造成报错的原因是 vue3 中使用 proxy 的方式监听响应式,charts 实例会被在 vue 内部转换成响应式对象

  • 在初始化的时候可以使用markRaw指定为非响应式即可

<template>   <div ref="lineChartDomRef"></div> </template> <script setup> import { markRaw, ref, onMounted } from "vue"; import * as echarts from "echarts"; const lineChartInsRef = ref(); const lineChartDomRef = ref(); onMounted(() => {   // 初始化时使用markRaw,后面使用lineChartInsRef.value实例更新时,就不会报错了   const option = {     // ...   };   lineChartInsRef.value = markRaw(echarts.init(lineChartDomRef.value));   lineChartInsRef.value.setOption(option);   window.addEventListener("resize", () => {     lineChartInsRef.value.resize();   }); }); </script> 复制代码

3.6 Vue3.x 使用<script setup>如何设置组件name名称

forum.vuejs.org/t/vue3-2-sc…

其实可以写两个 script 标签,下面两个可以并存

<script> import { defineComponent } from "vue"; export default defineComponent({   name: "Test", }); </script> <script setup> // ... </script> 复制代码

3.7 vue3 中的 vue-router4.x 下的 keep-alive 写法

[Vue Router Warn]: <router-view> can no longer be used directly inside <transition> or <keep-alive>

  • router-view 的 v-slot

  • 在动态组件上使用 keep-alive

之前这样写,会报警告

<keep-alive>   <RouterView /> </keep-alive> 复制代码

根据提示,得这样写:

<template>   <router-view v-slot="{ Component }">     <!-- 缓存name名称为aaa和bbb的组件 -->     <keep-alive :include="['aaa', 'bbb']">       <component :is="Component" />     </keep-alive>   </router-view> </template> 复制代码

3.8 vue-router4 监听路由变化 onBeforeRouteUpdate

import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'; onBeforeRouteUpdate((to, from, next) => {   if (from.name === 'MachineList') {     ...   }   next(); }); 复制代码

3.9 nginx 线上部署,刷新后页面 404

修改 nginx 配置

location / {     root   /usr/share/nginx/dist; # 服务默认启动目录     index  index.html index.htm; # 默认访问文件 +    try_files $uri /index.html; # 防止浏览器刷新后,页面404     client_max_body_size 100m; }


作者:sRect
链接:https://juejin.cn/post/7028137821269393438

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐