一、先聊聊网页为什么慢
每个访问者打开一个 Nuxt 项目时,真正花时间的往往不是后台接口,而是浏览器要下载那一堆 JS、CSS、图片。如果这些资源体积大、文件多,还都堆在自己服务器上,加载速度自然就下来了。我们要解决的事情其实很简单:把静态资源打包得规整一点,再把它们放到离用户更近的 CDN 上,让浏览器能更快拿到。
这里说的静态资源,是指那些不会频繁变化的内容,比如样式表、脚本文件、Logo、页面里的公共图片。它们和接口数据不一样,接口每次请求都不一样,但静态资源构建一次后内容就固定了,特别适合用 CDN 缓存。
二、先搞清楚 Nuxt 里静态资源放在哪里
2.1 assets 和 public 的分工
Nuxt 项目里有两个经常让人纠结的目录,一个是 assets,一个是 public。很多新手会把图片随便丢一个目录,结果打包后路径找不到,或者文件被重复处理。
assets 里的文件是给构建工具看的。比如你在组件的 script 里引入了 CSS 或图片,Nuxt 会把它作为模块参与打包。它会经历压缩、加 hash、按需加载这一套流程。处理完之后,文件名会变成类似 logo-1a2b3c.png 的样子。
而 public 目录里的文件更像传统网站里的根目录静态文件。你放一个 logo.png,然后直接用 /logo.png 就能访问。它不会被打包器处理,也不会改文件名,构建后原样复制到输出目录。
下面是一个最简单的目录示例:
技术栈:Nuxt 3(Vue 3 + JavaScript)
└── my-nuxt-app/
├── assets/
│ └── css/
│ └── main.css
├── public/
│ ├── logo.png
│ └── favicon.ico
├── app.vue
└── nuxt.config.js
如果你想在组件里直接引用一张公共图片,把它放到 public 下面即可:
<!-- 技术栈:Nuxt 3(Vue 3 + JavaScript) -->
<template>
<header>
<!-- /logo.png 指向 public/logo.png -->
<img src="/logo.png" alt="站点 Logo">
</header>
</template>
上面的注释特意写清楚了路径对应关系,因为 public 目录不会出现在 URL 里。
2.2 assets 里的文件要怎么用
如果你希望图片经过压缩、加 hash,方便 CDN 做永久缓存,可以把它当成模块导入。
<script>
// 技术栈:Nuxt 3(Vue 3 + JavaScript)
// 导入 assets/img 下面的图片
import logo from '@/assets/img/logo.png'
export default {
name: 'AppHeader',
setup() {
// 返回给模板使用
return { logo }
}
}
</script>
<template>
<header>
<!-- 这里使用的是打包处理后的地址 -->
<img :src="logo" alt="站点 Logo">
</header>
</template>
这段代码里 @/assets 是 Nuxt 常用的别名,指向 assets 目录。构建后,logo.png 会变成带 hash 的文件名。这一步很关键,带 hash 的文件名能帮我们判断浏览器要不要重新下载资源。
三、构建配置里的关键参数
3.1 配置 CDN 地址和构建资源目录
Nuxt 3 中,我们可以直接在 nuxt.config.js 里设置 CDN 地址。CDN 地址可以理解成静态资源的主机头,也就是 URL 前面那一段。
// nuxt.config.js
// 技术栈:Nuxt 3(Vue 3 + JavaScript)
export default defineNuxtConfig({
app: {
// 如果你的站点不在域名根目录,可以改成 /子目录/
baseURL: '/',
// 打包后的 JS、CSS 放在这个目录下,默认是 _nuxt
buildAssetsDir: '_nuxt',
// CDN 域名,部署时请换成你自己的
cdnURL: 'https://static.my-site.com'
}
})
这里 cdnURL 主要影响的是通过打包生成的那批 JS、CSS 文件。配置好后,构建出来的 HTML 里,脚本和样式地址会以 https://static.my-site.com/_nuxt/ 开头。
为了让大家看得更清楚,可以对比一下配置前后的效果。假设你执行构建命令:
# 技术栈:Nuxt 3(Vue 3 + JavaScript)
npm run build
构建完成后的 HTML 里,你会找到类似下面的标签:
<!-- 配置了 cdnURL 之后,浏览器会从这里加载资源 -->
<script src="https://static.my-site.com/_nuxt/main-abc123.js"></script>
<link rel="stylesheet" href="https://static.my-site.com/_nuxt/main-abc123.css">
而没配置之前,这些地址通常是 / 开头的相对路径。
3.2 想要真正让 CDN 生效,还需要考虑部署方式
这里要分两类场景。第一种是纯静态站点。你可以用 nuxi generate 生成静态文件,然后把生成的 dist 或 .output/public 目录上传到对象存储,再套一层 CDN。此时访问者获取 HTML、JS、CSS、图片都可以走 CDN 节点,速度提升非常明显。
第二种是 Node 服务端部署。假如你在服务器上运行 node .output/server/index.mjs,那么页面 HTML 由 Node 服务生成,而 JS、CSS 这类静态文件仍然可以交给 CDN。配置好 cdnURL 后,浏览器加载这些文件时会直接请求 CDN,服务器压力就会小很多。
需要提醒的是,不要忘记把构建出来的静态文件同步到 CDN 源站。很多平台提供了自动同步或者回源功能,如果没有,就要在发版流程里加上上传静态文件这一步。
四、应用场景:什么时候最需要这样优化
我见过最典型的场景是图片资源多、营销活动页面、面向全国用户的产品站点。用户分布在不同地区,自己单独一台服务器扛不住带宽。尤其遇到活动时,大量 JS 和图片同时请求,服务器出口带宽很容易被打满。
另一个明显场景是每次发版都会更新文件名。配置了带 hash 的文件名后,没有变化的文件,CDN 可以继续缓存很久;只有内容变化的那个文件,文件名才会变化,CDN 就会重新回源获取。这种精确失效的缓存策略,是纯手工管理静态资源很难做到的。
如果你的项目只是内部管理后台,用户几十个,且都集中在一个网络环境,其实没必要折腾 CDN。不要为了技术看起来高级而上 CDN,这是很多团队踩过的坑。静态资源优化有收益,但也有成本和复杂度。
五、这样做的好处和坏处
5.1 优点
第一,加载速度更快。CDN 节点离用户近,网络延迟低。第二,服务器压力小。原本所有 JS、CSS、图片都从你的服务器下载,现在 CDN 扛掉了大头。第三,缓存策略更清晰。文件名带 hash,版本变化一目了然,线上问题排查时也更容易。
5.2 缺点
首先,配置和发布流程会变复杂。你不能再只执行本地启动命令就完事,构建后要上传资源、刷新 CDN 缓存,出错概率增加。其次,如果 CDN 配置得不好,比如没有清理旧文件,或者回源设置错误,很容易出现线上资源更新了,但用户还在用旧版。另外,CDN 服务是需要费用的,流量特别大时,费用会变成一个需要关注的因素。
这些缺点不是让你放弃优化,而是建议在动手前想清楚:你的用户分布、流量规模、团队运维能力是否合适。
六、注意事项:这些坑一定要避开
6.1 public 目录下的资源不会被处理
public 里的文件不会加 hash,不会压缩,也不会改名字。如果修改了 public/logo.png,图片访问地址还是 /logo.png。如果 CDN 缓存了这张图,用户短时间内还是看到旧图。这时你需要手动更新 CDN 缓存,或者把文件名改掉。
6.2 尽量使用相对稳定的 CDN 域名
千万不要今天用一个域名,明天换另一个域名。每次换域名,所有资源链接都会变化,浏览器缓存等于全部失效。如果一定要换,最好能提前规划好下线和过渡方案。
6.3 注意跨域问题
如果 CDN 域名和当前站点不是同一个域名,而你的字体文件、Canvas 绘制操作需要读取资源内容,就会遇到跨域问题。一般来说,静态资源通过 script、img、link 标签加载不受跨域影响,但如果你用 fetch 去请求,或者引入 Web Font 时需要进行跨域读取,就需要在 CDN 上配置 CORS 响应头。
6.4 请把缓存时间设置正确
带 hash 的资源文件名基本不变,所以可以设置很长的缓存时间。不带 hash 的文件,比如 public 里的图片、HTML 页面本身,应该设置短缓存或者不缓存,避免更新后用户拿不到最新页面。
一个常见的配置思路是:
// 这个只是便于理解的规则,不是实际代码
// 带 hash 的 JS/CSS:一年
// HTML 页面:不缓存
// public 里会变动的图片:30 天或更短
如果你的 CDN 平台不支持这种规则,就要在边缘服务或源站里手动配置。
七、文章总结
Nuxt 项目要提速,比较大的收益点就是管理好静态资源。先把 assets 和 public 的用途分清楚,再决定哪些文件参与打包、哪些文件原样发布。然后通过 nuxt.config.js 里的 baseURL、buildAssetsDir、cdnURL 几个配置,把打包后的资源地址指向 CDN,同时配合合理的缓存时间,就能让用户在打开页面时更快拿到样式和脚本。
最后再强调一遍:配置 CDN 不是终点。你还需要在发布流程里保证构建文件和 CDN 内容是同步的,在线上出问题时能迅速判断用户拉到的到底是哪个版本。把这些基础工作做扎实,网站加载速度才能稳定地好起来。
评论
围绕“Nuxt.js资源加载优化:处理静态资源打包与CDN加速的配置问题”参与讨论