为啥我必须对 React 中的图像使用“require”而不是“import from”?

Posted

技术标签:

【中文标题】为啥我必须对 React 中的图像使用“require”而不是“import from”?【英文标题】:Why do I have to use "require" instead of "import from" for an image in React?为什么我必须对 React 中的图像使用“require”而不是“import from”? 【发布时间】:2019-02-22 17:25:05 【问题描述】:

我看到this answer 建议导入图像的语法如下所示(已注释掉)。就我而言,它没有成功(抱怨在该文件中找不到模块),我不得不切换到当前处于活动状态的语法。

// import Author from "../assets/author.png";
var Author = require("../assets/author.png");

我可以想象的不同之处在于我使用的是 TypeScript(通过 awesome-typescript-loader 转译我的 TSX 并加载我的 PNG file-loader)而且它们看起来使用 JSX。但就我的理解而言,这一切都转译为纯 JS,最后 require

作为 React 的菜鸟,我不确定造成这种差异的原因是什么但也我不知道该用谷歌搜索什么来调查自己。

【问题讨论】:

查看this question的答案 【参考方案1】:

这更多是 typescript 的问题,而不是 webpack 本身,您可能需要在声明文件中声明模块。

创建一个declarations.d.ts

更新你的 tsconfig.json

"include": [
    "./declarations.d.ts",
],

把这个放在那个文件上:

declare module '*.png';

错误可能消失了。

【讨论】:

不,我按照你的建议做了,但错误仍然存​​在。它仍然抱怨无法找到模块并且图像未呈现。 嗯,这超出了我从 ts 了解的范围。你能分享整个错误信息吗? ERROR in [at-loader] ./src/components/MainArea.tsx:3:21 然后 TS2307: 找不到模块 '../assets /author.png'。【参考方案2】:

你可以像这样为你的图片声明一个模块:

declare module "*.png" 
  const value: any;
  export default value;

然后,您将能够像这样导入您的图像:

import AuthorSrc from "../assets/author.png";

这是因为 webpack 不支持开箱即用的图像导入。因此,您需要在 webpack 配置文件中为此添加规则。当您添加新规则时,TypeScript 不会自动知道这一点,因此您需要声明一个新模块来解决此问题。如果没有该模块,您将能够导入图像,但 TypeScript 会抛出错误,因为您没有告诉它是可能的。

【讨论】:

它似乎已经消除了错误但是我看不到图像,只是它周围的边框,而背景与其余部分相同页。我使用以下规则加载图像:test: /\.(png)$/,use: [ loader: "file-loader" ]。你能想象一个更合适的吗? 另外,我很好奇 const value: any; export default value; 相当于简单地设置一个分号而不是大括号。我看到人们这样声明模块:declare module "bzz"; 我不清楚它是否是 declare module "bzz"... 的简写。 【参考方案3】:

这个问题与 webpack 或任何 bundler 无关,也不是 typescript 的问题。

Typescript 声明 `require("path") 是一种将模块包含到当前模块范围内的方法,同时它也可以用于读取一些随机文件(例如 json 文件)。

正如 Vincent 和 Playma256 所指定的,您可以声明一个模块通配符以匹配某些文件类型,因此您可以将其作为导入语句导入。但你真的不需要这样做。如果您尝试导入 png 或 json 文件,Typescript 不会给您错误(tslint 可能,但这取决于您的配置)。

顺便说一句,如果您的声明位于 tsconfig.json 中定义的项目的源文件夹中,则无需按照 Playma256 的规定包含它。

我在 node 中创建了一个示例项目供您测试:

https://github.com/rodrigoelp/typescript-declare-files

【讨论】:

我不完全确定它是否正确。如果我理解正确,您导入一个 JSON 文件而不是图像,并且由于您使用的是哪种加载器,这实际上可能会有所不同,不是吗?我正在为我的 PNG 使用 file-loader 并且我正在看到图像应该在的位置周围的边框(但没有实际图像)。您真的看到正在渲染的图像吗? (错误信息消失了,所以答案有点正确-但我也想见作者,呵呵。) 另外,我见过 declare module ".xxx";* 和 declare module ".xxx"const v:any;返回默认 v*。那些是等价的吗? 嗨@DonkeyBanana,试图给你一些背景信息:“我正在使用什么样的装载机?”如果您指的是捆绑程序,我直接使用 node 进行了测试,但也使用 webpack 和 metro 进行了测试。 “我正在导入一个 json 文件而不是 png”,打字稿完成的编译将是相同的。任何导入语句都被转换为要求,AFAIK。应该没什么区别。当我做我的小测试时,我确实看到了图像,但我的测试是使用 react 完成的(我认为你正在做同样的事情) 关于:declare module "*.xxx"; 是否等同于 declare module "*.xxx" const v: any; export default v ?不,第一个只是用该名称声明模块的存在,第二个告诉 typescript 它需要默认捕获已导出的实例或定义。 请原谅我在提出问题时的无知。我不是指捆绑器的类型(顺便说一句,我总是使用 Webpack)。但是,当配置它时,有一个规则部分,其中,我必须为 TS、style-loadercss 指定 awesome-typescript-loader -loadersass-loader 用于 SCSS,还有 file-loader,这应该是静态文件(即我的 PNG)所必需的。我要问的是 file-loader 是否是 Webpack 配置在页面上呈现 PNG 图像的首选。【参考方案4】:

我认为你可以用 Webpack&&typescript 解决这个问题。webpack 的官方网页在 https://webpack.js.org/guides/typescript/ 我自己也试过这个 https://github.com/reactpersopnal/webpack-root/tree/feature/typescript 原因是您想在 TypeScript 中使用非代码资产,因此我们需要为 webpack 的这些导入延迟类型。 您可以简单地添加 custom.d.ts。

declare module "*.jpg" 
    const content: any;
    export default content;

【讨论】:

以上是关于为啥我必须对 React 中的图像使用“require”而不是“import from”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 react-bootstrap 中映射图像显示错误(重复输出)

为啥 setState() 在我的情况下不能在 React 中工作?

为啥使用 matplotlib 无法正确显示 CIFAR-10 图像?

为啥我必须将它绑定到 Reactjs 的类组件中的方法

从 React 上传 Cloudinary 图像:我包括 Cloudinary 未签名预设,但得到“使用未签名上传时必须指定上传预设”

React 中的内联背景图像