Zend Framework 1 应用程序中的缓存破坏静态资产

Posted

技术标签:

【中文标题】Zend Framework 1 应用程序中的缓存破坏静态资产【英文标题】:Cache busting static assets in Zend Framework 1 application 【发布时间】:2018-07-13 08:43:59 【问题描述】:

在带有 node.js、模块捆绑器、任务运行器等的“现代”Web 应用程序的美丽新世界中,我感到非常迷茫和愚蠢。

我有一个可用的 Zend Framework (ZF 1) php 应用程序(它还嵌入了 WordPress 多站点,允许用户创建自己的博客站点)。它托管在带有 mod_php 的 Apache 服务器上。它在表单和数据显示中使用了相当多的 html 表格,但幸好不是用于整个页面布局,尽管 css 是基于 1000 像素的固定宽度页面。

应用程序在 javascript 应该仅用于“渐进式增强”的概念下开始开发,尽管最终我们屈服于要求启用 javascript 以获得正确的行为。我们支持通过多个提供商(Facebook、Google、LinkedIn、Twitter 等)使用 OAuth2 身份验证进行注册和登录,但只能通过服务器流而不是 javascript SDK。我们使用 jQuery 和数量有限的 Zend_Dojo javascript 库以及一些自产的 javascript 函数(除了 WordPress 使用的任何东西)。

我们最近在原始 Apache 网络服务器前添加了一个 nginx 反向代理。它托管我们的 ssl 证书并提供静态文件资产。

现在,我们正在寻求采用更具响应性的设计,以更好地适应移动设备和平板电脑用户,并思考渐进式网络应用。因此,对 css 的重大更改和对 javascript 的使用的增加都在计划之中。尽管 Nginx 提供的静态资产为我们提供了 eTags,但 Google Page Speed Insights 告诉我们,我们阻止了 javascript 和 css 资源的下载,并且我们没有利用浏览器缓存。

从我看到的各种文章中可以看出,Webpack 捆绑工具可以为解决所有这些性能瓶颈提供重要帮助。但就我的一生而言,我看不出它如何适应这个生态系统。我的网站工作原理的心智模型是,http 查询由 PHP 代码分析,发送到访问会话数据和我们的 mysql 数据库的 PHP 操作例程,然后通过包含嵌入式 PHP 的 phtml 模板(ZF1 视图脚本)输出 html标签。 phtml 模板可能包含<script><style><img> 标签,这些标签可以直接包含,也可以由其他管理整个页面布局及其<header> 部分内容的PHP 函数注入到html 中。

但是当我查看 Webpack 时,它似乎期待某种 *** javascript 文件,它可以通过 import 或 @ 从中构建其他 javascript 和 css 文件的依赖关系树987654327@ 指令之类的。它以某种方式支持缓存清除,方法是对静态资产文件的内容进行哈希处理,从文件名中嵌入哈希值创建新文件,并编辑对这些文件的引用以包含哈希值。但是对于这个应用程序,所有对 javascript、css 和图像文件的引用都出现在 .phtml 文件中(通常在嵌入的 <?php> 标记中)或纯 .php 文件中。然而,webpack 似乎根本不处理 php 文件——所以我看不出它如何找到对 javascript、css 和图像文件的引用,或者编辑它们以包含哈希!而且我看到的关于在PHP项目中使用webpack的文章似乎根本没有提到这个问题。有一个 html 加载器,但没有一个用于 PHP 的。是否有某种标准做法可以在 PHP 网站中以独立的模块化方式使用 javascript,而不是使用我不知道的 <script> 标签?

最后,不同的网页对 javascript 和样式有不同的要求,而 webpack 似乎想要一个可以找到所有依赖项的单一 javascript 主入口点。在这个生态系统中使用 webpack 是否意味着为每个页面创建一个单独的 webpack 项目?我已经阅读了很多关于 webpack 的文章,但它们似乎都在处理与我的结构完全不同的 web 应用程序!

我确实在 *** 上阅读了 this 的答案,我希望这会启发我。它非常接近 - 它解释说我确实需要创建一个*** index.js 文件,需要s所有其他 javascript 文件。但是由于不同的页面使用不同的 javascript,我推断我需要为每个页面创建不同的 index.js 文件(从而将每个页面视为不同的项目)。这是真的吗?许多文章都在谈论“单页应用程序”,所以也许这只是这些描述中的假设。或者也许我需要了解“代码拆分”。也许如果我一遍又一遍地阅读那个答案,我最终会明白要点。它讨论了 CSS 和 style-loadercss-loader,但我不清楚我的 .phtml 文件中存在的 <style> 标签是如何被它们处理的(更不用说在 WordPress 代码中排队的样式了)。我已经尝试过 SurviveJs 和 Official Webpack 文档,但同样,他们似乎在谈论与我所居住的世界不同的宇宙。我认为罗塞塔石碑的存在可以将这个新世界映射回传统 PHP应用!有什么指点吗?

【问题讨论】:

【参考方案1】:

这是一个老问题,但我试图提供一些指示,因为我刚刚经历了类似的障碍:尝试将 Webpack 与旧版 ZF1 应用程序集成:

    资产捆绑 通过将版本哈希附加到文件名来破坏缓存 为不同的应用路线提供不同的捆绑包

我的做法:

首先我签入了较新版本的 Zend_View,它提供了一些用于版本控制前端资产的解决方案。我发现了这个:

https://docs.zendframework.com/zend-view/helpers/asset/

并且非常喜欢将版本控制问题封装在单独的配置文件中的想法。显然,为了能够使用这种格式,我要么必须在遗留应用程序中使用这个 zend_view 助手,要么只是扩展遗留的 zend_view 类并添加简单地读取这种格式的资源映射的 ->asset 方法:

'view_helper_config' => [
    'asset' => [
        'resource_map' => [
            'css/style.css' => 'css/style-3a97ff4ee3.css',
            'js/vendor.js' => 'js/vendor-a507086eba.js',
        ],
    ],
],

坚持这种格式的另一个好处是,一旦您将应用程序升级到较新版本的 Zend Framework 或 Zend Expressive,您无需进行任何更改,只需开始使用现代 Zend_View 的 Asset 助手即可。

一旦我们有了这样的地图,我们就需要让 webpack 编写它。所以 HtmlWebpackPlugin 并不局限于 html 文件。我们可以write our own template 并完全控制如何使用 webpack 变量(例如资产名称和哈希)编写模板。这里最大的优势是 webpack 不需要覆盖通常会变成一团糟并且有其自身问题的大量视图模板(例如,如果我们通过 headScript 调用在控制器中包含脚本怎么办?) - 它只写地图。此位解决了问题 #2 - 缓存破坏。问题 #1 和 #3 - 资产捆绑和创建不同的捆绑包现在可以通过原生 webpack 方式解决 - 通过创建多个捆绑包,然后使用我们的自定义模板编写配置文件:

const path = require('path');

 module.exports = 
     mode: 'development',
     entry: 
         'js/vendor.js': './frontend/src/js/vendor.js',
         'css/style.css': './frontend/src/css/style.js',
         // and so on...
     ,
     output: 
         filename: '[name]-[hash].js',
         path: path.resolve(__dirname, 'public/js'),
     ,
     plugins: [
         new HtmlWebpackPlugin(  // Also generate a test.html
             filename: 'view-helper-config.php',
             template: 'view-helper-config.tpl'
         )
     ]
 ;

view-helper-config.tpl 将是:

'view_helper_config' => [
    'asset' => [
        'resource_map' => [
             <% for (var chunk in htmlWebpackPlugin.files.chunks)  %>
                 <%chunk%> => <%= htmlWebpackPlugin.files.chunks[chunk].entry %>
            <%  %>
        ],
    ],
],

【讨论】:

您是否也将您的应用程序升级到 ZF 2,如果是,您希望获得什么样的好处(除了现代 Zend_View)?几年前我就考虑过,但从我当时的阅读来看,这听起来像是一项巨大的工作,却收效甚微。这些天,如果我要进行重写,我在想的是转向渐进式网络应用程序,因为原生感觉和在没有互联网连接的情况下执行某些功能的能力很重要 我从来都不喜欢 Zend Framework 在 ZF2 和 ZF3 中的发展方向,但同时 ZF1 已经过了很长时间了,我需要保持整个堆栈的新鲜和安全(升级到 php7.2 ,升级 ubuntu 等)。所以这是我升级的主要动机 - 必要性和未来的证明比任何特定的好处更重要。幸运的是,Zend 提出了 Zend Expressive - 一个精益微框架,您可以在其中挑选和匹配组件,恕我直言,它提供了从 ZF1 到 ZF1->ZF2->ZF3 废话的更短升级路线。 ZE 的配置灵活性让我可以轻松地围绕遗留系统创建外观,并开始逐步将旧的 ZF1 模型重构为 ZE 服务等。我现在看到的主要好处主要是架构方面的——我终于可以开始使用 Composer 来解决依赖关系,我终于可以正确地使用依赖注入了(与 ZF2 的服务定位器模式不同)。所有这些都有助于提高代码库的可测试性和健壮性。

以上是关于Zend Framework 1 应用程序中的缓存破坏静态资产的主要内容,如果未能解决你的问题,请参考以下文章

使用Zend Framework列出S3目录中的所有文件

DQL 语句在使用 Zend Framework 和 Doctrine 的应用程序中的位置

Zend Framework 中的动态菜单

php - Zend Framework中的冲突视图助手名称

Zend Framework windows8.1下配置zend framework1.12

我在 Zend Framework 中的哪里保存部分(视图),以便我的应用程序中的所有视图都可以访问?