You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Webpack时Vue路由失效:主页正常但子路径报404错误

Vue路由在Webpack下出现404问题

用Webpack之前,我的Vue路由运行完全正常。但后来遇到了一系列loader问题,因此决定改用Webpack。然而Webpack运行起来后,主页可以正常加载,但所有路由都出现404错误。所有被注释的代码都是我已经尝试过但无效的方案。我认为问题出在Webpack配置文件中,但无法定位具体问题,希望能得到解决方案或帮助。


App.vue

<template>
  <div class="base-app">
    <div class="mapbox" id="mapbox">
      <router-view />
    </div>
  </div>
</template>

<script>
// import Login from './components/login.vue';
// import Tract from './components/tract.vue';

export default {
  name: "App",
  // components: {
  //   Login,
  //   Tract
  // }
};
</script>

router.js

import { createWebHistory, createRouter } from "vue-router";
import Index from "./components/index.vue";
import Login from "./components/login.vue";
import Tract from "./components/tract.vue";

const routes =  [
  {
    path: "/",
    component: Index
  },
  {
    path: "/login",
    component: Login
  },
  {
    path: "/tract/:id",
    component: Tract
  }
];


const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

main.js

import { createApp } from 'vue';
import App from './App.vue';
// import login from './components/login.vue';
// import tract from './components/tract.vue';
import router from './router.js';

import "./assets/styles/normalize.css";
import "./assets/styles/app.css"; 

const app = createApp(App);
// app.component('login', login);
// app.component('tract', tract);
app.use(router);
app.mount('#app');

webpack.config.cjs

const { VueLoaderPlugin } = require("vue-loader");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const htmlWebpackPlugin = require("html-webpack-plugin");
const autoprefixer = require("autoprefixer");
const path = require("path");

module.exports = {
  entry: {
    main: "./src/main.js",
  },
  output: {
    filename: 'main.bundle.js',
    path: path.resolve(__dirname, 'dist/')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
      {
        test: /\.s?css$/,
        use: [
          "style-loader",
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              esModule: false,
            },
          },
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: () => [autoprefixer()],
              }
            },
          },
          "sass-loader",
        ],
      },
      {
        test: /\.m?js/,
        resolve: {
          fullySpecified: false,
        },
      }
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash:8].css",
      chunkFilename: "[name].[contenthash:8].css",
    }),
    new htmlWebpackPlugin({
      template: path.resolve(__dirname, "public", "index.html"),
      favicon: "./public/favicon.ico",
    }),
  ],
  resolve: {
    extensions: [ '.tsx', '.ts', '.js', '.vue' ],
    alias: {
        'vue': '@vue/runtime-dom'
    }
  },
  devtool: 'source-map'
};

vue.config.cjs

module.exports = {
  devServer: {
    disableHostCheck: true,
    devMiddleware: {
      writeToDisk: false
    }
  }
}

package.json

{
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "startdev": "webpack-dev-server --mode development --config ./webpack.config.cjs",
    "start": "NODE_ENV=production webpack --config ./webpack.config.cjs"
  },
  "dependencies": {
    "@aws-amplify/ui-vue": "^3.1.20",
    "aws-amplify": "^5.3.3",
    "axios": "^0.22.0",
    "bootstrap": "4.6.0",
    "chart.js": "^4.4.0",
    "core-js": "^3.34.0",
    "jquery": "^3.6.0",
    "mapbox-gl": "^2.6.0",
    "popper.js": "^1.16.1",
    "postcss-loader": "^7.3.3",
    "vue": "^3.0.0",
    "vue-chartjs": "^5.2.0",
    "vue-router": "4"
  },
  "devDependencies": {
    "@babel/core": "^7.23.5",
    "@babel/preset-env": "^7.23.5",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "autoprefixer": "^10.4.16",
    "babel-loader": "^9.1.3",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.8.1",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.5.4",
    "mini-css-extract-plugin": "^2.7.6",
    "postcss": "^8.4.32",
    "sass": "^1.69.5",
    "sass-loader": "^13.3.2",
    "source-map-loader": "^4.0.1",
    "style-loader": "^3.3.3",
    "vue-loader": "^17.3.1",
    "vue-template-compiler": "^2.7.15",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1"
  }
}

解决方案

问题根源

你使用了Vue Router的createWebHistory()(HTML5 history模式),这种模式下,当直接访问子路由或刷新页面时,Webpack开发服务器会将这些请求视为静态资源请求,找不到对应文件就返回404。必须配置服务器把所有路由请求重定向到index.html,让Vue Router接管路由逻辑。

开发环境修复

修改webpack.config.cjs,添加devServer配置并开启historyApiFallback:

module.exports = {
  // ... 其他原有配置
  devServer: {
    historyApiFallback: true, // 核心配置,解决history模式下的404问题
    disableHostCheck: true,
    devMiddleware: {
      writeToDisk: false
    }
  },
  // ... 其他原有配置
}

注意:你之前在vue.config.cjs中的devServer配置不会生效,因为你是通过webpack-dev-server直接启动项目,而非vue-cli,所以必须把devServer配置写在webpack.config.cjs里。

生产环境部署配置

部署到生产服务器时,同样需要配置服务器将所有请求重定向到index.html:

  • Nginx:在站点配置中添加
    location / {
      try_files $uri $uri/ /index.html;
    }
    
  • Apache:在项目根目录创建.htaccess文件
    <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase /
      RewriteRule ^index\.html$ - [L]
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . /index.html [L]
    </IfModule>
    
  • 其他服务器请参考对应文档,核心逻辑都是将所有路由请求指向index.html。

额外优化建议

  1. 删除package.json中的vue-template-compiler依赖,你使用的是Vue3,该依赖是Vue2的模板编译器,与Vue3不兼容(你已安装的@vue/compiler-sfc才是Vue3的正确模板编译工具)。
  2. 确认webpack.config.cjs中resolve.alias的'vue': '@vue/runtime-dom'配置正确,这是Vue3运行时的正确入口。

内容的提问来源于stack exchange,提问作者Stephan Genyk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 23:22:05