Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Web 如何在es6中缓存导入的模块?_Web_Browser Cache_Es6 Modules - Fatal编程技术网

Web 如何在es6中缓存导入的模块?

Web 如何在es6中缓存导入的模块?,web,browser-cache,es6-modules,Web,Browser Cache,Es6 Modules,ES6模块允许我们创建单个入口点,如下所示: //main.js 从“foo”导入foo; foo() 对于所有这些问题,有一种解决方案不涉及查询字符串。假设您的模块文件位于/modules/中。导入模块时使用相对模块分辨率/或。/,然后在服务器端重写路径以包含版本号。使用类似于/modules/x.x.x/的方法,然后将路径重写为/modules/。现在,通过将第一个模块包含在 或者,如果您无法重写路径,则只需在开发期间将文件放入文件夹/modules/version/,然后在发布时将文件

ES6模块允许我们创建单个入口点,如下所示:

//main.js
从“foo”导入foo;
foo()

对于所有这些问题,有一种解决方案不涉及查询字符串。假设您的模块文件位于
/modules/
中。导入模块时使用相对模块分辨率
/
。/
,然后在服务器端重写路径以包含版本号。使用类似于
/modules/x.x.x/
的方法,然后将路径重写为
/modules/
。现在,通过将第一个模块包含在

或者,如果您无法重写路径,则只需在开发期间将文件放入文件夹
/modules/version/
,然后在发布时将文件夹重命名为版本号并更新脚本标记中的路径

在我看来,这可能是一个解决办法

步骤1) 使用gulp或webpack创建清单文件。这里有这样一个映射:

export default {
    "/vendor/lib-a.mjs": "/vendor/lib-a-1234.mjs",
    "/vendor/lib-b.mjs": "/vendor/lib-b-1234.mjs"
};
步骤2) 创建一个文件函数来解析路径

import manifest from './manifest.js';

const busted (file) => {
 return manifest[file];
};

export default busted;
步骤3) 使用动态导入

import busted from '../busted.js';

import(busted('/vendor/lib-b.mjs'))
  .then((module) => {
    module.default();
});

我在Chrome上做了一次短暂的尝试,效果很好。处理相对路径在这里是一个棘手的部分。

目前只是一个想法,但您应该能够让Webpack在所有拆分包中放置内容哈希,并将该哈希写入您的导入语句中。我相信它在默认情况下做到了第二点

HTTP报头用于救援。为您的文件提供文件的校验和。S3就是这样做的。 当您再次尝试导入文件时,浏览器将请求该文件,这一次将ETag附加到“”标头:服务器将验证ETag是否与当前文件匹配,并发回304未修改、保存带和时间,或文件的新内容(及其新ETag)

这样,如果您更改项目中的单个文件,用户就不必下载每个其他模块的完整内容。明智的做法是添加一个短
max age
头,这样,如果在短时间内两次请求同一模块,就不会有额外的请求

如果添加缓存破坏(例如,通过绑定器追加?x={randomNumber},或将校验和添加到每个文件名),您将强制用户在每个新项目版本下载每个必要文件的完整内容


在这两种情况下,您无论如何都要对每个文件执行一个请求(cascade上导入的文件将产生新的请求,如果您使用ETag,至少可能会以小304结尾)。为了避免这种情况,您可以使用动态导入
,例如,如果(用户单击OnSomething和IneedToloadSomeMoreTuff){import('./someModule')。然后('.')}

使用相对路径对我有效:

import foo from './foo';

而不是

import foo from '/js/modules/foo';
编辑


因为这个答案被否决了,我更新了它。模块并不总是重新加载。第一次,您必须手动重新加载模块,然后浏览器(至少是Chrome)将“理解”文件被修改,然后在每次更新时重新加载文件

如前一个答案所指出的,您可以使用ETag,或者,如果自以来进行了修改,则可以使用与
相关的
上次修改的

以下是一种可能的情况:

  • 浏览器首先加载资源。服务器响应
    上次修改:Sat,2020年3月28日18:12:45 GMT
    缓存控制:最大年龄=60
  • 如果第二次启动请求的时间早于第一次启动后的60秒,浏览器将从缓存中为文件提供服务,而不会向服务器发出实际请求
  • < LI>如果在60秒后启动请求,浏览器将考虑缓存文件过时,并且如果修改为“代码”,则发送请求:自星期六,2020年3月28日18:12:45 GMT:<代码>头。服务器将检查此值,并执行以下操作:
    • 如果文件在所述日期之后被修改,它将在正文中使用新文件发出
      200
      响应
    • 如果文件在日期后未修改,服务器将发出一个
      304
      “未修改”状态,正文为空
    最后,我为Apache服务器设置了以下内容:

    <IfModule headers_module>
      <FilesMatch "\.(js|mjs)$">
        Header set Cache-Control "public, must-revalidate, max-age=3600"
        Header unset ETag
      </FilesMatch>
    </IfModule>
    
    
    标头设置缓存控制“公共,必须重新验证,最大年龄=3600”
    标题未设置ETag
    
    您可以根据自己的喜好设置
    max age


    我们必须取消ETag。否则,Apache每次都会以
    200OK
    响应()。此外,如果您使用基于修改日期的缓存,您将不需要它。

    我想到了一个解决方案,但我不会使用,因为我不喜欢它。LOL是

    window.version=`1.0.0`;
    让{default:fu}=wait import(`./bar.js?v=${window.version}`);
    
    使用导入“方法”可以传递模板文本字符串。我还将其添加到窗口中,以便无论导入js文件有多深,都可以轻松访问它。但我不喜欢它的原因是我必须使用“wait”,这意味着它必须被包装在一个异步方法中。

    我已经创建了一个函数,它向每个模块名(静态和动态导入)添加一个内容哈希

    从'/js/foo.js'导入foo;
    导入('./bar.js')。然后(bar=>bar());
    
    变成

    从“/js/foo.abcd1234.js”导入foo;
    导入('./bar.1234abcd.js')。然后(bar=>bar());
    
    然后,您可以使用
    缓存控制:immutable
    让UAs(浏览器、代理等)无限期地缓存这些版本化的URL。一些
    max age
    可能更合理,具体取决于您的设置


    您可以在开发(和测试)过程中使用原始源文件,然后转换和缩小文件以用于生产。

    !我终于找到了一个理由。谢谢你的邀请!我反对所有那些花哨的ES模块的主要理由是破坏缓存。每次网站更新时,它都会在比赛条件下失败。我喜欢动态导入的CommonJS:<IfModule headers_module> <FilesMatch "\.(js|mjs)$"> Header set Cache-Control "public, must-revalidate, max-age=3600" Header unset ETag </FilesMatch> </IfModule>