hexo博客图片无法显示的问题解决方法
本文需要一些耐心阅读
许多朋友在初次使用hexo搭建博客时可能和我一样,都会遇到图片无法显示的问题。我在网上搜索了大量的资料,发现都无法解决我的问题,把_config.yml
中的post_asset_folder
也设为 true
了,hexo-asset-image
插件也装了,但就是不行。后来找来找去,在 hexo-asset-image
中发现了端倪。本文最后将会从 hexo-asset-image
的源码上来分析问题,大家不要畏惧,这个插件的源码很简单,都是一些字符串操作。
追根溯源
首先,在一个网页中,图片加载不出来有两种情况,1. 图片服务器宕机,2. 图片URL错误。第一种情况属于个人博客服务器的问题,不在我们的讨论范围内,我们的重点是,图片的URL。
首先要理解hexo的原理,我们给hexo提供markdown文件,hexo生成静态网页,在hexo生成HTML网页的时候,就是图片URL写入的时候,而 hexo-asset-image
插件就是在hexo每生成一个HTML网页时,修改其中<img>
标签的 src
属性,从而能引用到正确的图片
然后就是 post_asset_folder
属性,这个属性为true时,运行 hexo new "passage name"
创建文章时,hexo会在 source/_posts/
目录下创建一个和文章的markdown文件名相同的文件夹,这个文件夹就hexo存放我们的markdown中图片的地方。为了和hexo的图片文件夹保持同步,我们还需要对markdown编辑器的文件路径进行一些调整,我使用的是Typora,来到Typora的设置中,找到图像选项,设置为以下这样:

如果你的文章现在已经有了一些图片,那么你可能需要修改一下图片的文件夹名,和文章中引用图片的markdown语句,来确保引用了正确的图片。
除此之外,这个属性对于 hexo-asset-image
这个插件来说至关重要,我们来看看 hexo-asset-image
的源码:
大家注意到了吗,在上图的if
语句中,有:config.post_asset_config
没错,当post_asset_config
这个属性为true
时,才会执行 hexo-asset-image
插件的一系列逻辑!所以 post_asset_config
这个属性是一定要设置为 true
的,否则插件不会生效。
你还需要注意一个博客配置文件_config.yml
的属性:permalink
。这个属性定义了你的每一篇文章的URL是怎样的,默认值是这样的:
1 | permalink: :year/:month/:day/:title/ |
例如,我的博客网站地址是 www.example.com , 那么我在2024年10月10日写的标题为test的文章的地址就是: www.example.com/2024/10/10/test ,我们后面的配置都会按照上面的这个格式来,建议大家设为和我一样
查看你的网页图片src
属性
在进行接下来的步骤之前,你需要确保
_config.yml
文件中:post_asset_folder
已设置为true
,permalink
已设置为:year/:month/:day/:title/
先别急着安装
hexo-asset-image
插件
既然图片渲染不出来,那么看看它的src
属性是啥不就行了嘛,这里有两种方法,第一种是直接在浏览器的F12菜单中查看,第二种是去到你的博客目录的 public/:year/:month/:day/:title/
没错,就是我们前文通过permalink
所设置的日期路径,打开这个文件夹后,你会发现你的图片就在这里面,除此之外还有一个HTML文件,这个文件就是hexo根据你的md文件渲染出来的HTML网页。
我们打开这个HTML文件,查看img
标签的src
属性,发现是这样的:
安装 hexo-asset-image
插件
这很明显不对!我们期望的路径应该是/2024/10/27/test/image-20241027143951576.png
,这个时候我们再装上hexo-asset-image
插件:npm install hexo-asset-image --save
,然后运行:
1 | hexo clean |
再来看看区别:
可以看到路径更加牛头不对马嘴了,这里解释一下,撰写这篇文章时,我的博客是用IP地址部署的,也就是说没有域名,我的IP地址后两位就是82,而82前面那个英文句点自然就是IP地址中的分割点了,从这里就可以看出,是hexo-asset-image
这个插件有问题,把图片映射到了错误的路径。
解决问题:修改hexo-asset-image
的源码
源码可以在<你的博客目录>/node_modules/hexo-assets-image/index.js
找到
这里我直接将代码的关键部分贴出来:
1 | // http://stackoverflow.com/questions/14480345/how-to-get-the-nth-occurrence-in-a-string |
首先我们来分析一下其中的各个变量代表什么含义,首先就是 var link = data.permalink
这句,我虽然没有了解过如何编写hexo插件,但是结合我们刚才在配置文件中看到的 permalink
属性就可以猜出来,data.permalink
实际上就是文章的URL,而且是包括了域名的URL,我们可以尝试将其打印出来看看:console.log("permalink: " + link)
注意这个打印语句并非是在你每次访问文章网页的时候打印到浏览器的F12菜单的控制台里面的,而是在你每次运行 hexo g
命令时,输出到命令行里面的,所以要想看到输出,我们就必须要运行 hexo g
,运行后,你会发现输出了很多行语句,hexo-asset-image
这个插件的原理就是在hexo生成完静态网页后,修改其中的img
的src
属性,所以你有多少篇文章,这个语句就会被执行多少次!我的输出是这样的:
理解了data.permalink
是什么,我们来继续读代码,可以看到又调用了一个 getPosition
函数,这个函数是定义在代码最开头的,我们来看看:
1 | function getPosition(str, m, i) { |
使用了字符串的split
方法,这个方法的第二个参数是用来限制分割后的列表长度的,例如:
1 | "hello,world,are,you,ok".split(",", 3) // ["hello", "world", "are"] |
根据我的URL,经过它传入的参数调用这个函数,最终的beginPos
的值应该是:20,也就是指向 /2024
处的斜杠的位置
好的我们继续往下看,它的注释写的很清楚,就是处理URL中有无index
子串或者index.html
子串,我们重点来看else
的部分(因为我的博客URL没有index
或者index.html
关键字),可以看到这部分代码出现了明显的错误!怎么能直接去找最后一个".“的位置呢,这也是我们前面看到的src
属性出现了:”.82"的字样的原因,只需要将这行代码改成下面这样就行了:
1 | var endPos = link.length + 1; |
没错就是这么简单,直接让他指向URL的末尾就可以了
再继续看:
1 | link = link.substring(beginPos, endPos) + appendLink; |
这行代码就是在得出最后的图片路径了,在我的博客配置下,appendLink
变量是一个空字符串。
不妨来输出一下这个link变量:console.log("final link: " + link)
成功了!
这时候再次运行hexo g
,查看生成的HTML中img的src属性:
路径终于正确了!
至此,博客上面的图片就能正常加载出来了