如何在 React 和 Webpack 项目中使用来自 sharp 模块的图像
How to use images from sharp module in React and Webpack project
这是一个codesandbox I would like the image in it to be processed by the sharp module。我希望它这样做是因为我希望这个模块对我的 React 项目中的所有图像进行网络优化,并将它们转换为 webm。
这是我尝试使用 ImageSharp
的相同 codesandbox
我会在根目录中创建一个 convert.js 来进行文件转换。检查锐利 docs.
然后在package.json中只需在任何需要图像转换的脚本之前添加'node convert'专门启动和构建
"start": "node convert && react-scripts start",
"build": "node convert && react-scripts build",
现在,无论何时启动本地服务器或构建您的应用程序,它都会先转换图像,然后再执行其余的。
这是一个简单的示例,其中 convert.js 仅将名为 1.jpeg 的文件转换为尺寸为 320x240 的 output.webp。
这完全取决于您喜欢如何组织项目中的图像大小、文件夹和文件,以便 covert.js 可以找到它们并正确转换它们。
const sharp = require('sharp');
sharp('1.jpeg')
.resize(320, 240)
.toFile('output.webp', (err, info) => { });
您需要进行一些更改:
Webpack.config.js
- 将
sharp-loader
移动到rules
:
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
...
{
test: /\.(gif|jpe?g|png|svg|tiff)(\?.*)?$/,
loader: "sharp-loader",
query: {
name: "[name].[hash:8].[ext]",
cacheDirectory: true,
presets: {
// Preset 1
thumbnail: {
format: ["webp", "jpeg"],
width: 200,
quality: 60
},
// Preset 2
prefetch: {
// Format-specific options can be specified like this:
format: { id: "jpeg", quality: 30 },
mode: "cover",
blur: 100,
inline: true,
size: 50
}
}
}
}
]
},
devServer: {
...
},
plugins: [
...
]
};
如果你正在使用 Webpack 5:
Rule.query is deprecated in favor of Rule.options and
UseEntry.options.
Home.js
- 因为这个
"outputs":[{"width": 500}]
,sharp-loader
会将logo转换成一个对象的数组。您将需要使用相应的对象:
import React from "react";
import logo from '../../react-logo.png?{"outputs":[{"width": 500}]}';
export default function Home() {
return (
<div>
<h2>Home</h2>
<img src={logo[0].url} />
</div>
);
}
如果您使用 require.context
,它的工作方式相同:
import React from "react";
function importAll(r) {
return r.keys().reduce((curr, key) => ((curr[key] = r(key)), curr), {});
}
const images = importAll(require.context('./images/?{"outputs":[{"width": 200}, {"width": 150}]}', true, /\.png$/));
export default function Home() {
return (
<div>
<h2>Home</h2>
<img src={images['./react-logo.png'][0].url} />
</div>
);
}
这是一个codesandbox I would like the image in it to be processed by the sharp module。我希望它这样做是因为我希望这个模块对我的 React 项目中的所有图像进行网络优化,并将它们转换为 webm。
这是我尝试使用 ImageSharp
的相同 codesandbox我会在根目录中创建一个 convert.js 来进行文件转换。检查锐利 docs.
然后在package.json中只需在任何需要图像转换的脚本之前添加'node convert'专门启动和构建
"start": "node convert && react-scripts start",
"build": "node convert && react-scripts build",
现在,无论何时启动本地服务器或构建您的应用程序,它都会先转换图像,然后再执行其余的。
这是一个简单的示例,其中 convert.js 仅将名为 1.jpeg 的文件转换为尺寸为 320x240 的 output.webp。 这完全取决于您喜欢如何组织项目中的图像大小、文件夹和文件,以便 covert.js 可以找到它们并正确转换它们。
const sharp = require('sharp');
sharp('1.jpeg')
.resize(320, 240)
.toFile('output.webp', (err, info) => { });
您需要进行一些更改:
Webpack.config.js
- 将
sharp-loader
移动到rules
:
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
...
{
test: /\.(gif|jpe?g|png|svg|tiff)(\?.*)?$/,
loader: "sharp-loader",
query: {
name: "[name].[hash:8].[ext]",
cacheDirectory: true,
presets: {
// Preset 1
thumbnail: {
format: ["webp", "jpeg"],
width: 200,
quality: 60
},
// Preset 2
prefetch: {
// Format-specific options can be specified like this:
format: { id: "jpeg", quality: 30 },
mode: "cover",
blur: 100,
inline: true,
size: 50
}
}
}
}
]
},
devServer: {
...
},
plugins: [
...
]
};
如果你正在使用 Webpack 5:
Rule.query is deprecated in favor of Rule.options and UseEntry.options.
Home.js
- 因为这个
"outputs":[{"width": 500}]
,sharp-loader
会将logo转换成一个对象的数组。您将需要使用相应的对象:
import React from "react";
import logo from '../../react-logo.png?{"outputs":[{"width": 500}]}';
export default function Home() {
return (
<div>
<h2>Home</h2>
<img src={logo[0].url} />
</div>
);
}
如果您使用 require.context
,它的工作方式相同:
import React from "react";
function importAll(r) {
return r.keys().reduce((curr, key) => ((curr[key] = r(key)), curr), {});
}
const images = importAll(require.context('./images/?{"outputs":[{"width": 200}, {"width": 150}]}', true, /\.png$/));
export default function Home() {
return (
<div>
<h2>Home</h2>
<img src={images['./react-logo.png'][0].url} />
</div>
);
}