返回

Vite 处理构建外URL:API与资源优化策略

vue.js

Vite 如何处理构建系统之外的 URL

在使用 Vite 进行前端项目构建时,常常会遇到一种情形:需要引用构建系统之外的 URL,例如 API 端点,或者一些动态生成的资源。这种需求很常见,特别是在前后端分离的架构中,前端应用需要与后端 API 进行通信。Vite 作为一种高效的构建工具,提供了多种处理此类情况的方式。

问题在于,Vite 默认情况下会尝试解析所有的 URL 引用,当遇到那些并不在构建流程中的 URL(例如 /api/*),就会抛出错误。这就需要开发者采取一些策略来引导 Vite 跳过对这些 URL 的解析和处理,让其直接传递到浏览器环境中。

问题分析

Vite 默认将应用代码视作模块化的代码,对于在 JavaScript 或 Vue 等组件中使用的 import/export 语句中的 URL,以及像 img 标签 src 中的 URL 都视作静态资源,并且尝试去构建系统中解析,这导致当访问如 /api/* 这类不在项目构建目录的 API 时构建出错。要解决这类问题,就需要告诉 Vite:这些 URL 是不需要打包处理的。

解决方案一:使用代理服务器进行请求重定向

此方案适用于开发阶段。可以通过 Vite 配置文件的 server.proxy 属性,配置代理规则,让对特定路径的请求(例如 /api/*)被重定向到对应的服务器。

  • 工作原理 :当应用发出请求到 /api/*,Vite 开发服务器会拦截这个请求,将其转发到配置的目标服务器。目标服务器可以是本地的 API 服务,也可以是一个测试环境的地址。

  • 代码示例 (vite.config.js):

    import { defineConfig } from 'vite';
    import vue from '@vitejs/plugin-vue';
    
    export default defineConfig({
      plugins: [vue()],
      server: {
        proxy: {
          '/api': {
            target: 'http://localhost:8080', //  替换成你的后端 API 地址
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/api/, ''),
          },
        },
      },
    });
    
  • 操作步骤

    1. 打开 vite.config.js 文件。
    2. server 对象中,配置 proxy 属性。
    3. 定义需要代理的路径,如上述例子中的 /api, 并指定对应的 target (即实际API服务的地址), changeOrigin 设置为 true 表示在转发请求时修改 HTTP 请求头中的 origin 为目标服务器的域名。 rewrite 可以在转发请求时改写URL路径,这在有些后端服务场景中会很有用。
    4. 保存文件,并重新启动 Vite 开发服务器。

这个方案的优点是简单易用,尤其在开发环境下快速配置API接口,缺点则是不能应用于生产环境的部署。生产环境下需要有专门的反向代理来配置类似功能。

解决方案二:配置 assetsInclude 来识别静态资源

这个方法适用于 Vite 在构建过程,会默认把指定后缀名和大小的静态资源作为可构建的静态资源处理。如果静态资源不在项目构建目录内,Vite 就无法正确的找到资源,出现类似路径无法解析的情况,通过 assetsInclude 我们可以定义需要纳入构建的额外资源,即使这些资源在构建系统中实际并不存在。但配置该参数会让 Vite 在编译过程中尝试分析路径并拷贝资源,即便不需要也要生成相关处理逻辑,可能会增大包体积并导致不必要的操作。

  • 工作原理assetsInclude 配置项可以让 Vite 将特定的文件路径,纳入到静态资源的构建处理流程中。通过将/api/icon.png这类资源告知 Vite 需要将其当做静态资源来处理,避免被当作模块来解析,从而解决构建过程中出现无法找到对应资源路径的问题。

  • 代码示例 (vite.config.js):

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
export default defineConfig({
  plugins: [vue()],
    assetsInclude: ["/api/**"],
  build: {
    rollupOptions: {
      output: {
        assetFileNames: 'assets/[name].[ext]',
      }
    }
  },
});
  • 操作步骤
    1. 打开 vite.config.js 文件。
    2. 添加或修改 assetsInclude 数组,并添加对应的路径模式(支持glob patterns语法)。
    3. 可选的步骤,为使 Vite 在构建后保留 asset 的原本结构, 可以修改output.assetFileNames 配置项.
    4. 保存文件并重新执行 Vite 构建。

这种方式的优点是:允许直接引入 API 端的图片资源,可以实现动态替换的功能。 缺点则是在静态资源构建层面配置处理这些特殊 URL ,可能会影响实际编译和输出产物结构。

解决方案三:配置 rollupOptions.external

rollupOptions.external 可以让 Vite 跳过对指定的 import URL 的解析和处理,不将他们加入构建流程。配置这个参数会指示 Rollup 构建工具(Vite 基于 Rollup)不打包指定的 URL,而是保持它们的引用方式。

  • 工作原理 :此选项的工作机制与 assetsInclude 正好相反。将类似 /api/icon.png URL 加入 external 列表后,Rollup 不会尝试加载这个模块,也不对其进行任何转换, 而是直接将这个路径作为外部模块处理,这意味着浏览器将尝试直接获取该 URL 对应的资源。
  • 代码示例 (vite.config.js):
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
    build: {
        rollupOptions: {
            external: [ '/api/**'],
        }
    }
});
  • 操作步骤
    1. 打开 vite.config.js 文件。
    2. 添加 build.rollupOptions.external 选项,并添加需要排除的路径,支持使用glob 匹配
    3. 保存文件,并重新执行 Vite 构建。

此方案比较直接,通过 external 告诉 Rollup 这些 URL 需要排除在外,避免编译报错。但是当项目比较复杂的时候可能会因为配置不合理导致模块依赖出现问题。

安全建议

上述方案都在尽力解决构建过程中如何合理处理特定URL的问题。 但在实践中还需关注安全性:

  • 避免在前端代码中暴露敏感信息(如API 密钥)。将它们存储在后端环境或者使用环境变量。
  • 限制 API 端点的访问权限,并采用 HTTPS 协议进行数据传输。
  • 在生产环境中使用反向代理服务器来处理 API 请求,而不是直接在前端暴露后端服务的地址。

处理构建系统之外的 URL 是常见的挑战,Vite 提供多种方式处理。选择合适的方法,能提升开发效率并确保应用的可靠性。理解这些方案的差异以及适用的场景,能够更好地使用 Vite 构建应用。