ES6模块允许我们创建一个单一的入口点,如下所示:
// main.js
import foo from 'foo';
foo()

<script src="scripts/main.js" type="module"></script>
&#13;
foo.js 将存储在浏览器缓存中。在我将 foo.js 的新版本推向生产之前,这是可取的。
通常的做法是添加一个具有唯一ID的查询字符串参数,以强制浏览器获取新版本的js文件( foo.js?cb = 1234 )
如何使用es6模块模式实现这一目标?
答案 0 :(得分:1)
对于所有这一切,有一个不涉及查询字符串的解决方案。假设您的模块文件位于/modules/
中。导入模块时,请使用相对模块分辨率./
或../
,然后在服务器端重写路径以包含版本号。使用类似/modules/x.x.x/
的内容,然后将路径重写为/modules/
。现在,只需在第一个模块中添加以下内容,即可获得模块的全局版本号
<script type="module" src="/modules/1.1.2/foo.mjs"></script>
或者,如果您无法重写路径,则只需在开发过程中将文件放入文件夹/modules/version/
中,然后将version
文件夹重命名为版本号,并在发布时更新脚本标记中的路径。
答案 1 :(得分:1)
从我的角度来看,dynamic imports是这里的解决方案。
步骤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浏览器中尝试了一下,即可正常工作。在这里处理相对路径是棘手的部分。
答案 2 :(得分:0)
此刻只是一个想法,但是您应该能够使weboack将内容哈希放入所有拆分包中,并为您将该哈希写入到import语句中。我相信默认情况下它会执行第二个操作。
答案 3 :(得分:0)
用于救援的HTTP标头。使用ETag(即文件的校验和)为文件提供服务。例如,S3会执行by default。 当您尝试再次导入文件时,浏览器将请求该文件,这次将ETag附加到“ if-none-match”标头中:服务器将验证ETag是否与当前文件匹配,并发送回304 Not修改后,可节省带宽和时间,或文件的新内容(带有新的ETag)。
这样,如果您在项目中更改单个文件,则用户将不必下载所有其他模块的全部内容。最好添加一个简短的D
标头,这样,如果在短时间内两次请求相同的模块,就不会有其他请求。
如果添加缓存清除(例如,通过捆绑程序添加?x = {randomNumber},或将校验和添加到每个文件名),将强制用户在每个新项目版本中下载每个必需文件的全部内容。
在两种情况下,您无论如何都要对每个文件进行请求(级联导入的文件将产生新请求,如果使用etag,则至少可以以小304结尾)。为避免这种情况,您可以使用动态导入C object
答案 4 :(得分:0)
您可以使用上一个答案指出的ETag,也可以将Last-Modified
与If-Modified-Since
结合使用。
这是一种可能的情况:
Last-Modified: Sat, 28 Mar 2020 18:12:45 GMT
和Cache-Control: max-age=60
进行响应。If-Modified-Since: Sat, 28 Mar 2020 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>
您可以根据自己的喜好设置max-age
。
我们必须取消设置ETag。否则,Apache每次(it's a bug)都会始终以200 OK
进行响应。此外,如果您基于修改日期使用缓存,则不需要它。
答案 5 :(得分:0)
我创建了一个 Babel plugin,它将内容哈希添加到每个模块名称(静态和动态导入)。
import foo from './js/foo.js';
import('./bar.js').then(bar => bar());
变成
import foo from './js/foo.abcd1234.js';
import('./bar.1234abcd.js').then(bar => bar());
然后您可以使用 Cache-control: immutable
让 UA(浏览器、代理等)无限期地缓存这些版本化的 URL。一些 max-age
可能更合理,具体取决于您的设置。
您可以在开发(和测试)期间使用原始源文件,然后转换和缩小用于生产的文件。
答案 6 :(得分:-1)
一个让我大吃一惊但我不会使用的解决方案,因为我不喜欢大声笑
window.version = `1.0.0`;
let { default: fu } = await import( `./bar.js?v=${ window.version }` );
使用导入的“方法”可以传递模板文字字符串。我还将其添加到窗口中,以便无论我导入js文件的深度如何都可以轻松访问它。我不喜欢它的原因是我必须使用“ await”,这意味着它必须包装在异步方法中。
答案 7 :(得分:-5)
使用相对路径对我有用:
import foo from './foo';
或
import foo from './../modules/foo';
代替
import foo from '/js/modules/foo';
编辑
由于该答案已被否决,因此我对其进行了更新。并非总是重新加载模块。第一次,您必须手动重新加载模块,然后浏览器(至少是Chrome)将“了解”文件已修改,然后在每次更新时重新加载文件。