程序媛刘刘 2025-11-06 16:52 采纳率: 20%
浏览 11

vite-plugin-static-copy和vite-plugin-html共同使用,publicDir:true没有引入

项目使用vite-plugin-static-copy和vite-plugin-html组件,想实现开发环境:根据配置引入内容或者全部内容,html 根据配置生成,生产环境分别根据配置打包,生产环境没有问题,就是开发环境,使用iframe 引用public内容会提示404,注释vite-plugin-html引用就没有问题了,试了好几个解决方案都不行,还有其他方案可以解决?


```javascript
import { defineConfig, loadEnv } from "vite";
import path from "path";
import createVitePlugins from "./vite/plugins";
// const baseUrl = "http://192.168.1.116:8080"; // 后端接口
const baseUrl = 'http://192.168.1.104:8080' // 后端接口

let views = {}
const base = ["error","monitor","redirect","system","tool"]
const other = [""]  
views.baseModules = base
views.includedModules = other

// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd());
  const { VITE_APP_ENV ,VITE_BUILD_PROJECT} = env;
  if(VITE_BUILD_PROJECT) other.push(VITE_BUILD_PROJECT)
  return {
    // 部署生产环境和开发环境下的URL。
    // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
    // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
    base: VITE_APP_ENV === "production" ? "" : "/",
    publicDir: VITE_APP_ENV === "production" ? false :"public", // 禁用 Vite 默认的 public 文件夹复制行为
    plugins: createVitePlugins(env, command === "build",views),
    resolve: {
      // https://cn.vitejs.dev/config/#resolve-alias
      alias: {
        // 设置路径
        "~": path.resolve(__dirname, "./"),
        // 设置别名
        "@": path.resolve(__dirname, "./src"),
      },
      // https://cn.vitejs.dev/config/#resolve-extensions
      extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
    },
    // 打包配置
    build: {
      // https://vite.dev/config/build-options.html
      sourcemap: command === "build" ? false : "inline",
      outDir: "dist",
      assetsDir: "assets",
      chunkSizeWarningLimit: 2000,
      rollupOptions: {
        output: {
          chunkFileNames: "static/js/[name]-[hash].js",
          entryFileNames: "static/js/[name]-[hash].js",
          assetFileNames: "static/[ext]/[name]-[hash].[ext]",
        },
      },
    },
    // vite 相关配置
    server: {
      port: 3000,
      host: true,
      open: true,
      proxy: {
        // https://cn.vitejs.dev/config/#server-proxy
        "/dev-api": {
          target: baseUrl,
          changeOrigin: true,
          rewrite: (p) => p.replace(/^\/dev-api/, ""),
        },
        // springdoc proxy
        "^/v3/api-docs/(.*)": {
          target: baseUrl,
          changeOrigin: true,
        },
      },
    },
    css: {
      postcss: {
        plugins: [
          {
            postcssPlugin: "internal:charset-removal",
            AtRule: {
              charset: (atRule) => {
                if (atRule.name === "charset") {
                  atRule.remove();
                }
              },
            },
          },
        ],
      },
    },
  };
});





```javascript
import vue from "@vitejs/plugin-vue";

import createAutoImport from "./auto-import";
import createSvgIcon from "./svg-icon";
import createCompression from "./compression";
import createSetupExtend from "./setup-extend";
import createModuleFilter from "./filter-views";
import createPublicFilter from './filter-public';
import createEditHtml from './edit-html'

export default function createVitePlugins(viteEnv, isBuild = false, buildList) {
  const vitePlugins = [vue()];
  isBuild && vitePlugins.push(createPublicFilter(viteEnv));
 vitePlugins.push(createEditHtml(viteEnv));
  vitePlugins.push(createAutoImport());
  vitePlugins.push(createSetupExtend());
  vitePlugins.push(createSvgIcon(isBuild));
  isBuild && vitePlugins.push(...createCompression(viteEnv));
  isBuild && vitePlugins.push(createModuleFilter(buildList));

  return vitePlugins;
}


import { viteStaticCopy } from 'vite-plugin-static-copy';
import { publics, getConfigByKey } from '../config/system'

export default function createPublicFilter(env) {
  const { VITE_BUILD_PROJECT } = env
  const systemPublics = getConfigByKey(publics,VITE_BUILD_PROJECT);
  console.log(systemPublics);
  
  return  viteStaticCopy({
    targets: systemPublics,
    enableInDevMode: true
  })
}
import { createHtmlPlugin } from 'vite-plugin-html';
import { html, getConfigByKey } from '../config/html'

export default function createEditHtml(env) {
  const { VITE_BUILD_PROJECT } = env
  const systemHtml = getConfigByKey(html,VITE_BUILD_PROJECT);
  return  createHtmlPlugin(systemHtml)
}

//index.html 文件配置
const defaultHtml = {
  minify: true,
};

const html = {
  license: {
    inject: {
      data: {
        injectScript :`  <script src="/drag/js/jquery.min.js"></script>
  <script src="/drag/js/draggabilly.pkgd.min.js"></script>`
      },
    }
  },
};

function getConfigByKey(routers, projectKey) {
  if (!routers || typeof routers !== "object" || Array.isArray(routers)) {
    return { ...defaultHtml };
  }
  if (typeof projectKey !== "string" || projectKey.trim() === "") {
    return { ...defaultHtml };
  }
  const normalizedKey = projectKey.trim().toLowerCase();
  const baseConfig = { ...defaultHtml };
  if (routers.hasOwnProperty(normalizedKey)) {
    const projectConfig = routers[normalizedKey];
    return {
      ...baseConfig,
      ...projectConfig,
      inject: {
        ...baseConfig.inject,
        ...projectConfig.inject,
      },
    };
  }
  return baseConfig;
}

export { html, getConfigByKey };


// public 是否打包配置
const defaultKey = [
  {
    src: "public/html",
    dest: "",
  },
  {
    src: "public/favicon.ico",
    dest: "",
  },
];

const publics = {
  license: [
    {
      src: "public/drag",
      dest: "",
    },
  ],
  ngbseal: [
    {
      src: "public/onlineSeal",
      dest: "",
    },
    {
      src: "public/sign",
      dest: "",
    },
  ],
  sdjnseal: [
    {
      src: "public/sign",
      dest: "",
    },
  ],
};

function getConfigByKey(routers, projectKey) {
  if (!routers || typeof routers !== "object") {
    return [];
  }
  if (!projectKey || typeof projectKey !== "string") {
    return [];
  }
  const normalizedKey = projectKey.trim().toLowerCase();
  if (Object.prototype.hasOwnProperty.call(routers, normalizedKey)) {
    return [...defaultKey, ...routers[normalizedKey]];
  }
  return [...defaultKey];
}

export { publics, getConfigByKey };


  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-11-21 18:32
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你遇到的问题是关于 Vite 中使用 vite-plugin-static-copyvite-plugin-html 时,开发环境下引用 public 目录下的资源(如 iframe)出现 404 错误,但注释掉 vite-plugin-html 后问题消失。这表明两者在开发环境中的行为存在冲突。


    问题分析

    1. publicDir 配置不正确

      • 在你的配置中,publicDir: VITE_APP_ENV === "production" ? false : "public" 是错误的。
      • 如果你想在开发环境中保留 public 文件夹内容,并且希望它被复制到构建输出中,应将 publicDir 设置为 "public",而不是 false
      • false 会完全禁用 Vite 的默认 public 文件夹处理逻辑,导致开发服务器无法正确提供这些文件。
    2. vite-plugin-static-copy 与 vite-plugin-html 冲突

      • vite-plugin-static-copy 用于复制静态资源,而 vite-plugin-html 用于生成 HTML 文件。
      • 当两者同时启用时,可能会导致开发服务器对某些路径的解析不一致,尤其是当 publicDir 被设置为 false 或其他非标准值时。
    3. iframe 引用路径问题

      • 开发服务器可能没有正确地将 public 文件夹中的资源映射到正确的 URL 路径,导致 iframe 引用失败。

    解决方案

    1. 修正 publicDir 配置

    重点部分:
    publicDir 应始终设置为 "public",除非你明确不需要它。

    publicDir: VITE_APP_ENV === "production" ? false : "public",
    

    ❌ 原始代码:

    publicDir: VITE_APP_ENV === "production" ? false : "public",
    

    ✅ 修改后:

    publicDir: "public", // 无论开发还是生产环境都保留 public 文件夹
    

    2. 确保 vite-plugin-static-copy 正确复制文件

    如果你需要在开发环境中复制一些特定文件,可以使用 vite-plugin-static-copy 来实现:

    import { defineConfig, loadEnv } from "vite";
    import vue from "@vitejs/plugin-vue";
    import path from "path";
    import { viteStaticCopy } from 'vite-plugin-static-copy';
    
    export default defineConfig(({ mode }) => {
      const env = loadEnv(mode, process.cwd());
      const { VITE_APP_ENV } = env;
    
      return {
        plugins: [
          vue(),
          viteStaticCopy({
            targets: [
              {
                src: 'public/*',
                dest: 'public'
              }
            ]
          })
        ],
        publicDir: "public",
        server: {
          port: 3000,
          host: true,
          open: true,
        },
      };
    });
    

    3. 调整 vite-plugin-html 的配置

    确保 vite-plugin-html 不会对开发环境造成干扰。你可以通过判断 command 是否为 build 来控制其行为:

    // vite/plugins/edit-html.js
    import { htmlPlugin } from 'vite-plugin-html';
    
    export default function createEditHtml(env) {
      const { VITE_APP_ENV } = env;
      return htmlPlugin({
        template: './index.html',
        inject: {
          data: {
            title: 'My App'
          }
        }
      });
    }
    

    然后在 createVitePlugins 中根据是否是 build 来决定是否添加:

    isBuild && vitePlugins.push(createEditHtml(viteEnv));
    

    4. 检查 iframe 的引用路径

    确保你在开发环境中引用的是正确的路径,例如:

    <iframe src="/your-file.html"></iframe>
    

    如果你将文件放在 public/your-file.html,那么访问路径应为 /your-file.html


    最终建议的配置方案

    📁 项目结构示例

    project/
    ├── public/
    │   └── your-file.html
    ├── src/
    │   └── main.js
    ├── vite.config.js
    └── package.json
    

    🧾 vite.config.js 示例

    import { defineConfig, loadEnv } from "vite";
    import vue from "@vitejs/plugin-vue";
    import path from "path";
    import { viteStaticCopy } from 'vite-plugin-static-copy';
    import createVitePlugins from "./vite/plugins";
    
    export default defineConfig(({ mode, command }) => {
      const env = loadEnv(mode, process.cwd());
      const { VITE_APP_ENV } = env;
    
      return {
        base: VITE_APP_ENV === "production" ? "" : "/",
        publicDir: "public",
        plugins: createVitePlugins(env, command === "build"),
        resolve: {
          alias: {
            "~": path.resolve(__dirname, "./"),
            "@": path.resolve(__dirname, "./src"),
          },
          extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
        },
        build: {
          sourcemap: command === "build" ? false : "inline",
          outDir: "dist",
          assetsDir: "assets",
          rollupOptions: {
            output: {
              chunkFileNames: "static/js/[name]-[hash].js",
              entryFileNames: "static/js/[name]-[hash].js",
              assetFileNames: "static/[ext]/[name]-[hash].[ext]",
            },
          },
        },
        server: {
          port: 3000,
          host: true,
          open: true,
        },
      };
    });
    

    总结

    | 问题 | 解决方案 | |------|----------| | publicDir: false 导致资源不可见 | 将 publicDir 设置为 "public" | | vite-plugin-static-copyvite-plugin-html 冲突 | 确保两者配置合理,避免重复处理 | | iframe 引用 404 | 检查资源路径是否正确,使用绝对路径 /your-file.html |


    如有更多关于插件配置或路径问题,请继续提问!

    评论

报告相同问题?

问题事件

  • 修改了问题 11月7日
  • 修改了问题 11月7日
  • 创建了问题 11月6日