使用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。
额外优化建议
- 删除
package.json中的vue-template-compiler依赖,你使用的是Vue3,该依赖是Vue2的模板编译器,与Vue3不兼容(你已安装的@vue/compiler-sfc才是Vue3的正确模板编译工具)。 - 确认
webpack.config.cjs中resolve.alias的'vue': '@vue/runtime-dom'配置正确,这是Vue3运行时的正确入口。
内容的提问来源于stack exchange,提问作者Stephan Genyk
相关产品推荐
相关产品推荐

