Node js 服务器不在 React 应用程序中显示图像
Node js server doesn't display images in React app
我在前端有一个站点,因此决定向其添加后端(以获取数据并进行一般修改)。后端给前端提供数据,但是图片有问题,不知道为什么。 data.js提供了_id,URL,title,flavor,category,region,variety,description,但是没有图片(Failed to load resource:服务器响应状态为404(Not Found))。
不幸的是,我试图搜索答案,但没有找到适合我的答案。前端也是我自己配置的webpack5
这里是 link 回购:link to the repo。
下面我为大家介绍所有重要信息:
节点 v16.13.2
我的文件结构:
mainFolder
- backend
-- data.js
-- server.js
- frontend
-- config
--- webpack.common.js
--- webpack.config.js
--- webpack.dev.js
--- webpack.prod.js
-- public
--- folder
---- pic.jpg
-- src
--- (...)
---- frontend.js
-- (...)
-- package.json (in frontend folder)
- package.json (in root folder)
package.json(在根文件夹中):
{
"name": ...,
"type": "module",
"version": ...,
"description": ...,
"author": ...,
"license": ...,
"main": ...,
"scripts": {
"start": "nodemon --watch backend --exec node --experimental-modules backend/server.js"
},
"dependencies": {
"express": "^4.17.2"
},
"devDependencies": {
"nodemon": "^2.0.15"
}
}
package.json(在前端文件夹中):
{
"name": ...,
"proxy": "http://127.0.0.1:8000",
"version": ...,
"description": ...,
"author": ...,
"license": ...,
"main": ...,
"scripts": {
"start": "webpack serve --config config/webpack.config.js --env env=dev",
"build": "webpack --config config/webpack.config.js --env env=prod"
},
"devDependencies": {...},
"dependencies": {...}
}
server.js:
import express from 'express'
import data from './data.js'
const app = express()
const port = process.env.PORT || 8000
app.get('/api/products', (req, res) => {
res.send(data.products)
})
app.get('/', (req, res) => {
res.send('server is ready')
})
app.listen(port, () => {
console.log(`serve at http://localhost:${port}}`)
})
data.js:
const data = {
products: [
{
_id: 1,
url: 'url',
title: 'title',
flavor: 'flavor',
category: 'category',
image: '/images/folder/pic.jpg',
region: 'region',
variety: 'variety',
description:'description',
},
{...},
],
}
export default data
frontend.js:
import { Link } from 'react-router-dom'
import { useEffect, useState } from 'react'
import axios from 'axios'
const Frontend = ({ match }) => {
const [products, setProducts] = useState([])
useEffect(() => {
const fetchData = async () => {
const { data } = await axios.get('/api/products')
setProducts(data)
}
fetchData()
}, [])
const list = products.map((product) => (
<li key={product._id}>
<Link to={`${match.url}/${product.url}`}>
<img
src={product.image}
alt={product.url}
/>
<div>
<h2>{product.title}</h2>
<p>{product.flavor}</p>
<button>View more</button>
</div>
</Link>
</li>
))
return (
<div>
<ul>{list}</ul>
</div>
)
}
export default Frontend
webpack.common.js:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.resolve(__dirname, '..', './src/index.js'),
output: {
path: path.resolve(__dirname, '..', './dist'),
filename: '[name].[contenthash:6].js',
clean: true,
publicPath: '/',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|mp4)$/i,
type: 'asset/resource',
},
{
test: /\.(woff(2)?|eot|ttf|otf|svg|pdf)$/,
type: 'asset/inline',
},
],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
plugins: [
new HtmlWebpackPlugin({
title: '...',
template: path.resolve(__dirname, '..', './src/template/template.html'),
favicon: path.resolve(__dirname, '..', './public/favicon.ico'),
filename: 'index.html',
}),
],
}
webpack.config.js:
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
module.exports = ({ env }) => {
const envConfig = require(`./webpack.${env}.js`)
return merge(commonConfig, envConfig)
}
webpack.dev.js:
const path = require('path')
const Dotenv = require('dotenv-webpack')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
module.exports = {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
proxy: {
'/api': 'http://localhost:8000',
},
historyApiFallback: true,
contentBase: path.resolve(__dirname, '..', './dist'),
open: true,
hot: true,
compress: true,
port: 8080,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
plugins: [require.resolve('react-refresh/babel')],
},
},
],
},
{
test: /\.(s[ac]|c)ss$/i,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
],
},
plugins: [
new Dotenv({
path: path.resolve(__dirname, '..', './.env.development'),
}),
new ReactRefreshWebpackPlugin(),
],
}
webpack.prod.js:
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const Dotenv = require('dotenv-webpack')
module.exports = {
mode: 'production',
devtool: 'source-map',
output: {
path: path.resolve(__dirname, '..', './dist'),
filename: 'js/[name].[contenthash:6].js',
},
module: {
rules: [
{
test: /\.(s[ac]|c)ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles/[name].[contenthash:6].css',
chunkFilename: '[id].css',
}),
new Dotenv({
path: path.resolve(__dirname, '..', './.env.production'),
}),
],
optimization: {
minimize: true,
minimizer: [new CssMinimizerPlugin(), '...'],
runtimeChunk: {
name: 'runtime',
},
},
}
我看到您没有在 Express 应用中使用静态文件。您应该将静态文件添加到您的 Express 应用程序,并在您的后端服务器上提供图片。
基本上可以看看这个document.
此外,如果您喜欢视频,可以观看此 video。
首先,你的后台文件应该是这样的;
backend
-server.js
-data.js
-public
--images
---coffee
----pic.jpg
这里是 server.js 文件:
import express from 'express'
import data from './data.js'
import path from 'path'
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const app = express()
const port = process.env.PORT || 8000
app.get('/api/products', (req, res) => {
res.send(data.products)
})
app.get('/', (req, res) => {
res.send('server is ready')
})
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
app.use(express.static(path.join(__dirname,'public')))
app.use('/static',express.static('public'))
app.listen(port, () => {
console.log(`serve at http://localhost:${port}}`)
})
// go to 'http://localhost:8000/images/coffee/pic.jpg' it will work
我在前端有一个站点,因此决定向其添加后端(以获取数据并进行一般修改)。后端给前端提供数据,但是图片有问题,不知道为什么。 data.js提供了_id,URL,title,flavor,category,region,variety,description,但是没有图片(Failed to load resource:服务器响应状态为404(Not Found))。
不幸的是,我试图搜索答案,但没有找到适合我的答案。前端也是我自己配置的webpack5
这里是 link 回购:link to the repo。
下面我为大家介绍所有重要信息:
节点 v16.13.2
我的文件结构:
mainFolder
- backend
-- data.js
-- server.js
- frontend
-- config
--- webpack.common.js
--- webpack.config.js
--- webpack.dev.js
--- webpack.prod.js
-- public
--- folder
---- pic.jpg
-- src
--- (...)
---- frontend.js
-- (...)
-- package.json (in frontend folder)
- package.json (in root folder)
package.json(在根文件夹中):
{
"name": ...,
"type": "module",
"version": ...,
"description": ...,
"author": ...,
"license": ...,
"main": ...,
"scripts": {
"start": "nodemon --watch backend --exec node --experimental-modules backend/server.js"
},
"dependencies": {
"express": "^4.17.2"
},
"devDependencies": {
"nodemon": "^2.0.15"
}
}
package.json(在前端文件夹中):
{
"name": ...,
"proxy": "http://127.0.0.1:8000",
"version": ...,
"description": ...,
"author": ...,
"license": ...,
"main": ...,
"scripts": {
"start": "webpack serve --config config/webpack.config.js --env env=dev",
"build": "webpack --config config/webpack.config.js --env env=prod"
},
"devDependencies": {...},
"dependencies": {...}
}
server.js:
import express from 'express'
import data from './data.js'
const app = express()
const port = process.env.PORT || 8000
app.get('/api/products', (req, res) => {
res.send(data.products)
})
app.get('/', (req, res) => {
res.send('server is ready')
})
app.listen(port, () => {
console.log(`serve at http://localhost:${port}}`)
})
data.js:
const data = {
products: [
{
_id: 1,
url: 'url',
title: 'title',
flavor: 'flavor',
category: 'category',
image: '/images/folder/pic.jpg',
region: 'region',
variety: 'variety',
description:'description',
},
{...},
],
}
export default data
frontend.js:
import { Link } from 'react-router-dom'
import { useEffect, useState } from 'react'
import axios from 'axios'
const Frontend = ({ match }) => {
const [products, setProducts] = useState([])
useEffect(() => {
const fetchData = async () => {
const { data } = await axios.get('/api/products')
setProducts(data)
}
fetchData()
}, [])
const list = products.map((product) => (
<li key={product._id}>
<Link to={`${match.url}/${product.url}`}>
<img
src={product.image}
alt={product.url}
/>
<div>
<h2>{product.title}</h2>
<p>{product.flavor}</p>
<button>View more</button>
</div>
</Link>
</li>
))
return (
<div>
<ul>{list}</ul>
</div>
)
}
export default Frontend
webpack.common.js:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: path.resolve(__dirname, '..', './src/index.js'),
output: {
path: path.resolve(__dirname, '..', './dist'),
filename: '[name].[contenthash:6].js',
clean: true,
publicPath: '/',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|mp4)$/i,
type: 'asset/resource',
},
{
test: /\.(woff(2)?|eot|ttf|otf|svg|pdf)$/,
type: 'asset/inline',
},
],
},
resolve: {
extensions: ['*', '.js', '.jsx'],
},
plugins: [
new HtmlWebpackPlugin({
title: '...',
template: path.resolve(__dirname, '..', './src/template/template.html'),
favicon: path.resolve(__dirname, '..', './public/favicon.ico'),
filename: 'index.html',
}),
],
}
webpack.config.js:
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
module.exports = ({ env }) => {
const envConfig = require(`./webpack.${env}.js`)
return merge(commonConfig, envConfig)
}
webpack.dev.js:
const path = require('path')
const Dotenv = require('dotenv-webpack')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
module.exports = {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
proxy: {
'/api': 'http://localhost:8000',
},
historyApiFallback: true,
contentBase: path.resolve(__dirname, '..', './dist'),
open: true,
hot: true,
compress: true,
port: 8080,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
plugins: [require.resolve('react-refresh/babel')],
},
},
],
},
{
test: /\.(s[ac]|c)ss$/i,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
],
},
plugins: [
new Dotenv({
path: path.resolve(__dirname, '..', './.env.development'),
}),
new ReactRefreshWebpackPlugin(),
],
}
webpack.prod.js:
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const Dotenv = require('dotenv-webpack')
module.exports = {
mode: 'production',
devtool: 'source-map',
output: {
path: path.resolve(__dirname, '..', './dist'),
filename: 'js/[name].[contenthash:6].js',
},
module: {
rules: [
{
test: /\.(s[ac]|c)ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles/[name].[contenthash:6].css',
chunkFilename: '[id].css',
}),
new Dotenv({
path: path.resolve(__dirname, '..', './.env.production'),
}),
],
optimization: {
minimize: true,
minimizer: [new CssMinimizerPlugin(), '...'],
runtimeChunk: {
name: 'runtime',
},
},
}
我看到您没有在 Express 应用中使用静态文件。您应该将静态文件添加到您的 Express 应用程序,并在您的后端服务器上提供图片。
基本上可以看看这个document.
此外,如果您喜欢视频,可以观看此 video。
首先,你的后台文件应该是这样的;
backend
-server.js
-data.js
-public
--images
---coffee
----pic.jpg
这里是 server.js 文件:
import express from 'express'
import data from './data.js'
import path from 'path'
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const app = express()
const port = process.env.PORT || 8000
app.get('/api/products', (req, res) => {
res.send(data.products)
})
app.get('/', (req, res) => {
res.send('server is ready')
})
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
app.use(express.static(path.join(__dirname,'public')))
app.use('/static',express.static('public'))
app.listen(port, () => {
console.log(`serve at http://localhost:${port}}`)
})
// go to 'http://localhost:8000/images/coffee/pic.jpg' it will work