taro copy静态资源失败以及解决方案

248 阅读4分钟
# Taro Vite 项目静态资源复制问题解决小记

## 1. 最初的目标:静态资源去哪儿了?

大家好!这次我们遇到了一个小挑战:在我们的 Taro (Vue3 + Vite) 项目中,希望把放在 `public/` 目录下的一些静态资源(比如字体、图片、JSON 文件等),在打包后能乖乖地跑到我们期望的 `dist/` 目录下的特定文件夹里去。这样,H5 或其他端的应用就能正确加载这些资源了。

听起来很简单?嗯,一开始我也这么觉得。

## 2. 踩坑实录:为什么就是不到位?

我们尝试了几种方法,但都遇到了一些小麻烦:

* **Taro 自带的 `copy` 配置不灵了?** 之前用 Webpack 的时候,Taro 配置里的 `copy` 选项挺好使。但换到 Vite 后,发现它好像不怎么听话了,或者说和 Vite 的机制不太合拍。
* **Vite 的 `public` 目录有自己的想法:** Vite 有个 `public` 目录,默认情况下,它会把里面的东西直接复制到打包后的 `dist` 文件夹根目录。也就是说,`public/assets/some-file.png` 会变成 `dist/assets/some-file.png`。如果我们的目标是 `dist/my-custom-static-folder/assets/some-file.png`,这就和我们想要的路径不太一样了。

## 3. 脑袋急转弯:该怎么破?

遇到问题,就得想办法。我的思考过程大概是这样的:

* **为什么默认的不行?** 明白了,Vite 对 `public` 目录的处理方式是固定的,它主要是为了那些不需要编译、直接访问的静态资源设计的。我们的需求稍微特殊了一点,想自定义目标路径。
* **Vite 项目通常怎么处理这种“特殊”复制需求?** Vite 有一个强大的插件生态系统。很多时候,当 Vite 自身功能不直接满足特定需求时,社区通常会有插件来解决。这就好比给 Vite 装了个新工具。
* **哪个插件合适呢?** 经过一番搜索和之前文档的指引 (参考 ID: `bacc495b-d2d9-467b-8759-6858280e4db6`),`vite-plugin-static-copy` 这个插件进入了视线。它看起来就是专门干这种“指哪打哪”的复制活儿的。

## 4. 柳暗花明:`vite-plugin-static-copy` 登场!

最终,我们选择了 `vite-plugin-static-copy` 插件,问题迎刃而解。

**怎么做的?**

1.  **安装插件:**
    ```bash
    npm install vite-plugin-static-copy -D
    # 或者用 yarn
    # yarn add vite-plugin-static-copy -D
    ```

2.  **修改 `config/index.js` 文件:**
    在 Taro 项目的配置文件里,给 Vite 的插件列表加上新成员。

    ```javascript
    // config/index.js
    import { defineConfig } from '@tarojs/cli'
    import path from 'node:path'
    import { viteStaticCopy } from 'vite-plugin-static-copy'
    import { normalizePath } from 'vite' // 别忘了这个,处理路径兼容性

    export default defineConfig<'vite'>(async (merge, { command, mode }) => {
      // ... 其他配置 ...
      const baseConfig = {
        // ... 其他配置 ...
        compiler: {
          type: 'vite',
          vitePlugins: [
            // ... 可能还有其他插件 ...
            viteStaticCopy({
              targets: [
                {
                  // 源头:告诉它去哪里找静态资源,比如 public/font
                  src: normalizePath(path.resolve(process.cwd(), 'public/font')),
                  // 目的地:告诉它复制到打包后的哪个位置,比如 dist/static/font
                  dest: 'static/font' // 这个路径是相对于 dist 目录的
                },
                // 你可以添加更多 target 来复制其他静态资源
                // 例如,复制 public/images 到 dist/static/images
                {
                  src: normalizePath(path.resolve(process.cwd(), 'public/images')),
                  dest: 'static/images'
                }
              ]
            })
          ]
        },
        // ... 其他配置 ...
      }
      // ...
      return merge({}, baseConfig, process.env.NODE_ENV === 'development' ? devConfig : prodConfig)
    })
    ```

**为什么这个方案可行?**

* **精准控制:** 这个插件允许我们明确指定“从哪里来”(`src`)和“到哪里去”(`dest`),可以配置多个复制任务。
* **Vite 规范:** 它是 Vite 生态的一员,遵循 Vite 的构建流程,兼容性好。
* **路径处理:** 使用 `path.resolve``normalizePath` 可以确保路径在不同操作系统上都能正确识别。

## 5. 总结一下

* **遇到的问题:** Taro 项目升级到 Vite 后,原有的静态资源复制方式失效,Vite 默认的 `public` 目录复制行为不满足自定义目标路径(例如,不仅仅是字体,还包括图片、JSON等其他静态资源需要复制到 `dist/static/` 下的特定子目录)的需求。
* **解决方案:** 引入并配置 `vite-plugin-static-copy` Vite 插件,通过其 `targets` 选项精确指定各类静态资源的源文件目录和相对于输出目录的目标路径,从而实现将 `public/` 下的各种静态资源(如 `public/font/``public/images/`)复制到期望的 `dist/` 目录下的指定位置(如 `dist/static/font/``dist/static/images/`)。

搞定!希望这个小小的踩坑和填坑记录能帮到有类似需求的朋友们。