webpack 迁移至 vite 注意事项 基于vue3+ts(持续汇总)

1.require 无法加载图片, 图片、文字等静态资源使用别名@ 、~@获取无法获取

require是node.js提供的模块 Webpack使用了node 使得编辑vue时可以使用require
但是vite不支持
而且图片在标签src中的路径不可以使用@ 别名获取绝对路径
css style中也不可以使用别名 ~@ 获取图片 文字等静态资源
替代方式 vite 静态资源处理

//const imgUrl = require('@/assets/image/demo.png')
//改为
const imgUrl = new URL('@/assets/image/demo.png', import.meta.url).href
//或者
function getImageUrl(name) {
    
    
  return new URL(`./dir/${
      
      name}.png`, import.meta.url).href
}

可以封装一个函数进行调用 根据不同的静态路径设置不同的函数
pub-use.ts

// 获取assets静态资源
const getAssetsFile = (url: string) => {
    
    
  if (url && url[0] == "/") {
    
    
    url = url.slice(1);
  }
  return new URL(`../assets/img/${
      
      url}`, import.meta.url).href;
};
const usePub = () => {
    
    
  return {
    
    
    getAssetsFile,
    //getAssetsFile1,
    //getAssetsFile2
  };
};
export default usePub;

使用 pub-use.ts

import usePub from "@/utils/pub-use";
const Pub = usePub();
const getAssetsFile = Pub.getAssetsFile;

//标签中使用 先setup return 出去
setup(){
    
    
return  getAssetsFile 
}

<img :src="getAssetsFile('/[email protected]')" />

2. 组件不传参时 props不可以设置为空 否则打包错误

错误示例 vite打包报错 Type ‘{}’ is not assignable to type ‘IntrinsicAttributes & (Partial<{ [x: number]: string; } | {}> & Omit<(readonly string[] | Readonly<ExtractPropTypes<Readonly<ComponentObjectPropsOptions>>>) & (VNodeProps & … 2 more … & Readonly<…>), never>)’.
原因是 子组件props:{}
更改 父组件不需要给子组件传值是 不写 props属性
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
解决
在这里插入图片描述

3.vue html事件绑定 函数 需要定义参数类型

如果需要用到箭头函数 需要指定event 参数类型

  <el-input
    @focus="
      (e:any) => {
    
    
        handle(e,item.name)
      }
    "
    @blur="
      (e:any) => {
    
    
         handle(e,item.value)
      }
    "
    class="input h-full w-full input_border_0"
    v-model="fromData.packLength"
  ></el-input>

4. ts接口(interface ) 定义导出是需要使用 type 导出

interface navDrawerListType {
    
    
  active?: boolean; //是否为活跃状态
  name_id?: string; //唯一标识 名称
  title: string; //标题
  iconUrl?: string; //图片url
  path?: string; //跳转路由
  query?: {
    
    
    //跳转路由 路由参数
    [propName: string]: string;
  };
  type?: number; // 抽屜导航列表类型  1默认类型 单标题  2 拥有子标题类型  3 无图片 下拉菜单方式导航列表
  children?: navDrawerListType[]; //子路由列表
}
// 导出
export type {
    
     navDrawerListType};

5. tsconfig.json 、vite.config.js/vue.config.js 及环境变量 .env.development及 .env.production的变化

  1. alias 路径 以及 开发环境切换的变化

  2. css样式引入 变化
    webpack
    // 添加全局样式
    additionalData: @import "~@/assets/css/var.scss";
    vite
    // 添加全局样式
    additionalData: @import "src/assets/css/var.scss";,

  3. webpack 判断开发环境可以直接使用process.env获取到设置的 .env.development 及 .env.production不同开发环境的文件内容
    vite 本来可以通过 import.meta.env 对象上暴露环境变量 但是 生产模式下重新编译了代码字符串改变了,导致获取不到。所以需要使用 define暴露环境变量 参考 vite 环境变量和模式
    在这里插入图片描述

    vite 在vite.config.js外部不能直接获取到 .env.development 及 .env.production的内容 需要使用vite的 define 在 vite.config.js定义全局常量替换方式 建立 process.env变量 且 .env.development 及 .env.production定义的变量需要使用VITE开头 vite.config.js才能获取的到 参考vite definevite env

vite tsconfig.json

    // 文件路径在解析时, 基本url
    "baseUrl": ".",
    // 路径解析(类似于webpack alias)
    "paths": {
    
    
      // "@/*": ["src/*"],
      "@/*": ["./src/*"], // 多加个这个
      "components/*": ["src/components/*"]
    }

webpack tsconfig.json

    // 文件路径在解析时, 基本url
    "baseUrl": ".",
     // 路径解析(类似于webpack alias)
    "paths": {
    
    
      "@/*": ["src/*"],
      "components/*": ["src/components/*"]
    },

vite vite.config.js

import {
    
     defineConfig, loadEnv } from "vite";
import vue from "@vitejs/plugin-vue";
const path = require("path");
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import {
    
     ElementPlusResolver } from "unplugin-vue-components/resolvers";
import {
    
     replaceRequireVariable } from "./dynamic.js";
// https://vitejs.dev/config/
// process.env.VITE_APP_BASE_API = "http://dev.freyparts.cn/api/";
console.log("import.meta", import.meta);
export default ({
     
      mode }) => {
    
    
  // process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };
  const encConfig =loadEnv(mode, process.cwd());
  return defineConfig({
    
    
    // base: process.env.ELECTRON == 'true' ? './' : '.',
    envDir: "./", //这里使用相对路径,绝对路径其实也可以
    resolve: {
    
    
      alias: {
    
    
        "@": path.resolve(__dirname, "./src"),
      },
      // alias: [{ find: '@', replacement: path.resolve(__dirname, 'src') }]
      // alias: {
    
    
      //   // 键必须以斜线开始和结束
      //   '@': path.resolve(__dirname, 'src')
      // }
      // 忽略后缀名的配置选项,vue不建议这样做,因为会影响IDE和类型支持
      //extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
    },
    define: {
    
    
      "process.env": {
    
    
        // BASE_API: "/dev",
        // IMG_BASE: "/dev",
        // VUE_APP_BROWSER: "/dev",
        VITE_NODE_ENV:encConfig.VITE_NODE_ENV,
        NODE_ENV:encConfig.VITE_NODE_ENV,
        VITE_APP_BASE_API: encConfig.VITE_APP_BASE_API,
      },
    },
    plugins: [
      vue(),
      replaceRequireVariable(["hyFileStyle.vue?vue&type=template&lang.js"]), // 替换 组件里面require加变量的内容
      AutoImport({
    
    
        resolvers: [ElementPlusResolver()],
      }),
      Components({
    
    
        resolvers: [ElementPlusResolver()],
      }),
    ],
    css: {
    
    
      preprocessorOptions: {
    
    
        scss: {
    
    
          // 添加全局样式
          additionalData: `@import "src/assets/css/var.scss";`,
          // prependData: "@import ('/src/assets/css/var.scss')"
        },
      },
    },
    server: {
    
    
      proxy: {
    
    
        "/api": {
    
    
          target: encConfig.VITE_APP_BASE_API,
          ws: true,
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ""),
        },
      },
    },
  });
};

webpack vue.config.js

 const path = require('path')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const {
    
     ElementPlusResolver } = require('unplugin-vue-components/resolvers')
// const CompressionWebpackPlugin = require('compression-webpack-plugin')
process.env.VUE_APP_BASE_API = 'http://xxxxxx'
module.exports = {
    
    
  // 1.配置方式一: CLI提供的属性
  // outputDir: './build',
  // publicPath: './',
  devServer: {
    
    
    proxy: {
    
    
      '^/api': {
    
    
        target: process.env.VUE_APP_BASE_API,
        pathRewrite: {
    
    
          '^/api': ''
        },
        changeOrigin: true
      }
    }
  },
  css: {
    
    
    loaderOptions: {
    
    
      // 但是在配置 `prependData` 选项的时候
      // `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
      scss: {
    
    
        // 添加全局样式
        additionalData: `@import "~@/assets/css/var.scss";`
        // prependData: "@import ('~@/assets/css/var.scss')"
      }
    }
  },
  chainWebpack: (config) => {
    
    
    // eslint-disable-next-line prettier/prettier
    // ['home', 'specialUpdateUnShelve', 'allotTransferWarehouse', 'inboundDelivery', 'allocatingStorageBill', 'login', 'main', 'sweepPicking', 'salesReturn', 'scanPackage', 'materialReturnOrRecipients'].forEach((name) => {
    
    
    //   // 移除 preload 插件
    //   config.plugins.delete(`preload-${name}`)
    //   // 移除 prefetch 插件
    //   config.plugins.delete(`prefetch-${name}`)
    // })
    //config.plugins.delete('preload-${name}')//可配置移除预加载的页面。eg:login.html则添加config.plugins.delete('preload-login'),
    config.resolve.alias
      .set('@', path.resolve(__dirname, 'src'))
      .set('components', '@/components')
    // config.externals = {
    
    
    //   'element-plus/es/components/loading-directive/style/css': 'empty'
    // }
    // config
    //   .plugin('AutoImport')
    //   .use(AutoImport({ resolvers: [ElementPlusResolver()] }))
    // config
    //   .plugin('Components')
    //   .use(Components({ resolvers: [ElementPlusResolver()] }))
    config.plugin('AutoImport').use(
      AutoImport({
    
    
        imports: ['vue'],
        resolvers: [
          ElementPlusResolver({
    
    
            importStyle: 'css',
            exclude: new RegExp(/^(?!.*loading-directive).*$/)
          })
        ],
        dts: 'auto-imports.d.ts'
      })
    )
    config.plugin('Components').use(
      Components({
    
    
        resolvers: [ElementPlusResolver({
    
     importStyle: 'css' })],
        dts: 'components.d.ts'
      })
    )
    // const productionGzipExtensions =
    //   /\.(js|ts|css|json|txt|html|ico|svg)(\?.*)?$/i
    // config.plugin('CompressionWebpackPlugin').use(
    //   new CompressionWebpackPlugin({
    
    
    //     filename: '[path].gz[query]',
    //     algorithm: 'gzip',
    //     test: productionGzipExtensions,
    //     threshold: 10240,
    //     minRatio: 0.8
    //   })
    // )

    if (process.env.use_analyzer) {
    
    
      // 添加分析工具
      config
        .plugin('webpack-bundle-analyzer')
        .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
    }
  }
}

vite .env.development及 .env.production

.env.development

# .env.development 测试环境参数值
VITE_NODE_ENV= development
VITE_APP_BASE_API = "http://xxxxxx"

.env.production

扫描二维码关注公众号,回复: 16507375 查看本文章
# env.production 生产环境参数值
VITE_NODE_ENV= production
VITE_APP_BASE_API = "http://xxx"

webpack .env.development及 .env.production

.env.development

VUE_APP_BASE_URL=https://xxxxxxx
VUE_APP_BASE_NAME=hhh2

.env.production

VUE_APP_BASE_URL=https:xxxx
VUE_APP_BASE_NAME=hhh

猜你喜欢

转载自blog.csdn.net/weixin_43245095/article/details/125330204