使用React、Typescript和Webpack显示静态图像

16

我正在尝试在使用webpack和webpack-dev-server的项目中将图像显示在React组件中。

到目前为止,我已完成以下步骤:

  • 使用npm安装了file-loader
  • 更新了webpack.config.js以添加图片文件的加载器
  • 将所需图片导入到我的组件中
  • 在我的img标记中使用了这个导入

采取这些步骤后,webpack编译失败,出现“找不到模块”的错误:

ERROR in [at-loader] ./src/components/App.tsx:4:26
    TS2307: Cannot find module '../images/kitten-header.jpg'.

我的文件夹结构如下:

/dist
   /images
      kitten-header.jpg
   bundle.js
   bundle.js.map
/node_modules
   (content ignored for brevity)
/src
   /components
      App.tsx
   /images
      kitten-header.jpg
   /styles
      App.less
   index.tsx
index.html
package.json
tsconfig.json
webpack.config.js 

我添加到webpack.config.js的新装载程序是:

test: /\.(jpe?g|gif|png|svg)$/, loader: "file-loader?name=./images/[name].[ext]"

我已经在App.tsx中像这样导入了图像文件:

import kittenHeader from '../images/kitten-header.jpg';

...并在img标签中使用import,如下所示:

<img src={ kittenHeader } />

注意: 提供了webpack.config.js和App.tsx的完整文本,直到我接近答案时意识到它们并不相关(请参见更新1)。

我认为我在相对路径导入方面犯了一些非常微小的错误。正如您所想象的那样,我尝试了各种替代方案。

有人能提供一些见解吗?

供参考,因为我不断地碰到与错误版本的webpack有关的文章和问题,这里是我的版本:

  • React 15.5.4
  • Webpack 2.6.1
  • Webpack-dev-server 2.4.5
  • TypeScript 2.3.2


更新1: 2017.06.05
所以,看着这个SO问题Medium上的这篇文章,我已经确定问题不在于如何使用webpack,而在于我正在使用TypeScript。错误是由于typescript编译器不知道什么是.jpg文件引起的typescript错误。

显然,我需要提供一个d.ts文件或使用require语句。

快到了...


你是否有一个源代码存储库,我们可以使用它来重现问题?那将非常方便。 - Pavel Denisjuk
谢谢@EvanSebastian,你的评论正好在我写答案的时候出现了。正如你所看到的,我的答案是不完整的。你知道如何为jpg编写d.ts吗?是否可以创建一个模块来覆盖*.jpg,还是每个图像文件都需要一个d.ts? - Montgomery 'monty' Jones
我还注意到你推荐了 @types/webpack-env,而我使用的是 @types/node。Node 类型确实可以工作。这两者在让 'require' 工作方面有什么区别?我假设它们只是相同底层 'require' 实现的两个 d.ts 定义? - Montgomery 'monty' Jones
@types/webpack-env and @types/node are different, you use @types/node when you need to write NodeJS modules to make standard library typings available. @types/webpack-env is used when you are in a webpack bundled project. For instance, require.ensure will be available if you use @types/webpack-env - Evan Sebastian
如果您喜欢使用 .d.ts,则语法如下:https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#wildcard-character-in-module-names在这种情况下,您希望 export default 具有类型 string - Evan Sebastian
显示剩余3条评论
7个回答

14

使用常规的require,在tsx文件中使用的方式如下:

const logo = require('../assets/logo.png');

...

<img alt='logo' style={{ width: 100 }} src={String(logo)} />
希望这能帮到你。对我来说,import也不起作用。

4
这是我让它正常工作的方法:
// This declaration can be move in some common .d.ts file, will prevent tslint from throwing error
declare function require(path: string);

const SampleComponent = () => (
  <div>
    <img src={require('./styles/images/deadline.png')} alt="Test" />
  </div>
);

您在答案中提出的方法将导致需要为放置在组件中的每个图像文件编写模块声明。

2
错误信息“TS2307: Cannot find module '../images/kitten-header.jpg'”提示TypeScript编译器无法理解导入.jpg文件的操作。
尽管编译错误出现,但由于图片文件已经成功复制到dist文件夹中,因此webpack配置是正常的。
我们有两种方法可以解决这个问题。 首先,我们可以通过使用“require”语句绕过TypeScript的导入。要做到这一点,将导入语句...
import kittenHeader from '../images/kitten-header.jpg';

...可以被替换为一个 require...

const kittenHeader = require('../images/kitten-header.jpg');

...然后就是所有需要的了。

注意,在我的情况下,我还需要安装一些类型支持“require”语句。如果没有这些,我会得到一个TS2304:找不到名称“require”的错误。

最初,我使用了@types/node,如此SO答案中所述,但@EvanSebastian指出node旨在支持编写NodeJS模块,而这不是我正在做的事情(请参见问题的注释)。

我尝试了@types/webpack-env,如建议的那样,但这导致了对我的图像标记的src属性的TS2322:类型'{src:{};}'不能分配给类型'HTMLProps<HTMLImageElement>'。错误。

最近,我切换到使用@types/requirejs,希望它足够专注,避免包含大量不适当的其他类型。目前它正常工作:

npm install @types/requirejs --save-dev
或者,我们可以保留导入并提供一个d.ts文件,其中包含声明适当模块的类型信息。我无法确定这个文件应该是什么样子的。

0

尝试我的代码,在你想要的 React-Typescript 组件中

import * as logo from './assests/icon.jpg';

const img = logo.default;

const Comp = ()=> {
    return <img src={img} alt="image" className="" />
}

仅提供代码的答案是不可取的。 - JustCarty

0
在您的src目录中的任何位置添加一个typescript定义文件(例如命名为image.d.ts) 像这样导出jpeg文件的模块定义:
export module "*.jpg";

0

const logo = require('../../../assets/img/logo.svg')

 <img src={logo.default} style={{ width: "100%", height: "50px" }} alt="" />


3
考虑添加代码解释以帮助读者理解它如何回答问题。当回答一个有多个答案的问题时,解释你的答案与其他答案的不同之处或改进之处也是很有用的。 - rmlockerd

-1

除了mcku的回答,你也可以这样使用imports:

// @ts-ignore
import * as kittenHeader from '../images/kitten-header.jpg';
...
<img alt='logo' style={{ width: 100 }} src={logo} />

虽然你必须忽略这个警告。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接