Nuxt执行yarn build后.nuxt/dist/client缺失JS资源报404
问题描述
- 部署场景:使用Apache + PM2部署对接独立域名后端API的Nuxt前端项目,虚拟主机配置完成后可正常访问登录页,但执行
yarn build构建后,.nuxt/dist/client目录下预期生成的某一个JS文件始终返回404错误。 - 特殊现象:将配置中有效的
API_URL(原值为https://xxx.xxx/api/v1)替换为无效地址(如https://xxx.xxx/api/1),重新执行yarn build并重启PM2后,404错误消失。 - 错误截图:

- 运行环境:
- 操作系统:Debian 11
- 服务组件:Apache2 + PM2
现有nuxt.config.js配置
import colors from "vuetify/es5/util/colors"; export default { // Global page headers: https://go.nuxtjs.dev/config-head head: { titleTemplate: "%s - " + process.env.APP_NAME, title: process.env.APP_NAME, htmlAttrs: { lang: "en", }, meta: [ { charset: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { hid: "description", name: "description", content: "" }, { name: "format-detection", content: "telephone=no" }, ], link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }], }, watchers: { webpack: { aggregateTimeout: 300, poll: 1000, }, }, auth: { strategies: { laravelPassport: { provider: "laravel/passport", endpoints: { userInfo: process.env.API_URL + "/me", }, url: process.env.API_SERVER, clientId: process.env.PASSPORT_CLIENT_ID, clientSecret: process.env.PASSPORT_CLIENT_SECRET, }, local: { endpoints: { login: { url: "/user/login", method: "post", propertyName: "data.access_token", }, logout: { url: "/user/logout", method: "post" }, user: { url: "/me", method: "get", propertyName: "data" }, }, token: { property: "data.access_token", }, user: { property: "data", }, tokenRequired: true, tokenType: "Bearer", autoFetchUser: true, }, customStrategy: { scheme: "~/schemes/customScheme", endpoints: { login: { url: "/user/login", method: "post", propertyName: "data.access_token", }, logout: { url: "/user/logout", method: "post" }, user: { url: "/me", method: "get", propertyName: "data" }, }, tokenRequired: true, tokenType: "Bearer", autoFetchUser: true, }, }, redirect: { login: "/", logout: "/", home: "/admin", }, }, router: { middleware: ["auth"], }, // Global CSS: https://go.nuxtjs.dev/config-css css: [], // Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins plugins: ["~plugins/vue-api-query"], // Auto import components: https://go.nuxtjs.dev/config-components components: true, // Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules buildModules: [ // https://go.nuxtjs.dev/vuetify "@nuxtjs/vuetify", ], // Modules: https://go.nuxtjs.dev/config-modules modules: ["@nuxtjs/axios", "@nuxtjs/auth-next"], // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify vuetify: { customVariables: ["~/assets/variables.scss"], theme: { dark: false, themes: { dark: { primary: colors.blue.darken2, accent: colors.grey.darken3, secondary: colors.amber.darken3, info: colors.teal.lighten1, warning: colors.amber.base, error: colors.deepOrange.accent4, success: colors.green.accent3, }, }, }, }, // Build Configuration: https://go.nuxtjs.dev/config-build build: { maxChunkSize: 300000, extend(config, ctx) { config.performance.maxAssetSize = 700 * 1024; }, }, // Axios module configuration: https://go.nuxtjs.dev/config-axios axios: { baseURL: process.env.API_SERVER || "https://xxx.xxx", apiUrl: process.env.API_URL || "https://xxx.xxx/api/v1", headers: { common: { Platform: "web", }, }, }, };
故障原因
- 构建逻辑差异:
@nuxtjs/auth-next的Laravel Passport适配逻辑会在构建阶段检测配置的API端点可达性。当API_URL为有效地址时,模块会注入完整的Passport适配代码,触发webpack代码分割生成额外的异步JS chunk;当API_URL为无效地址时,该部分适配代码会被构建工具tree-shaking移除,不会生成对应chunk,自然不会触发404。 - Apache配置错误:当前虚拟主机规则没有正确处理Nuxt静态资源请求,存在以下任一问题:
/_nuxt/路径的本地目录映射错误,未指向实际的.nuxt/dist/client路径;静态资源请求未配置fallback规则,文件不存在时直接返回404而非转发给PM2托管的Nuxt服务;.nuxt目录权限配置错误,Apache进程无读取权限。 - Nuxt配置不规范:使用了已废弃的
build.maxChunkSize参数,且在auth配置中硬拼接全量API地址,导致构建阶段环境变量被静态替换,触发非预期的分包行为。
修复方案
- 修正Apache虚拟主机配置,确保静态资源映射和反向代理规则正确,参考配置如下(将路径、端口替换为实际部署值):
<VirtualHost *:80> ServerName 你的前端域名 DocumentRoot /your/nuxt/project/path/static # Nuxt静态资源映射 Alias /_nuxt/ /your/nuxt/project/path/.nuxt/dist/client/ <Directory /your/nuxt/project/path/.nuxt/dist/client/> Require all granted Options FollowSymLinks AllowOverride None </Directory> # 静态资源未命中时回源到Nuxt服务 <Location /_nuxt/> FallbackResource proxy:http://127.0.0.1:3000/_nuxt/ </Location> # 其余请求反向代理到PM2启动的Nuxt服务 ProxyPass /_nuxt/ ! ProxyPass / http://127.0.0.1:3000/ ProxyPassReverse / http://127.0.0.1:3000/ </VirtualHost>
配置完成后执行systemctl reload apache2重载服务,同时修正目录权限:chown -R www-data:www-data /your/nuxt/project/path/.nuxt。
修正nuxt.config.js不规范配置:
- 将auth策略中硬拼接的全量接口地址改为相对路径,统一由axios模块处理baseURL,避免构建阶段静态替换导致的异常分包:把laravelPassport配置下的
userInfo: process.env.API_URL + "/me"修改为userInfo: "/me",移除url字段的硬编码全量地址。 - 替换废弃的分包参数,将build配置修改为:
build: { extend(config, ctx) { config.performance.maxAssetSize = 700 * 1024; config.optimization.splitChunks.maxSize = 300000; }, }- 将auth策略中硬拼接的全量接口地址改为相对路径,统一由axios模块处理baseURL,避免构建阶段静态替换导致的异常分包:把laravelPassport配置下的
清理缓存重新构建部署:
执行以下命令清理旧构建产物和缓存,重新构建后重启服务:rm -rf .nuxt node_modules/.cache yarn build pm2 restart 你的Nuxt服务名称
内容的提问来源于stack exchange,提问作者Ian Jay
相关产品推荐
相关产品推荐

