如何配置 vite 来加载从 node_modules 导入的样式表中的相关图像?

发布于 2025-01-14 22:42:07 字数 1962 浏览 0 评论 0原文

我有一个应用程序,它使用 UIkit,Less 用于本地样式,Vite 用于前端工具(捆绑等)。我不确定这是否相关,但这是一个 Vue 2/Webpack 应用程序,我正在升级到 Vue 3/Vite。

根据 UIkit 的 Less 文档,我们将 UIkit 的 uikit.theme.less 文件导入到我们项目的基本文件较少。 UIkit 的样式表有一些到 SVG 文件的相对路径,这些路径通过 less 的 data- 运行uri 函数(示例如下)。这在 Webpack 中工作得很好,但在 Vite 中却不太有效。据我了解,对于小文件,data-uri 将对资源进行 UTF-8 编码,并本质上内联它——至少我们在 Webpack 包中是这样的。但在我们的 Vite 构建中,这些相对图像路径似乎没有被解析,data-uri 因此回落到 url(),我们得到 404 错误图像。

例如,在 UIkit 的代码中,旋转图像的相对路径被定义为 此处;它用在 select.uk-select 中。以及此处该路径被传递到 .svg-fill mixin (此处)。当我们使用 Vite 捆绑代码或运行本地开发服务器时,结果是:

background-image: url(../../images/backgrounds/form-select.svg);

当然,不会加载,因为“images”目录是相对于 form.less 文件的。在 Webpack 中,输出符合预期:

background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='24' height='16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23001c30' d='M12 1 9 6h6zM12 13 9 8h6z'/%3E%3C/svg%3E");

对于此类问题,我通常会包含 HTML/CSS/JS 片段;不过,我认为SO不支持Vite。因此,我添加了一个小型 Stackblitz 来最低限度地演示该问题: https: //stackblitz.com/edit/vite-esqmqc?file=main.js 请参阅 main.jsstyle.less,并注意有一个控制台中出现 404 错误,抱怨上述 form-select.svg 文件。

如果问题不清楚,如何让 Vite 解析与 node_modules 中的依赖项相关的图像?

提前致谢。

I have an application that uses UIkit, Less for local styling, and Vite for frontend tooling (bundling and whatnot). I'm not sure that this is relevant, but this is a Vue 2/Webpack application that I'm upgrading to Vue 3/Vite.

Per UIkit's Less documentation, we import UIkit's uikit.theme.less file in our project's base less file. UIkit's stylesheets have some relative paths to SVG files that get run through less's data-uri function (examples below). That worked fine with Webpack, but with Vite it's not quite working. As I understand it, for small files, data-uri will UTF-8 encode the asset and essentially inline it--at least that's what we got in our Webpack bundles. But with our Vite build, it seems these relative image paths aren't being resolved, data-uri hence falls back to a url(), and we get 404s for the images.

For example, in UIkit's code the relative path to a spinner image is defined here; it's used in a select.uk-select. And here that path is passed to a .svg-fill mixin (here). When we bundle the code using Vite, or run a local dev server, the result is:

background-image: url(../../images/backgrounds/form-select.svg);

That, of course, doesn't load because the "images" directory is relative to the form.less file. In Webpack, the output was as expected:

background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='24' height='16' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23001c30' d='M12 1 9 6h6zM12 13 9 8h6z'/%3E%3C/svg%3E");

For this type of question, I would normally include an HTML/CSS/JS snippet; however, I don't think SO supports Vite. As such, I'm including a small Stackblitz that minimally demonstrates the issue: https://stackblitz.com/edit/vite-esqmqc?file=main.js Please see main.js, style.less, and note that there's a 404 error in the console complaining about the aforementioned form-select.svg file.

In case the question isn't clear, how can I get Vite to resolve images which are relative to a dependency in node_modules?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城°AllureLove 2025-01-21 22:42:07

解决方法是将 resolve.alias 配置为指向 ../../imagesuikit/src/images (解析为 node_modules/ 下的 uikit 包) 。这告诉 Vite 如何解决 问题相对图像路径

resolve.alias 配置作为 条目。每个条目都可以有一个自定义解析器,可以用于仅替换来自 UIKit 的导入。但是,它要求 uikit.theme.less 的导入位于其自己的文件中,以便自定义解析器可以正确识别导入器,从而确定何时替换导入。

  1. uikit.theme.less 的导入放入其自己的文件中,然后从 main.js 导入(而不是从 style.less):
// style.less
// @import './node_modules/uikit/src/less/uikit.theme.less'; ❌ move to own file
// my-uikit.less
@import './node_modules/uikit/src/less/uikit.theme.less';
// main.js
import './style.less';
import './my-uikit.less';
  1. 使用以下配置创建 vite.config.js
// vite.config.js
import { defineConfig } from 'vite';
import { fileURLToPath } from 'url';
import { basename } from 'path';

export default defineConfig({
  resolve: {
    alias: [
      {
        find: '../../images',
        replacement: '',
        customResolver(updatedId, importer, resolveOptions) {
          // don't replace if importer is not our my-uikit.less
          if (basename(importer) !== 'my-uikit.less') {
            return '../../images';
          }

          return fileURLToPath(
            new URL(
              './node_modules/uikit/src/images' + updatedId,
              import.meta.url
            )
          );
        },
      },
    ],
  },
})

演示

A workaround is to configure resolve.alias to point ../../images to uikit/src/images (which resolves to the uikit package under node_modules/). This tells Vite how to resolve the problematic relative image paths.

The resolve.alias config is passed to @rollup/plugin-alias as entries. Each entry can have a custom resolver that can be used to only replace imports from UIKit. However, it requires that the import of uikit.theme.less be in its own file so that the custom resolver can correctly identify the importer in order to determine when to replace the import.

  1. Put the import of uikit.theme.less in its own file, and import that from main.js (not from style.less):
// style.less
// @import './node_modules/uikit/src/less/uikit.theme.less'; ❌ move to own file
// my-uikit.less
@import './node_modules/uikit/src/less/uikit.theme.less';
// main.js
import './style.less';
import './my-uikit.less';
  1. Create vite.config.js with the following configuration:
// vite.config.js
import { defineConfig } from 'vite';
import { fileURLToPath } from 'url';
import { basename } from 'path';

export default defineConfig({
  resolve: {
    alias: [
      {
        find: '../../images',
        replacement: '',
        customResolver(updatedId, importer, resolveOptions) {
          // don't replace if importer is not our my-uikit.less
          if (basename(importer) !== 'my-uikit.less') {
            return '../../images';
          }

          return fileURLToPath(
            new URL(
              './node_modules/uikit/src/images' + updatedId,
              import.meta.url
            )
          );
        },
      },
    ],
  },
})

demo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文