2025前端SSR框架之十分钟快速上手Nuxt3搭建项目

大家好,我是鱼樱!!!

关注公众号【鱼樱AI实验室】持续分享更多前端和AI辅助前端编码新知识~~

不定时写点笔记写点生活~写点前端经验。

在当前环境下,纯前端开发者可以通过技术深化、横向扩展、切入新兴领域以及产品化思维找到突破口。

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

前端最卷的开发语言一点不为过,三天一小更,五天一大更。。。一年一个框架升级~=嗯,要的就是这样感觉!与时俱进~

认识Nuxtjs

Nuxt是一个基于Vue.js的通用应用框架,专注于简化服务器端渲染(SSR)和静态站点生成(SSG)的开发流程。(先思考你为什么需要学习它??你也可以不用学习它!!)我是当前项目需要使用到。所以简单做个分享~

Nuxt的核心定位

Nuxt是一个建立在Vue.js生态系统之上的全栈框架‌,其核心设计目标是提供开箱即用的服务器端渲染能力,同时支持静态站点生成和混合渲染模式。它通过抽象化路由配置、代码分割等复杂逻辑,显著提升了Vue应用的开发效率和性能表现。‌‌‌‌

  • Nuxt 自动导入组件、可组合项和 Vue.js API,以便在你的应用中使用,而无需显式导入它们
  • Nuxt 可以自动导入你的 components/composables/utils/
  • server 目录中,Nuxt 会自动导入从 server/utils/ 导出的函数和变量
  • 你还可以通过配置 nuxt.config 文件的 imports 部分,自动导入从自定义文件夹或第三方包导出的函数
  • Nuxt 使用 Vite(默认)或 webpack 来构建和打包你的应用
  • Nuxt 的核心特性之一是文件系统路由

先决条件

最佳设置附加说明: Node.js :确保使用偶数版本(18、20 等) - Nuxtr :安装社区开发的 Nuxtr extension - WSL :如果你使用的是 Windows 系统并且 HMR 运行缓慢,建议你尝试使用 WSL (Windows Subsystem for Linux),这可能会解决一些性能问题。打开终端(如果你使用的是 Visual Studio Code,则可以打开 集成终端),并使用以下命令创建一个新的启动项目:¥Open a terminal (if you're using Visual Studio Code, you can open an integrated terminal) and use the following command to create a new starter project:

nuxt 官网

中文官网英文官网

创建项目

sh 复制代码
pnpm create nuxt <project-name>

继续下一步出现 Are you interested in participating?

继续下一步出现 Would you like to install any of the official modules?

安装better-sqlite3报错

解决 升级Python Python官方下载

sh 复制代码
python --version
where python
sh 复制代码
npm config set python "C:\Users\你的用户名\AppData\Local\Programs\Python\Python313\python.exe"

原因:better-sqlite3 需要 Python 3.6~3.11,但你的 Python 配置不正确或版本不兼容,且 node-gyp 找不到可用的 Python。windows-build-tools 已经不推荐使用

项目根目录创建pnpm-workspace.yaml

yml 复制代码
onlyBuiltDependencies:
  - better-sqlite3

此时默认本地打开 http://localhost:3000.

你不必使用 TypeScript 来使用 Nuxt 构建应用。但是,强烈建议对 nuxt.config 文件使用 .ts 扩展名。这样,你可以利用 IDE 中的提示来避免在编辑配置时出现拼写错误。

配置文件一 app.config.ts

app.config.ts 文件位于源目录(默认为项目根目录),用于公开可在构建时确定的公共变量。与 runtimeConfig 选项相反,这些不能使用环境变量覆盖。

一个最小的配置文件导出一个 defineAppConfig 函数,该函数包含一个包含你配置的对象。defineAppConfig 助手无需导入即可全局使用。

代码如下 这些变量通过 useAppConfig 获取

配置文件二 nuxt.config.ts

nuxt.config.ts 文件位于 Nuxt 项目的根目录下,可以覆盖或扩展应用的行为。

一个最小的配置文件导出一个 defineNuxtConfig 函数,该函数包含一个包含你配置的对象。defineNuxtConfig 助手无需导入即可全局使用。

为了确保你的配置是最新的,Nuxt 在检测到主配置文件(.env.nuxtignore.nuxtrc 点文件)中的更改时将进行完全重启

基础配置参考

js 复制代码
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  compatibilityDate: "2025-05-15",
  devtools: { enabled: true },
  // 样式表将内联在 Nuxt 渲染的 HTML 中,全局注入并存在于所有页面中 比如 "~/assets/css/main.css" 可以配置多个
  // css: ["animate.css"],
  // 在应用中引入外部样式表。你可以使用不同的方法实现此结果。请注意,本地样式表也可以像这样包含
  app: {
    // 启用页面转换,为所有 pages 应用自动转换 页面过渡效果
    pageTransition: { name: "page", mode: "out-in" },
    // 启用布局转换,为所有 layouts 应用自动转换 布局过渡
    layoutTransition: { name: "layout", mode: "out-in" },
    // 将 pageTransition: false,layoutTransition: false 关闭过渡效果
    //  pageTransition: {
    //   name: 'fade',
    //   mode: 'out-in' // default
    // },
    // layoutTransition: {
    //   name: 'slide',
    //   mode: 'out-in' // default
    // }
    // 也可以 建议在 app.vue 中使用 useHead()
    head: {
      link: [
        {
          rel: "stylesheet",
          href: "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css",
        },
      ],
    },
  },
  // 使用 Vite
  vite: {
    // 预处理文件中注入代码 比如 scss 变量
    css: {
      preprocessorOptions: {
        scss: {
          // additionalData: '@use "~/assets/_colors.scss" as *;',
        },
      },
    },
    // 将选项传递给 @vitejs/plugin-vue
    vue: {
      customElement: true,
    },
    // 将选项传递给 @vitejs/plugin-vue-jsx
    vueJsx: {
      mergeProps: true,
    },
  },
  imports: {
    // 启用从 vue-i18n 包自动导入 useI18n 可组合项的功能 从第三方包自动导入
    presets: [
      {
        from: "vue-i18n",
        imports: ["useI18n"],
      },
    ],
    //   autoImport: false // 完全禁用自动导入,但仍然可以使用 #imports 中的 显式导入。
    //   scan: false // 部分禁用自动导入 如果你希望特定于框架的函数(例如 ref)保持自动导入,但希望禁用你自己的代码(例如,自定义可组合函数)的自动导入
  },
  components: {
    // 要禁用从你自己的 ~/components 目录自动导入组件的功能,你可以将 components.dirs 设置为空数组(但请注意,这不会影响模块添加的组件)
    dirs: [],
  },
  // 启用实验性 Vue 功能
  vue: {
    propsDestructure: true,
  },
  // webpack 并需要配置 vue-loader
  //  webpack: {
  //   loaders: {
  //     vue: {
  //       hotReload: true,
  //     }
  //   }
  // },
  modules: [
    "@nuxt/content",
    "@nuxt/eslint",
    "@nuxt/image",
    "@nuxt/scripts",
    "@nuxt/test-utils",
    "@nuxt/ui",
  ],
});

默认入口 app.vue

默认情况下,Nuxt 将此文件视为入口点,并为应用的每个路由渲染其内容

如果你的应用中只有一个布局,我们建议你将 app.vue<NuxtPage /> 一起使用

样式处理

  • 可以使用 CSS 预处理器、CSS 框架、UI 库和 Nuxt 模块来设置应用的样式
  • 如果你正在编写本地样式表,那么将它们放置到 assets/ 目录 中是最自然的选择
  • 组件内导入你可以直接在页面、布局和组件中导入样式表。你可以使用 JavaScript 导入或 CSS @import 声明
  • CSS 属性 你还可以在 Nuxt 配置中使用 css 属性。样式表的自然存放位置是 assets/ 目录。然后,你可以引用它的路径,Nuxt 会将其添加到应用的所有页面中

路由 & 页面

Nuxt 的核心特性之一是文件系统路由。pages/ 目录中的每个 Vue 文件都会创建一个相应的 URL(或路由),用于显示文件的内容。通过为每个页面使用动态导入,Nuxt 利用代码拆分为请求的路由提供最少量的 JavaScript

  • Nuxt 路由基于 vue-router,并根据文件名为 pages/ 目录 中创建的每个组件生成路由
  • 此文件系统路由使用命名约定来创建动态和嵌套路由
  • <NuxtLink> 组件用于链接各个页面。它会渲染一个 <a> 标签,并将 href 属性设置为页面的路由。应用完成 hydrated 后,页面转换将通过更新浏览器 URL 在 JavaScript 中执行。这可以防止整页刷新并允许动画过渡。
  • useRoute() 可组合函数可用于 Vue 组件的 <script setup> 块或 setup() 方法中,以访问当前路由详情

路由中间件

路由中间件有三种类型:

  1. 匿名(或内联)路由中间件,直接在使用它们的页面中定义。
  2. 命名路由中间件,放置在 middleware/ 目录中,并在页面上使用时通过异步导入自动加载。(注意:路由中间件名称已规范化为短横线命名,因此 someMiddleware 变为 some-middleware。)
  3. 应用的全局样式将随响应一起发送。

auth 中间件保护 /dashboard 页面的示例

路由验证

Nuxt 通过 definePageMeta()validate 属性在每个你希望验证的页面中提供路由验证。

validate 属性接受 route 作为参数。你可以返回一个布尔值来确定这是否是与此页面一起渲染的有效路由。如果你返回 false,并且找不到其他匹配项,则会导致 404 错误。你还可以直接返回一个带有 statusCode/statusMessage 的对象,以立即响应错误(其他匹配项将不会被检查)

视图

如果控制台显示 Create a Vue component in the pages/directory to enable <NuxtPage> 说明pages下面没有页面;

遇到的问题

  • It looks like you're trying to use c directly as a PostCSS plugin. The PostCSS plugin has moved to a separate package, so to continue using Tailwind CSS with PostCSS you'll need to install @tailwindcss/postcss and update your PostCSS configuration.

  • @nuxtjs/tailwindcss

  • tailwindcss

注意 tailwindcss v3 v4的区别(具体看官网的配置变更)

js 复制代码
// 使用 useSeoMeta 设置页面 SEO 信息
useSeoMeta({
  title: "Nuxt 3 博客系统 - 现代化前端开发",
  description:
    "基于 Nuxt 3 构建的现代化博客系统,展示所有核心 API 用法、最佳实践和注意事项",
  ogTitle: "Nuxt 3 博客系统",
  ogDescription: "学习 Nuxt 3 开发的最佳实践和核心功能",
  ogImage: "/og-image.jpg",
  twitterCard: "summary_large_image",
});

// 使用 useHead 进行更详细的头部配置
useHead({
  title: "Nuxt 3 博客系统",
  meta: [
    {
      name: "keywords",
      content: "Nuxt 3, Vue 3, TypeScript, 博客系统, 前端开发",
    },
    { name: "author", content: "Nuxt 3 博客系统" },
    { name: "viewport", content: "width=device-width, initial-scale=1" },
  ],
  link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }],
});

页面跳转

js 复制代码
/**
 * 导航到博客列表页
 */
const navigateToBlog = () => {
  navigateTo("/blog");
};

在页面或组件中跳转并携带参数

js 复制代码
<script setup>
const router = useRouter()

function goToDetail(id) {
  router.push({ name: 'detail', params: { id } })
}
</script>

<template>
  <button @click="goToDetail(123)">跳转到详情页(ID=123)</button>
</template>

跳转到 query 参数页面

js 复制代码
<script setup>
const router = useRouter()

function goToSearch(keyword) {
  router.push({ path: '/search', query: { q: keyword } })
}
</script>

<template>
  <button @click="goToSearch('nuxt')">搜索 nuxt</button>
</template>

动态路由页面(如 /pages/detail/[id].vue

[id].vue 页面中获取参数:

js 复制代码
<script setup>
const route = useRoute()
const id = route.params.id
</script>

回到顶部

js 复制代码
/**
 * 滚动到页面顶部
 */
const scrollToTop = () => {
  window.scrollTo({ top: 0, behavior: "smooth" });
};

组件使用

components 下的组件直接使用即可,无需导入,无需注册

动态路由

在 Nuxt(和 Next.js 等现代前端框架)中,[slug].vue 这种文件命名方式用于动态路由

  • slug 是一个占位符,代表任意路径参数。
  • 例如:/blog/[slug].vue 可以匹配 /blog/hello-world/blog/123/blog/abc-def 等路径。
  • 在页面组件中,你可以通过 useRoute()definePageMeta 获取 slug 的值。

中间件使用

js 复制代码
/**
 * 认证中间件
 *
 * 这个中间件演示了如何在 Nuxt 3 中:
 * 1. 检查用户认证状态
 * 2. 重定向未认证用户
 * 3. 处理路由守卫逻辑
 *
 * 使用方法:
 * 在页面中使用 definePageMeta({ middleware: 'auth' })
 */
export default defineNuxtRouteMiddleware((to, from) => {
  // 在服务端和客户端都会执行的逻辑
  console.log("认证中间件执行:", to.path);

  // 模拟用户认证状态检查
  // 在实际应用中,这里会检查 JWT token、session 等
  const isAuthenticated = false; // 模拟未认证状态

  // 定义需要认证的路由
  const protectedRoutes = ["/admin", "/profile", "/dashboard"];

  // 检查当前路由是否需要认证
  const requiresAuth = protectedRoutes.some((route) =>
    to.path.startsWith(route)
  );

  // 如果需要认证但用户未认证,重定向到登录页
  if (requiresAuth && !isAuthenticated) {
    console.log("用户未认证,重定向到登录页");

    // 保存用户尝试访问的页面,登录后可以跳转回来
    const redirectPath = encodeURIComponent(to.fullPath);

    // 抛出错误或重定向到登录页
    throw createError({
      status: 401,
      statusText: "需要登录才能访问此页面",
    });

    // 或者重定向到登录页
    // return navigateTo(`/login?redirect=${redirectPath}`)
  }

  // 如果用户已认证但尝试访问登录页,重定向到首页
  if (isAuthenticated && to.path === "/login") {
    console.log("用户已认证,重定向到首页");
    return navigateTo("/");
  }

  // 记录用户访问日志(仅在客户端)
  if (process.client) {
    console.log("用户访问页面:", to.path);
  }

  // 中间件执行完成,继续路由导航
  return;
});

全局插件

$utils

全局工具函数,可在任何组件中使用。

js 复制代码
// 在组件中使用
const { $utils } = useNuxtApp()
$utils.formatDate(new Date())
$utils.debounce(fn, 300)

数据获取

useAsyncData

  • 用于在服务端和客户端获取异步数据,支持缓存、自动处理 loading/error。
  • 推荐用于页面级数据获取(SEO友好)。
js 复制代码
<!-- 使用 useAsyncData -->
<script setup>
const { data, pending, error, refresh } = await useAsyncData('posts', () => 
  $fetch('/api/posts')
)
</script>

useFetch

  • useAsyncData 的封装,专门用于 HTTP 请求,语法更简洁。
  • 支持自动调用 $fetch,也支持 SSR。
js 复制代码
<!-- 使用 useFetch -->
<script setup>
const { data } = await useFetch('/api/users')
</script>

$fetch

  • 是 Nuxt3 内置的轻量 HTTP 客户端(基于 ohmyfetch)。
  • 用于发起 HTTP 请求,类似于 fetch,但自动处理 baseURL、headers 等。
  • 只能在 setup 或普通 JS 里用,不自动处理 loading/error
js 复制代码
const users = await $fetch('/api/users')

小结

  • 页面/组件异步数据推荐用 useAsyncDatauseFetch
  • 只做简单 HTTP 请求可用 $fetch
  • useFetch 语法最简,useAsyncData 更灵活。

状态管理

js 复制代码
<script setup>
// 全局状态
const counter = useState('counter', () => 0)

// 本地状态
const localState = ref('')
const computed = computed(() => localState.value.toUpperCase())
</script>

插件使用

js 复制代码
/*
 * @File name: global-components.client.ts
 * @Author: Nuxt3 博客系统
 * @Description: 全局组件插件 - 演示 Nuxt 3 客户端插件的使用方法
 */

import AppIcon from '~/components/AppIcon.vue'

/**
 * 全局组件插件
 *
 * 这个插件演示了如何在 Nuxt 3 中:
 * 1. 注册全局组件
 * 2. 添加全局属性
 * 3. 扩展 Vue 实例
 * 4. 处理客户端特定逻辑
 *
 * 文件名以 .client.ts 结尾表示这是一个客户端插件
 * 只会在客户端运行
 */
export default defineNuxtPlugin((nuxtApp) => {
  // 插件初始化日志
  console.log("全局组件插件已加载 (客户端)");

  // 1. 注册全局组件
  // 注册图标组件
  nuxtApp.vueApp.component("Icon", AppIcon)
  
  // 这里可以注册一些常用的全局组件
  nuxtApp.vueApp.component("GlobalLoading", {
    template: `
      <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
        <div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-xl">
          <div class="flex items-center space-x-4">
            <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
            <span class="text-gray-900 dark:text-white">{{ message }}</span>
          </div>
        </div>
      </div>
    `,
    props: {
      message: {
        type: String,
        default: "加载中...",
      },
    },
  });

  // 2. 添加全局属性
  // 这些属性可以在所有组件中通过 $utils 访问
  nuxtApp.vueApp.config.globalProperties.$utils = {
    /**
     * 格式化日期
     * @param date - 日期对象或字符串
     * @param format - 格式选项
     * @returns 格式化后的日期字符串
     */
    formatDate(
      date: Date | string,
      format: "short" | "long" | "time" = "short"
    ): string {
      const d = new Date(date);
      const formatOptions = {
        short: {
          year: "numeric",
          month: "short",
          day: "numeric",
        } as Intl.DateTimeFormatOptions,
        long: {
          year: "numeric",
          month: "long",
          day: "numeric",
        } as Intl.DateTimeFormatOptions,
        time: {
          hour: "2-digit",
          minute: "2-digit",
        } as Intl.DateTimeFormatOptions,
      };
      return d.toLocaleDateString("zh-CN", formatOptions[format]);
    },

    /**
     * 防抖函数
     * @param func - 要防抖的函数
     * @param wait - 等待时间(毫秒)
     * @returns 防抖后的函数
     */
    debounce<T extends (...args: any[]) => any>(func: T, wait: number): T {
      let timeout: NodeJS.Timeout;
      return ((...args: Parameters<T>) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
      }) as T;
    },

    /**
     * 节流函数
     * @param func - 要节流的函数
     * @param wait - 等待时间(毫秒)
     * @returns 节流后的函数
     */
    throttle<T extends (...args: any[]) => any>(func: T, wait: number): T {
      let inThrottle: boolean;
      return ((...args: Parameters<T>) => {
        if (!inThrottle) {
          func.apply(this, args);
          inThrottle = true;
          setTimeout(() => (inThrottle = false), wait);
        }
      }) as T;
    },

    /**
     * 复制文本到剪贴板
     * @param text - 要复制的文本
     * @returns Promise<boolean> - 是否成功复制
     */
    async copyToClipboard(text: string): Promise<boolean> {
      try {
        await navigator.clipboard.writeText(text);
        return true;
      } catch (error) {
        console.error("复制失败:", error);
        return false;
      }
    },

    /**
     * 生成随机字符串
     * @param length - 字符串长度
     * @returns 随机字符串
     */
    generateRandomString(length: number = 8): string {
      const chars =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      let result = "";
      for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
      }
      return result;
    },

    /**
     * 格式化文件大小
     * @param bytes - 字节数
     * @returns 格式化后的文件大小字符串
     */
    formatFileSize(bytes: number): string {
      const sizes = ["B", "KB", "MB", "GB", "TB"];
      if (bytes === 0) return "0 B";
      const i = Math.floor(Math.log(bytes) / Math.log(1024));
      return (
        Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + sizes[i]
      );
    },
  };

  // 3. 添加全局方法
  // 这些方法可以通过 $toast 在组件中使用
  nuxtApp.vueApp.config.globalProperties.$toast = {
    /**
     * 显示成功提示
     * @param message - 提示消息
     */
    success(message: string) {
      console.log("✅ 成功:", message);
      // 这里可以集成实际的 toast 组件
      if (window.alert) {
        window.alert(`✅ ${message}`);
      }
    },

    /**
     * 显示错误提示
     * @param message - 错误消息
     */
    error(message: string) {
      console.error("❌ 错误:", message);
      // 这里可以集成实际的 toast 组件
      if (window.alert) {
        window.alert(`❌ ${message}`);
      }
    },

    /**
     * 显示警告提示
     * @param message - 警告消息
     */
    warning(message: string) {
      console.warn("⚠️ 警告:", message);
      // 这里可以集成实际的 toast 组件
      if (window.alert) {
        window.alert(`⚠️ ${message}`);
      }
    },

    /**
     * 显示信息提示
     * @param message - 信息消息
     */
    info(message: string) {
      console.info("ℹ️ 信息:", message);
      // 这里可以集成实际的 toast 组件
      if (window.alert) {
        window.alert(`ℹ️ ${message}`);
      }
    },
  };

  // 4. 监听路由变化
  nuxtApp.hook("app:mounted", () => {
    console.log("应用已挂载到 DOM");
  });

  // 5. 添加错误处理
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    console.error("全局错误处理:", error, info);
    // 这里可以添加错误上报逻辑
  };

  // 6. 客户端特定的初始化逻辑
  if (process.client) {
    // 监听页面可见性变化
    document.addEventListener("visibilitychange", () => {
      if (document.hidden) {
        console.log("页面隐藏");
      } else {
        console.log("页面可见");
      }
    });

    // 监听在线状态变化
    window.addEventListener("online", () => {
      console.log("网络连接已恢复");
    });

    window.addEventListener("offline", () => {
      console.log("网络连接已断开");
    });
  }

  // 7. 提供插件功能给其他部分使用
  return {
    provide: {
      // 提供一个全局的事件总线
      eventBus: {
        events: new Map(),

        /**
         * 监听事件
         * @param event - 事件名称
         * @param callback - 回调函数
         */
        on(event: string, callback: Function) {
          if (!this.events.has(event)) {
            this.events.set(event, []);
          }
          this.events.get(event).push(callback);
        },

        /**
         * 触发事件
         * @param event - 事件名称
         * @param data - 事件数据
         */
        emit(event: string, data?: any) {
          if (this.events.has(event)) {
            this.events.get(event).forEach((callback: Function) => {
              callback(data);
            });
          }
        },

        /**
         * 移除事件监听
         * @param event - 事件名称
         * @param callback - 回调函数
         */
        off(event: string, callback: Function) {
          if (this.events.has(event)) {
            const callbacks = this.events.get(event);
            const index = callbacks.indexOf(callback);
            if (index > -1) {
              callbacks.splice(index, 1);
            }
          }
        },
      },
    },
  };
});

总结

总体nuxt3语法就是vue的语法,结合一些nuxt3固有api即可实现各种功能的结合,并且支持有vue基础的前端开发人员快速上手写代码;当然更为细致的各种api应该参考各种项目的最佳实践,设计思想和官方文档进行深度学习!!!

相关推荐
薛定谔的算法2 小时前
# 从0到1构建React项目:一个仓库展示应用的架构实践
前端·react.js
Tina学编程2 小时前
HTML基础P1 | HTML基本元素
服务器·前端·html
一只小风华~3 小时前
Web前端:JavaScript和CSS实现的基础登录验证功能
前端
90后的晨仔3 小时前
Vue Router 入门指南:从零开始实现前端路由管理
前端·vue.js
LotteChar3 小时前
WebStorm vs VSCode:前端圈的「豆腐脑甜咸之争」
前端·vscode·webstorm
90后的晨仔4 小时前
零基础快速搭建 Vue 3 开发环境(附官方推荐方法)
前端·vue.js
洛_尘4 小时前
Java EE进阶2:前端 HTML+CSS+JavaScript
java·前端·java-ee
孤独的根号_4 小时前
Vite背后的技术原理🚀:为什么选择Vite作为你的前端构建工具💥
前端·vue.js·vite
吹牛不交税4 小时前
Axure RP Extension for Chrome插件安装使用
前端·chrome·axure
薛定谔的算法5 小时前
# 前端路由进化史:从白屏到丝滑体验的技术突围
前端·react.js·前端框架