1. 为什么我的图片在本地好好的,一打包部署就“消失”了?
相信很多刚开始用 VueCli 的朋友都遇到过这个让人头疼的问题:开发的时候,图片显示得好好的,页面效果完美。结果一运行 npm run build 打包,再把 dist 文件夹扔到服务器上,页面上的图片就集体“失踪”了,只剩下一个个破碎的图标。控制台里还报了一堆 404 错误,看得人一头雾水。
这背后的“罪魁祸首”,其实就是静态资源的路径问题。VueCli 基于 Webpack 构建,它在开发和生产两种模式下,处理资源路径的逻辑是完全不同的。开发时,我们用的是 Webpack 的 Dev Server,它会启动一个本地服务器,动态地处理所有模块依赖,包括图片。这时候,你写的 ../assets/logo.png 或者 @/assets/logo.png,Webpack 都能帮你正确解析和热更新。
但到了打包环节,情况就变了。Webpack 会把你的代码、样式、图片等资源进行压缩、合并、重命名(比如加上哈希值 logo.abc123.png 用于缓存),然后输出到 dist 目录。这个过程里,资源的相对位置和最终访问路径都发生了变化。如果你还按照开发时的路径去引用,浏览器在访问生产环境时,自然就找不到这些被“搬家”和“改名”的文件了。
我刚开始做项目时,也在这里栽过跟头。记得有一次给客户部署一个宣传页到子目录,比如 www.example.com/campaign/,结果页面一片空白,查了半天才发现,所有 JS、CSS 和图片的请求都指向了 www.example.com/static/...,完全忽略了 /campaign/ 这个前缀。所以,理解 VueCli 和 Webpack 的路径处理机制,是解决这类问题的第一步。
简单来说,你需要搞清楚两件事:第一,你的资源是放在 src/assets 下(让 Webpack 管理),还是 public 目录下(直接拷贝);第二,你的应用最终要部署在服务器的哪个位置(根目录还是子路径)。这两个决定,直接影响了你的配置和写法。
2. 两种引入方式:assets 与 public 的抉择
VueCli 项目里,处理静态资源(主要是图片)主要有两种方式,对应着两个不同的文件夹:src/assets 和 public。选错了地方,麻烦就来了。
2.1 放在 src/assets:让 Webpack 接管
assets 目录是推荐的存放方式。放在这里的资源会被视为模块依赖,由 Webpack 统一处理。
怎么用? 在模板、JS 或 CSS 中,使用相对路径引入。
<!-- 在 .vue 文件的模板中 -->
<img src="../assets/logo.png" alt="logo">
<!-- 在组件的 style 标签中 -->
<style>
.logo {
background-image: url('../assets/bg.jpg');
}
</style>
<!-- 在 JS 中导入(比如作为组件数据) -->
<script>
export default {
data() {
return {
imgUrl: require('../assets/icon.png') // 注意这里用了 require
}
}
}
</script>
优点是什么? Webpack 会做很多优化工作:小图片会被转换成 Base64 内联,减少 HTTP 请求;大图片会被压缩并输出到 dist/static/img/ 这类目录下,且文件名会带上内容哈希(如 logo.abc123.png),这样你更新图片后,哈希值变了,文件名就不同,能有效避免浏览器缓存旧文件。而且,如果路径写错了,在编译阶段就会报错,不会等到上线才发现。
我踩过的坑:动态绑定 src 这里有个关键点,上面例子中 <img src="../assets/logo.png"> 是写死的字符串,Webpack 在编译模板时能识别并处理这个路径。但如果你用 :src 动态绑定一个字符串,情况就不同了。
<!-- 假设 data 中 imagePath: '../assets/logo.png' -->
<img :src="imagePath">
这样写,图片大概率会加载失败。因为 :src 绑定的是一个 JavaScript 表达式(这里是变量 imagePath 的值),Webpack 在编译时无法分析这个变量的值具体是什么,因此不会去处理 ../assets/logo.png 这个图片文件。打包后,这个路径原封不动地出现在 HTML 里,浏览器会按照这个相对路径去请求,而图片文件早已被 Webpack 移动并重命名了,当然找不到。
解决方案:使用 require 要让动态绑定的图片也被 Webpack 处理,必须用 require 显式地告诉 Webpack:“这是一个模块,请打包它”。
<img :src="require('../assets/logo.png')">
<!-- 或者在 data 中定义 -->
<script>
export default {
data() {
return {
logo: require('@/assets/logo.png') // 使用 @ 别名指向 src 目录更简洁
}
}
}
</script>
<template>
<img :src="logo">
</template>
require 是 CommonJS 的模块引入语法,在构建阶段,Webpack 会执行它,将图片模块化,并返回最终打包后的正确路径(可能是 Base64 或带哈希的 URL)。这是处理 assets 目录下图片动态引入的标准做法。
2.2 放在 public 目录:简单直接的拷贝
public 目录(在 VueCli 3+ 中,原来是 static 目录)是另一种选择。放在这里的文件,不会经过 We



被折叠的 条评论
为什么被折叠?



