静态资源路径必须用 iris.Dir() 包裹且传入绝对路径,如 iris.Dir(filepath.Abs("./static"));HandleDir 前缀须与前端请求 URL 严格一致;模板中应通过 StaticURL 变量动态引用;systemd 部署需显式设置 WorkingDirectory。

静态资源路径必须用 iris.Dir() 包裹,不能直接传字符串
很多人写 app.HandleDir("/static", "./static") 或 app.StaticWeb("/static", "./static"),结果部署后 404——因为 Iris v12+ 要求静态目录必须显式用 iris.Dir() 封装,否则底层会忽略或误判路径。本地开发可能碰巧跑通,但跨平台部署(比如从 macOS 编译到 Linux)时相对路径极易失效。
实操建议:
-
iris.Dir()接收的是**绝对路径**;用filepath.Abs("./static")获取当前目录下的绝对路径,或更稳妥地通过环境变量传入:os.Getenv("STATIC_ROOT") - 若用
app.HandleDir(),第二个参数必须是iris.Dir(...),不是字符串 -
app.StaticWeb()是旧版兼容方法,v12+ 推荐统一用app.HandleDir() - 路径末尾不加斜杠,
iris.Dir("/opt/myapp/static")正确,iris.Dir("/opt/myapp/static/")可能导致子路径匹配异常
/assets 这类前缀路由要和前端请求 URL 严格对齐
浏览器请求 /assets/js/app.js,但后端注册的是 app.HandleDir("/static", ...),就会 404。Iris 不做路径重写,前缀必须字面匹配。
常见错误现象:
- 前端构建配置了
publicPath: "/assets/",但后端只注册了/static - Nginx 反向代理把
/assets转发到 Go 服务,但 Go 里没注册对应路由 - Vue/React 的
base配置为"/",却把静态文件放在/dist/assets下,而 Go 只挂载了/dist根目录
解决办法:前后端约定好静态资源访问前缀,Go 端用完全一致的路径注册,例如:
app.HandleDir("/assets", iris.Dir("/opt/myapp/dist/assets"))
模板中引用静态资源要避免硬编码路径
Iris 的 HTML 模板里写 <script src="/static/js/main.js"></script> 看似合理,但一旦你把静态资源挂载路径从 /static 改成 /assets,所有模板都得改——容易漏、难维护。
推荐做法:
- 在模板上下文里注入一个
StaticURL变量,值来自配置项(如os.Getenv("STATIC_PREFIX")),模板中用{{.StaticURL}}/js/main.js - 或者用中间件统一注入:
ctx.ViewData("StaticURL", "/assets") - 避免在模板里拼接版本号(如
/js/app.js?v=1.2.3),改用构建时生成带哈希的文件名 +iris.Dir()自动匹配
Linux systemd 部署时,WorkingDirectory 影响相对路径解析
即使你用了 ./static,systemd 启动时默认工作目录是 / 或用户 home,./static 就指向错地方了。这是生产环境 404 最隐蔽的原因之一。
必须在 service 文件里显式指定:
WorkingDirectory=/opt/myapp
同时搭配:
-
StandardOutput=journal和StandardError=journal,否则日志看不到路径加载失败提示 - 代码里加
app.Logger().SetLevel("debug"),启动时会打印HandleDir registered: /assets → /opt/myapp/dist/assets这类关键信息 - 检查是否真被加载:启动后执行
sudo journalctl -u myapp -n 20,确认有HandleDir注册日志
iris.Dir() 没包、WorkingDirectory 没设、前缀不一致、日志关太早——四个点只要漏一个,静态资源就静默 404。


















