Windsooon
(Windson yang)
1
我正在尝试为我的论坛设置 CDN。由于中国封禁了 Fastly 以及许多 CDN 服务器,我无法使用它们来加速我的论坛。经过一番研究,我转向了 Jsdelivr,它可以提供来自 npm 或 Github 仓库的静态文件。
我知道可以在 app.yml 中使用 DISCOURSE_CDN_URL 来设置 URL。但在此之前,我必须收集论坛中的所有静态文件(js、CSS),然后将它们上传到 Github,以便 Jsdelivr 能够访问。我发现这些静态文件实际上位于 Docker 容器内的:
/var/www/discourse/app/assets
因此,我打算在每次重建应用后,从该路径复制所有文件,然后上传到 Github。我想这个方案应该可行,但实际的请求中包含一个很长的哈希文件名,我不知道该如何获取它。例如,
ember_jquery.js 会变成
ember_jquery-8ef4e572f0bf9485e6ef9a35f088729735f82434cf495fbcd5acedefbcddb363.js
所以我的问题是:
- 如何生成带哈希的文件名?
- 是否有其他方法可以收集这些静态资源?
schleifer
(Andrew Schleifer)
2
这是文件内容的 SHA1 哈希值。它在以下位置生成:
生成的编译版本会被放置在 /var/www/discourse/public/assets/ 目录中。
如果您在 app.yml 中添加一个配置段,就可以在容器重建后执行操作。例如,上传到 S3 时,我们使用类似以下的配置:
hooks:
after_assets_precompile:
- exec:
cd: $home
cmd:
- sudo -E -u discourse bundle exec rake s3:upload_assets
在您的情况下,请将 rake 任务替换为在容器构建时用于将编译后的资源推送到 GitHub 的命令。
Windsooon
(Windson yang)
3
感谢 @schleifer。您的回复非常有帮助。不过,我还有几个后续问题:
-
我可以在哪里找到像 after_assets_precompile 这样的 hooks 的文档?我搜索了 Docker 文档以及 Discourse 的 GitHub 仓库,但没找到任何相关信息。我需要自己设置名为 after_assets_precompile 的 hooks 吗(具体怎么做?)还是它已经像 after_code 一样由 Discourse 预设好了?
-
据我理解,我的伪代码大致如下:
hooks:
after_assets_precompile:
- exec:
cd: $home
cmd:
- 进入 Docker 容器
- 切换到 `/var/www/discourse/public/assets/` 目录
- 执行 git add、commit 并推送到 GitHub 仓库
谢谢。
schleifer
(Andrew Schleifer)
4
这是个很好的问题,但我没有很好的答案。
容器内部使用的配置系统是:
那里的 README 描述了钩子的一般工作原理。可用的具体钩子取决于您的实例如何设置——主要的 app.yml 会包含一个或多个模板。在大多数情况下,其中之一是 web.template.yml:
assets_precompile 钩子就在那里定义(在我输入时位于第 159 行)。根据 pups 文档,您可以使用 before_assets_precompile 和 after_assets_precompile 分别在该钩子完成之前或之后运行其他命令。
命令是在 Docker 容器内运行的,因此您无需为此做任何事情。
cd: 指令可以直接指向 /var/www/discourse/public/assets/,cmd 中的每一行都将从该目录运行。(警告:cmd 数组中的每一行都在单独的 shell 中运行,就像在 Makefile 中一样)。
我不确定 /var/www/discourse/public/assets/ 的内容是否会在构建之间保留,因此您可能每次都需要创建本地 Git 仓库并强制推送。更“正确”的解决方案可能是在 app.yml 中为资产目录定义一个 Docker 卷,该卷在 app.yml 中定义 与其他卷类似,并保留在容器外部。
Windsooon
(Windson yang)
5
非常感谢。我还发现一些静态资源(如 CSS)被存放在 /var/www/discourse/tmp/stylesheet-cache 中。但还有两个问题:
- 用户上传的资源(例如头像)在设置 DISCOURSE_CDN_URL 后也会由 CDN 提供。然而,每次用户上传后都将这些资源推送到 GitHub 似乎并不是一个理想的解决方案。
- 当 Discourse 请求用户头像(如
2_2.png)时,它会:1) 拆分文件名,2) 进行一些检查,3) 通过哈希计算真实的文件名。如果我要提供用户头像,就必须自己实现相同的逻辑,因为实际上并没有名为 2_2.png 的文件。
我的最终解决方案很简单:1) 在我的论坛前添加 Nginx,参考这篇帖子。2) 从上述路径收集所有静态资源并推送到 GitHub。3) 在 Nginx 配置文件中添加一些规则,例如:
location ~/(stylesheets|assets) {
return 301 https://cdn.jsdelivr.net/gh/my_github/my_repo/$request_uri;
}
再次感谢 @schleifer