nuxt3 Cannot find package ‘@popperis/core‘ 开发过程与踩坑记录心得

本文记录了使用Nuxt3结合Vue3和Vite开发企业官网的过程,包括解决动态路由、环境变量配置、骨架布局定制等问题,以及如何处理部署时遇到的包依赖冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《前端开发面试题进阶秘籍》:前端登顶-前端知识点梳理

需求简介:公司需要开发一个官方网站,在技术选型上面最终定nuxt3+vue3+vite
版本:nuxt3.9.1、vue3、vite5.0.11
本篇文章不过多解释创建nuxt3与基础的框架目录结构问题,敬请谅解!

一、踩坑记录问题点:

1、【Nuxt】Nuxt3 控制台警告 [Vue Router warn]: No match found for location with path “/undefined
2、设置自定义动态路由[slug].html访问
3、配置全局环境变量访问不同接口域名
4、使用内置NuxtLayout开发自定义骨架布局
5、配置nuxt.config.ts属性:modules、runtimeConfig、app、nitro、vite、hooks;等包含本地配置代理与nuxt2不同,需在nitro中配置
6、预渲染-配置,添加所有路由线路
7、部署问题,pnpm包引起的项目部署够报 “ Cannot find package ‘@popperis/core’ imported from /app/.output/server/chunks/app/_nuxt/default-AlcRvqCQ.mis ”
8、封装公共请求js文件;使用内置useFetch函数,通过promise抛出响应内容
9、关闭服务端渲染ssr: false & 静态文件托管CDN链
10、开启自定义路由后,关闭默认布局

二、解决问题
1)【Nuxt】Nuxt3 控制台警告 [Vue Router warn]: No match found for location with path “/undefined

在这里插入图片描述

2)设置自定义动态路由[slug].html访问

1、官网只解释了自定义路由的添加方法并未详细做出解释在哪块
2、官网其实是有个文件的路径显示,在根路径下面创建app文件夹
3、在app文件夹下面创建router.options.ts文件作为自定义路由

在这里插入图片描述

4、示例: 添加后缀让我们的项目更加像html书写出来的也叫伪静态,动态路由有利于后台管理平台或者低代码生成我们的想要的界面,更加便捷与灵活,减少开发成本,只需要固定的生成方式即可;

import type { RouterConfig } from '@nuxt/schema'

export default <RouterConfig> {
  routes: (_routes) => [
    {
      path: '/',
      redirect: '/home.html'
    },
    {
      name: 'home',
      path: '/home.html',
      component: () => import('~/pages/home.vue').then(r => r.default || r)
    },
    {
      name: 'about',
      path: '/about/:slug.html',
      component: () => import('~/pages/about/[slug].vue').then(r => r.default || r)
    },
  ],
}
3)配置全局环境变量访问不同接口域名
  1. 创建.env.development和.env.production
//.env.development

# 构建生产预渲染
BUILD_BASE_API = 'http://api.com:8080'

# 后端接口公共路径
NUXT_BASE_API = ''
  1. 修改package.json文件启动和构建命令
 "dev": "nuxt dev --dotenv .env.development --host",
 "build:test": "nuxt build --dotenv .env.development && npm run created",
 "build:prod": "nuxt build --dotenv .env.production && npm run created",
  "created": "mkdir .output/server/node_modules/@popperjs && mv .output/server/node_modules/@sxzz/popperjs-es .output/server/node_modules/@popperjs/core"
  1. 在nuxt.config.ts中添加全局访问接口前缀名
 runtimeConfig: {
    public: {
      baseURL: process.env.NUXT_BASE_API
    }
  },
4)使用内置NuxtLayout开发自定义骨架布局,根文件也可使用default输出!

在这里插入图片描述

5)配置nuxt.config.ts属性:modules、runtimeConfig、app、nitro、vite、hooks;等包含本地配置代理与nuxt2不同,需在nitro中配置
6)预渲染-配置添加针对所有路由(含5的内容)
import axios from "axios";
import path, { resolve } from 'path'
import { rm } from 'fs/promises'
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";

// 自定义的清理函数
const cleanOutputDir = async (env: string) => {
  const isDev = env === 'development';
  if (isDev) return
  const outputDir = resolve(__dirname, '.output')
  try {
    await rm(outputDir, { recursive: true, force: true })
    console.log('\x1b[31m清空 .output目录成功\x1b[0m');
  } catch (error) {
    console.error('清空 .output目录失败:', error)
  }
}

const baseURL = process.env.BUILD_BASE_API
// 动态获取后端返回的前端路由做处理,处理数据依据后端返回逻辑调整 => ['/home.html', '/about/1.html']
const getRoutes = async () => {
  const endpoint = baseURL + '/router/list';
  const response = await axios.get(endpoint)
  const articlesRouter = response.data?.data?.list || [];
  const navlist = articlesRouter.filter((item: any) => item.link).map((opt: any) => opt.link)
  const menuList = articlesRouter.map((item: any) => item.menuList?.length && item.menuList).filter(Boolean).flat().map((opt: any) => opt.link)
  const all = [...navlist, ...menuList]
  // ['/home.html', '/about/1.html']
  return all
}

export default defineNuxtConfig({
  ssr: true, // 服务端渲染
  devtools: { enabled: false },

  modules: ['@element-plus/nuxt', 'nuxt-swiper'],
  swiper: {},
  runtimeConfig: {
    public: {
      baseURL: process.env.NUXT_BASE_API,
      cdnURL: process.env.NUXT_PUBLIC_CDN_URL || "", // 全局配置CDN地址
    }
  },
  css: ['@/assets/styles/global.scss'], // 配置项目全局css样式
  app: {
  	cdnURL: process.env.NUXT_PUBLIC_CDN_URL, // 构建产物自动补充CDN链接
    head: {
      title: "测试",
      link: [{ rel: "icon", href: "/favicon.ico", type: 'image/x-icon' }],
      meta: [
        { charset: "utf-8" },
        { name: "viewport", content: "width=device-width, initial-scale=1" },
        { hid: "keywords", name: "keywords", content: "" },
        { hid: "description", name: "description", content: "" },
      ],
    },
  },
  nitro: {
    preset: "static",
    compressPublicAssets: true,
    output: { // 静态文件输出目录
      dir: "dist",
      publicDir: "dist", // 同级处理
    },
     // 配置nitro本地开发环境代理
    devProxy: {
      "/website": {
        target: "http://api:8080/website",
        changeOrigin: true,
        prependPath: true,
      },
    },
  },
  build: {
    transpile: ["element-plus", "@element-plus/icons-vue"],
  },
  vite: { // 配置vite构建剔除CMD面板警告问题
    build: {
      minify: 'terser',
      terserOptions: {
        compress: {
          drop_console: false,
          drop_debugger: true,
          pure_funcs: ['console.log']
        },
        format: {
          comments: false
        }
      },
    }
  },
  hooks: { // 配置nitro前置构建生产预渲染html内容,加速访问
    async 'nitro:config'(nitroConfig: any) {
      if (nitroConfig.dev) return
      let slugs = await getRoutes()
      nitroConfig?.prerender?.routes.push(...slugs)
      return
    },
    'build:before': () => cleanOutputDir(import.meta.env.NODE_ENV),
  },
   plugins: [
      createSvgIconsPlugin({
        iconDirs: [path.resolve(process.cwd(), "public/svgIcon")],
      }),
    ],
})

7)部署问题,pnpm包引起的项目部署够报 “ Cannot find package ‘@popperis/core’ imported from /app/.output/server/chunks/app/_nuxt/default-AlcRvqCQ.mis ”

1、解决办法,在package.json文件中新增: “created”: “mkdir .output/server/node_modules/@popperjs && mv .output/server/node_modules/@sxzz/popperjs-es .output/server/node_modules/@popperjs/core” 命令
2、引起的原因是pnpm创建下载的依赖包,与npm包的存放路径位置不一致导致的这个问题,所以需要我们手动拷贝或者命令行创建,使其更加便捷

"scripts": {
    "dev": "nuxt dev --dotenv .env.development --host",
    "build:test": "nuxt build --dotenv .env.development && npm run created",
    "build:prod": "nuxt build --dotenv .env.production && npm run created",
    "created": "mkdir .output/server/node_modules/@popperjs && mv .output/server/node_modules/@sxzz/popperjs-es .output/server/node_modules/@popperjs/core"
  },
8、封装公共请求js文件;使用内置useFetch函数,通过promise抛出响应内容

在utils文件夹下创建request.ts

import type { LocationQuery } from 'vue-router';
import type { NitroFetchRequest } from 'nitropack';
import type { FetchOptions } from 'ofetch';
import { ElMessage, ElLoading } from 'element-plus'

// 接口传参要求
interface QueryItem {
  uid?: string;
  token?: LocationQuery;
}

const codeMessage: any = {
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队(异步任务)。',
  204: '删除数据成功。',
  400: '发出的请求有错误。',
  401: '用户没有权限(令牌、用户名、密码错误)。',
  403: '登录过期请重新登录',
  404: '请求资源不存在。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除,且不会再得到的。',
  422: '当创建一个对象时,发生一个验证错误。',
  500: '服务器发生错误,请检查服务器。',
  502: '网关错误。',
  503: '服务不可用,服务器暂时过载或维护。',
  504: '网关超时。',
};


const request = (url: NitroFetchRequest, params?: FetchOptions<any>, method: 'get' | 'post' | 'delete' | 'put' = 'get') => {
  const route = useRoute();
  const config = useRuntimeConfig();

  const query: QueryItem = route.query;
  const baseURL: string = config.public.baseURL + '/mfy-website/';
  return new Promise((resolve, reject) => {
    const loadingInstance = ElLoading.service({ fullscreen: true })
    $fetch(url, {
      method,
      baseURL: baseURL,
      onRequest({ options }: any) {
        options.headers = { ...options.headers, Authorization: 'xxx' };
        if (method === 'post' || method === 'put') {
          options.body = { ...params };
          options.query = query;
        } else {
          options.query = Object.assign(query, { ...params });
        }
      },

      onResponse({ response }: any) {
        const { status, _data } = response
        const { code, message } = _data || {}
        setTimeout(() => loadingInstance.close(), 500)
        if (code === 0) return resolve(response._data)
        else if (code && message) return ElMessage.error(message || 'Error')
        if (codeMessage[status]) return ElMessage.error(status + ':' + codeMessage[status] || '请求异常')
      },

      onRequestError({ error }: any) {
        loadingInstance.close()
        reject(error)
      },

      onResponseError({ options }: any) {
        loadingInstance.close()
        reject(options)
      }
    } as any);
  })
}

export default request

请求的使用方式:

import request from '@/utils/request'

const api = {
  company: () => '/api/find/list',
}

const company = (params = {}) => request(api.company(), params)

export default {
  company,
}

10、开启自定义路由后,关闭默认布局
{
   name: 'partnerentry',
   path: '/partnerentry.html',
   meta: { layout: false }, // 设置当前页面不走默认布局
   component: () => import('~/pages/partnerentry/partnerentry.vue').then(r => r.default || r)
 },

<script setup lang="ts">
	definePageMeta({
	  layout: false
	});
</script>
<think>好的,用户现在遇到了两个问题:一个是找不到模块@babel/preset-env/lib/utils的错误,另一个是关于core-js版本的警告。根据用户提供的引用,这些问题可能版本不兼容有关。用户提到他们当前使用的core-js是3.6.5,而@babel/preset-env是7.26.9,但之前的回答和引用建议降级preset-env到7.12.17,或者更新core-js到更高版本。 首先,我需要确认这两个问题的根源。对于找不到模块的错误,引用[1]-[4]指出,这可能是因为@babel/preset-env的版本过高,导致内部路径变化,从而找不到utils模块。解决方法通常是降级到7.12.17版本。但用户现在用的是7.26.9,这显然比推荐的版本高很多,所以可能需要检查该版本是否确实存在路径问题。 其次,关于core-js的警告,用户使用的是3.6.5,而根据之前的回答,core-js需要和@babel/preset-env中指定的版本严格匹配。如果用户配置中指定了corejs:3.6.5,但实际安装的版本不匹配,就会出现警告。或者,可能用户的Babel配置没有正确声明corejs版本,导致默认使用了旧版。 接下来,需要综合用户提供的引用信息。引用[4]提到,即使依赖版本正确,有时候删除node_modules并重新安装(使用不同的包管理器如yarn或cnpm)可以解决问题。这可能是因为缓存或安装过程中的部分错误导致的。 因此,解决方案需要分步骤处理: 1. 处理模块找不到错误:根据引用建议,降级@babel/preset-env到7.12.17,但用户可能不想降级,尤其是如果他们需要使用更高版本的功能。另一种方法是检查7.26.9版本是否存在已知的路径问题,或者是否有其他依赖冲突。如果必须保持当前版本,可能需要手动检查node_modules中的文件路径是否正确,或者是否有损坏的安装。同时,引用[4]提到重新安装node_modules可能有效,所以建议用户尝试清除缓存并重新安装。 2. 解决core-js警告:需要确保core-js的版本Babel配置中的声明一致。用户当前使用3.6.5,但可能需要升级到更高的稳定版本,比如3.33.x,以兼容最新的Babel预设。同时,在Babel配置中明确指定corejs的版本,避免自动检测导致的版本不匹配。 可能的步骤包括: - 降级@babel/preset-env到7.12.17,但用户可能不愿意,所以需要评估是否有必要。 - 更新core-js到当前@babel/preset-env兼容的版本,并调整Babel配置。 - 清除node_modules和lock文件,重新安装依赖,可能切换包管理器。 - 检查Babel配置是否正确,特别是useBuiltIns和corejs的设置。 此外,用户之前的问题中提到了core-js版本不匹配的问题,所以在当前回答中需要结合之前的建议,确保core-js和preset-env的版本兼容性。同时,用户可能希望在不降级的情况下解决问题,因此需要提供替代方案,比如升级到支持当前preset-env版本的core-js,并正确配置。 最后,需要验证这些步骤是否可行,并确保用户能够按照指导操作解决问题,同时解释每一步的原因,帮助用户理解背后的原理,避免未来出现类似问题。</think>### 分步解决方案:解决 `@babel/preset-env/lib/utils` 缺失 `core-js` 版本警告 --- #### 一、**问题定位** 1. **`Cannot find module &#39;@babel/preset-env/lib/utils&#39;`** - **根本原因**:`@babel/preset-env@7.26.9` 的模块路径结构已更新,旧版本(如 `7.12.17`)的 `utils` 文件路径被移除或重构[^1][^2][^3]。 - **兼容性冲突**:`@babel/preset-env` `core-js@3.6.5` 版本不匹配(Babel 7.26.x 要求 `core-js@3.8+`)[^1]。 2. **`core-js` 版本警告** - **触发条件**:当 `@babel/preset-env` 检测到 `core-js` 版本低于其预期范围时,会提示版本不匹配警告[^1]。 --- #### 二、**解决方案(二选一)** --- ##### **方案一:降级 `@babel/preset-env`(兼容旧版)** **适用场景**:需快速修复编译问题,不依赖新特性 1. **降级依赖** ```bash npm uninstall @babel/preset-env npm install @babel/preset-env@7.12.17 --save-dev ``` 2. **锁定 `core-js` 版本** 确保 `core-js@3.6.5` 版本稳定: ```bash npm install core-js@3.6.5 --save ``` 3. **更新 Babel 配置** ```javascript // babel.config.js 或 .babelrc { "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": { "version": 3.6, // 显式声明版本 "proposals": true } } ] ] } ``` --- ##### **方案二:升级至新版生态链(推荐)** **适用场景**:需兼容现代工具链,避免长期技术负债 1. **升级 `core-js`** ```bash npm uninstall core-js npm install core-js@3.33.0 --save ``` 2. **同步升级 `@babel/preset-env`** ```bash npm uninstall @babel/preset-env npm install @babel/preset-env@7.26.10 --save-dev ``` 3. **修复路径缺失问题** 清除缓存并重新安装依赖: ```bash rm -rf node_modules package-lock.json npm cache clean --force npm install ``` 4. **验证配置** ```javascript // babel.config.js module.exports = { presets: [ [ "@babel/preset-env", { useBuiltIns: "usage", corejs: { version: 3.33, // 严格匹配安装版本 proposals: true } } ] ] }; ``` --- #### 三、**关键验证步骤** 1. **检查依赖树** ```bash npm list @babel/preset-env core-js ``` - 确保输出中无 `UNMET DEPENDENCY` 或冲突版本。 2. **运行编译测试** ```bash npm run build -- --verbose ``` - 确认无 `Module not found` 错误和 `core-js` 警告。 --- #### 四、**版本兼容性对照表** | 依赖包 | 方案一版本 | 方案二版本 | |---------------------|------------------|------------------| | `@babel/preset-env` | 7.12.17 | 7.26.10 | | `core-js` | 3.6.5 | 3.33.0 | | Node.js | ≥12.22 | ≥16.10 | [^1]: Babel 官方文档指出,`@babel/preset-env` 的 `useBuiltIns` 模式需 `core-js` 版本严格匹配。 [^2]: 实际项目案例表明,降级 `@babel/preset-env` 可临时解决路径缺失问题[^2][^3]。 [^3]: 依赖缓存清理是解决模块加载异常的通用方法[^4]。 --- #### 相关问题 1. 如何检查项目中是否存在多个版本的 `core-js`? 2. `useBuiltIns: "usage"` 和 `"entry"` 在 polyfill 注入方式上有何不同? 3. 升级 Babel 7.x 到 8.x 需要注意哪些破坏性变更?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SunnyRun!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值