
本文旨在解决webpack开发服务器中mp3等静态资源加载时出现的404错误。核心问题在于webpack配置中`output.publicpath`的缺失以及javascript中资源引用路径的不一致。通过统一使用webpack 5的asset modules并正确配置输出路径与公共路径,同时调整前端代码中的资源引用方式,可以确保资源被正确打包、服务并访问,从而消除404错误。
在现代前端开发中,Webpack作为模块打包工具,负责将各种资源(如JavaScript、CSS、图片、字体、音频等)打包并优化。当开发服务器在加载静态资源时返回404 Not Found错误,通常意味着浏览器请求的URL与服务器实际提供的资源路径不匹配。这可能由以下几个原因造成:
在提供的案例中,MP3文件加载失败并返回GET http://localhost:3000/assets/audio/Too_Late.mp3 404 (Not Found)错误,这明确指出浏览器尝试从/assets/audio/路径获取资源,但服务器未能找到。
我们来深入分析提供的Webpack配置和JavaScript代码:
Webpack配置分析:
module.exports = {
// ... 其他配置
output: {
path: path.resolve(__dirname, 'src/app/dist'),
clean: true,
filename: 'index.[contenthash].js',
assetModuleFilename: 'assets/[name][ext]', // 通用资源模块文件名
},
// ...
module: {
rules: [
// ... 其他规则
{
test: /\.mp3$/,
loader: 'file-loader', // MP3文件使用file-loader
},
// ...
],
},
// ...
}JavaScript代码分析:
const AudioController = {
// ...
renderAudios() {
data.forEach((item) => {
const audio = new Audio(`../../assets/audio/${item.link}`); // 问题所在
// ...
})
}
}为了解决MP3文件加载的404错误,我们将采取以下策略:
首先,修改Webpack配置,为MP3文件使用Asset Modules,并设置publicPath。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const PostCssPresetEnv = require('postcss-preset-env');
const mode = process.env.NODE_ENV || 'development';
const devMode = mode === 'development';
const target = devMode ? 'web' : 'browserslist';
const devtool = devMode ? 'source-map' : undefined;
module.exports = {
mode,
target,
devtool,
devServer: {
port: 3000,
open: true,
hot: true,
// 如果你的HTML不是在根目录,或者需要自定义,可能需要设置 static
// static: {
// directory: path.join(__dirname, 'src/app/dist'),
// publicPath: '/',
// },
},
entry: ['@babel/polyfill', path.resolve(__dirname, 'src/app/js', 'index.js')],
output: {
path: path.resolve(__dirname, 'src/app/dist'),
clean: true,
filename: 'index.[contenthash].js',
assetModuleFilename: 'assets/[name][ext]', // 通用资源模块文件名
publicPath: '/', // **新增或修改:设置公共路径为根目录**
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'src/app', 'index.html'),
}),
new MiniCssExtractPlugin({
filename: 'index.[contenthash].css',
}),
],
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
},
{
test: /\.s?css$/i,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [PostCssPresetEnv],
},
},
},
'sass-loader',
],
},
{
test: /\.(ttf|otf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name][ext]'
}
},
{
test: /\.mp3$/,
type: 'asset/resource', // **修改:使用Asset Modules**
generator: {
filename: 'assets/audio/[name][ext]' // **新增:为MP3指定输出子目录**
}
},
{
test: /\.(jpeg|jpg|png|gif|webp|svg)$/i,
use: [
{
loader: 'image-webpack-loader',
options: {
mozjpeg: { progressive: true },
optipng: { enabled: false },
pngquant: { quality: [0.65, 0.90], speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
}
},
],
type: 'asset/resource',
generator: {
filename: 'assets/images/[name][ext]' // **可选:为图片指定输出子目录**
}
},
{
test: /\.m?js$/i,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
}关键修改点:
现在Webpack配置已经能够将MP3文件正确打包并服务于/assets/audio/路径下。接下来,我们需要修改JavaScript代码,使其引用正确的URL。
方法一:使用绝对路径(推荐,与当前new Audio()模式兼容)
import '../index.html';
import '../scss/style.scss';
import {data} from './data.js';
const AudioController = {
state: {
audios: [],
},
init() {
this.initVariables();
this.renderAudios();
},
initVariables() {
this.audioList = document.querySelector('.items');
},
renderAudios() {
data.forEach((item) => {
// **修改:使用绝对路径**
const audio = new Audio(`/assets/audio/${item.link}`);
audio.addEventListener('loadeddata', () => {
const newItem = { ...item, duration: audio.duration, audio };
this.state.audios = [ ...this.state.audios, newItem ];
})
})
}
}
AudioController.init();通过将路径从../../assets/audio/更改为/assets/audio/,我们确保了浏览器将从服务器的根目录开始查找这些音频文件,这与Webpack的publicPath和generator.filename配置完美匹配。
方法二:直接导入MP3文件(更推荐的Webpack方式)
对于Webpack处理的资源,最佳实践是直接在JavaScript模块中导入它们。这样,Webpack会在打包时自动解析路径并提供正确的URL。
首先,你需要确保你的data.js中的link字段存储的是音频文件的模块路径,而不是简单的文件名。或者,你可以动态地导入。
修改data.js (示例,如果文件结构允许)
如果你的音频文件都位于src/app/assets/audio/,并且你希望直接导入:
// data.js
// 假设你的音频文件在 src/app/assets/audio/
import HurtYouMp3 from '../assets/audio/Hurt_You.mp3';
import InYourEyesMp3 from '../assets/audio/In_Your_Eyes.mp3';
import TheHillsMp3 from '../assets/audio/The_Hills.mp3';
import TooLateMp3 from '../assets/audio/Too_Late.mp3';
export const data = [
{
id: 1,
link: HurtYouMp3, // 直接引用导入的模块
genre: "R&B",
track: "Hurt You",
group: "The Weeknd",
year: 2020,
},
{
id: 2,
link: InYourEyesMp3,
genre: "R&B",
track: "In Your Eyes",
group: "The Weeknd",
year: 2020,
},
{
id: 3,
link: TheHillsMp3,
genre: "R&B",
track: "The Hills",
group: "The Weeknd",
year: 2020,
},
{
id: 4,
link: TooLateMp3,
genre: "R&B",
track: "Too Late",
group: "The Weeknd",
year: 2020,
},
];修改index.js
import '../index.html';
import '../scss/style.scss';
import {data} from './data.js';
const AudioController = {
state: {
audios: [],
},
init() {
this.initVariables();
this.renderAudios();
},
initVariables() {
this.audioList = document.querySelector('.items');
},
renderAudios() {
data.forEach((item) => {
// **修改:直接使用data.link中由Webpack处理后的路径**
const audio = new Audio(item.link);
audio.addEventListener('loadeddata', () => {
const newItem = { ...item, duration: audio.duration, audio };以上就是Webpack资产管理:解决开发服务器MP3文件404错误指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号