繁体   English   中英

如何处理作为 ES6 模块导入的 JavaScript 文件的缓存

[英]How to handle caching of JavaScript files imported as ES6 module

旧情

以前,如果有可用的新版本,我使用以下方法强制浏览器重新加载我的 JavaScript 文件。

<script src="common.js?version=1337"></script>
<script src="app.js?version=1337"></script>

我的 HTML 是自动生成的(例如使用 PHP),因此很容易实现自动化。

新形势

现在我想使用 ES6 模块并导入我的常用代码。 我的 HTML 变为:

<script src="app.js?version=1337" type="module"></script>

app.js包含导入:

import {foo, bar} from './common.js';

问题

现在我的问题是:在新场景中如何影响common.js的缓存?

我不想每次编辑common.js时都手动编辑app.js 如果可能的话,我也不想动态生成/预处理我的任何 JavaScript 文件。

ES6模块可以导入输出有效JS的PHP文件。 只要你也设置了正确的标题,你应该没问题。

所以你的index.php文件将包含:

<script src="app.js.php?version=1337" type="module"></script>

你的app.js.php文件将包含:

<?php
  header("Content-Type: application/javascript");
  $version = 1337; // Probably imported form some config file;
?>
import {foo, bar} from './common.js.php?version=<?=$version?>';

简洁版本:

只需使用Webpack ,您就可以继续使用您的技巧,因为所有的 javascript 都将在一个文件中。

长版:

你说你不想预处理你的 javascript 文件。 我会重新考虑这种立场。 大多数现代 Web 应用程序(及其相关框架,如 React、Angular、Vue.js)都是使用某种预处理器/打包器构建的,这些预处理器/打包器将应用程序的所有 javascript 捆绑到一个或多个文件中。

这样做有很多很好的理由,我们不需要在这里全面重复,但简而言之,您可以轻松地进行类型检查(例如 TypeScript)、linting、摇树、优化、混淆和压缩。

捆绑的 javascript 通常更小(大幅度)、更快、更正确。 它会导致更短的加载时间和更少的带宽使用,这在如今超过 50% 的网络流量来自移动设备时尤为重要。

虽然这可能有点学习曲线,但这是我们行业前进的方向,并且有充分的理由。 没有一种简单的方法在 ES 模块中包含缓存破坏查询参数重要的原因可能是因为该语言的设计者认为它是一种反模式。

您可以使用动态导入- 如果您使用的是 ES6 模块(似乎是这种情况) - 或者如果您使用任何允许您通过 .htaccess 等文件控制响应标头的服务器,则可以使用缓存控制响应.htaccess

我知道这个问题已有 5 年历史,但我昨天遇到了这个问题,捆绑器并不总是适用于所有类型的项目。

解决方案 1:动态导入

动态导入可以在模块的顶层使用,就像常规import声明一样。 您只需要添加await运算符并将其值分配给常量。

以下示例考虑您正在使用 PHP 并且您不希望使用它发出您的导入行,只希望版本号。

index.php

<?php
// Add your dynamic version number somewhere accessible 
// to JS (constant, element attribute, etc.).
echo '<script>const assetsVersion = "' . $assets_version . '";</script>';

应用程序.js

// Add your import to the top-level of your module referencing
// the version number in the string.
const { MyImport } = await import("./my-import.js?v=" + assetsVersion);

该解决方案允许您保留当前的缓存清除技术——并且无论使用何种后端技术都可以正常工作。

解决方案 2:缓存控制

此选项要求您修改.htaccess文件。 设置no-cache响应指令将使您的浏览器在实际使用它们之前验证您的缓存资产(与no-store指令不同)。

验证是通过If-None-MatchIf-Modified-Since请求标头完成的。 如果文件未被修改,服务器将响应 304 状态代码;如果资产已更新,服务器将响应 200 状态代码 - 导致您的浏览器重新下载它。

.htaccess

<IfModule mod_headers.c>
    <FilesMatch "\.(css|js)$">
        Header set Cache-Control "no-cache"
    </FilesMatch>
</IfModule>

如果您使用的是 Apache,您可能会遇到服务器总是返回 200 的问题(据我所知是由于错误)。 删除ETag header 可能会解决它(对我有用):

<IfModule mod_headers.c>
    <FilesMatch "\.(css|js)$">
        Header set Cache-Control "no-cache"
        Header unset ETag
    </FilesMatch>
</IfModule>

此解决方案会影响模块导入和普通脚本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM