RequireJS가 필수 스크립트를 캐시하지 못하도록 방지
RequireJS는 필요한 자바 스크립트 파일을 캐시하는 내부 작업을 수행하는 것 같습니다. 필요한 파일 중 하나를 변경하면 변경 사항이 적용되도록 파일 이름을 바꿔야합니다.
파일 이름 끝에 querystring 매개 변수로 버전 번호를 추가하는 일반적인 트릭은 requirejs에서 작동하지 않습니다. <script src="jsfile.js?v2"></script>
내가 찾고있는 것은 업데이트 할 때마다 스크립트 파일의 이름을 바꾸지 않고도 RequireJS 필수 스크립트의 내부 캐시를 방지하는 방법입니다.
플랫폼 간 솔루션 :
이제 urlArgs: "bust=" + (new Date()).getTime()
개발 중에 자동 캐시 버스 팅 및 urlArgs: "bust=v2"
업데이트 된 필수 스크립트를 롤아웃 한 후 하드 코딩 된 버전 수를 늘리는 프로덕션에 사용하고 있습니다.
노트 :
@Dustin Getz는 최근 답변에서 Javascript 파일을 이와 같이 지속적으로 새로 고칠 때 Chrome 개발자 도구가 디버깅 중에 중단 점을 제거한다고 언급했습니다. 한 가지 해결 방법은 debugger;
대부분의 Javascript 디버거에서 중단 점을 트리거하기 위해 코드 를 작성 하는 것입니다.
서버 별 솔루션 :
노드 또는 Apache와 같은 서버 환경에 더 적합한 특정 솔루션에 대해서는 아래 답변 중 일부를 참조하십시오.
캐시 버스 팅을 위해 각 스크립트 URL에 값을 추가하도록 RequireJS를 구성 할 수 있습니다.
RequireJS 문서 ( http://requirejs.org/docs/api.html#config )에서 :
urlArgs : RequireJS가 자원을 페치하기 위해 사용하는 URL에 추가 된 추가 쿼리 문자열 인수. 브라우저 나 서버가 올바르게 구성되지 않은 경우 버스트 캐시에 가장 유용합니다.
모든 스크립트에 "v2"를 추가하는 예 :
require.config({
urlArgs: "bust=v2"
});
개발 목적으로 타임 스탬프를 추가하여 RequireJS가 캐시를 무시하도록 할 수 있습니다.
require.config({
urlArgs: "bust=" + (new Date()).getTime()
});
urlArgs를 사용하지 마십시오!
스크립트로드에는 http 캐싱 헤더가 필요합니다. (스크립트는 동적으로 삽입 된 상태로로드됩니다. <script>
즉, 요청은로드 된 기존 애셋과 유사합니다.)
개발 중에 캐싱을 비활성화하려면 적절한 HTTP 헤더를 사용하여 Javascript 자산을 제공하십시오.
require의 urlArgs를 사용하면 설정 한 중단 점이 새로 고침 동안 유지되지 않습니다. 결국 debugger
코드 어디에나 명령문 을 넣어야 합니다. 나쁜. urlArgs
git sha를 사용하여 프로덕션 업그레이드 중에 캐시 버스 팅 자산에 사용 합니다. 그런 다음 자산을 영구적으로 캐시하도록 설정하고 오래된 자산이없는 것을 보장 할 수 있습니다.
개발 과정에서 복잡한 mockjax 구성으로 모든 ajax 요청을 조롱 한 다음 모든 캐싱이 해제 된 10 줄 파이썬 http 서버로 자바 스크립트 전용 모드로 앱을 제공 할 수 있습니다 . 이로 인해 수백 개의 편안한 웹 서비스 엔드 포인트가있는 상당히 큰 "엔터프라이즈"응용 프로그램으로 확장되었습니다. 백엔드 코드에 액세스하지 않고도 실제 프로덕션 코드베이스로 작업 할 수있는 계약 된 디자이너도 있습니다.
urlArgs 솔루션에 문제가 있습니다. 불행히도 귀하와 사용자의 웹 브라우저 사이에있을 수있는 모든 프록시 서버를 제어 할 수는 없습니다. 이러한 프록시 서버 중 일부는 파일 캐싱시 URL 매개 변수를 무시하도록 구성 할 수 있습니다. 이 경우 잘못된 버전의 JS 파일이 사용자에게 전달됩니다.
나는 마침내 내 자신의 수정 사항 을 require.js에 직접 포기하고 구현했습니다 . requirejs 라이브러리의 버전을 기꺼이 수정하려는 경우이 솔루션이 적합 할 수 있습니다.
여기서 패치를 볼 수 있습니다.
https://github.com/jbcpollak/requirejs/commit/589ee0cdfe6f719cd761eee631ce68eee09a5a67
추가 한 후에 require config에서 다음과 같은 작업을 수행 할 수 있습니다.
var require = {
baseUrl: "/scripts/",
cacheSuffix: ".buildNumber"
}
빌드 시스템 또는 서버 환경을 buildNumber
사용하여 개정 ID / 소프트웨어 버전 / 좋아하는 색상 으로 바꾸십시오 .
다음과 같이 요구합니다.
require(["myModule"], function() {
// no-op;
});
이 파일을 요청해야합니다.
http://yourserver.com/scripts/myModule.buildNumber.js
서버 환경에서 URL 재 작성 규칙을 사용하여 buildNumber를 제거하고 올바른 JS 파일을 제공합니다. 이렇게하면 실제로 모든 JS 파일의 이름을 바꾸는 것에 대해 걱정할 필요가 없습니다.
패치는 프로토콜을 지정하는 모든 스크립트를 무시하고 비 JS 파일에는 영향을 미치지 않습니다.
이것은 내 환경에서는 잘 작동하지만 일부 사용자는 접미사가 아닌 접두사를 선호한다는 것을 알고 있습니다. 필요에 맞게 커밋을 쉽게 수정할 수 있습니다.
최신 정보:
풀 요청 토론에서 requirejs 작성자는 개정 번호 앞에 접두사로 사용할 수 있다고 제안합니다.
var require = {
baseUrl: "/scripts/buildNumber."
};
나는 이것을 시도하지 않았지만 이것은 다음 URL을 요청한다는 의미입니다.
http://yourserver.com/scripts/buildNumber.myModule.js
접두사를 사용할 수있는 많은 사람들에게 매우 효과적 일 수 있습니다.
가능한 중복 질문은 다음과 같습니다.
require.js-URL의 일부로 필요한 모듈의 버전을 어떻게 설정할 수 있습니까?
require.js data-main의 Expire 캐시에서 영감을 받아 다음과 같은 개미 작업으로 배포 스크립트를 업데이트했습니다.
<target name="deployWebsite">
<untar src="${temp.dir}/website.tar.gz" dest="${website.dir}" compression="gzip" />
<!-- fetch latest buildNumber from build agent -->
<replace file="${website.dir}/js/main.js" token="@Revision@" value="${buildNumber}" />
</target>
main.js의 시작 부분은 다음과 같습니다.
require.config({
baseUrl: '/js',
urlArgs: 'bust=@Revision@',
...
});
생산 중
urlArgs
문제를 일으킬 수 있습니다!
requirejs의 주요 저자는 다음 을 사용하지 않는 것을 선호합니다urlArgs
.
배포 된 자산의 경우 전체 빌드의 버전 또는 해시를 빌드 디렉토리로
baseUrl
설정하고 프로젝트에서 해당 버전이 지정된 디렉토리를로 사용 하도록 구성을 수정하는 것을 선호 합니다baseUrl
. 그러면 다른 파일이 변경 되지 않으며 쿼리 문자열이있는 URL을 캐시하지 않을 수있는 프록시 문제를 피할 수 있습니다.
[스타일링 광산.]
나는이 조언을 따릅니다.
개발 중
자주 변경 될 수있는 파일을 지능적으로 캐시하는 서버를 사용하는 것이 좋습니다. 적절한 경우 304로 내보내고 Last-Modified
응답 하는 서버입니다 If-Modified-Since
. 정적 파일을 제공하기 위해 Node의 Express 세트를 기반으로 한 서버조차도 즉시 사용할 수 있습니다. 브라우저에 아무것도 할 필요가 없으며 중단 점을 망칠 필요가 없습니다.
AskApache 에서이 스 니펫을 가져 와서 로컬 Apache 웹 서버 (내 경우에는 /etc/apache2/others/preventcaching.conf)의 별도 .conf 파일에 넣었습니다.
<FilesMatch "\.(html|htm|js|css)$">
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>
</FilesMatch>
개발을 위해 코드를 변경할 필요없이 정상적으로 작동합니다. 프로덕션에서는 @dvtoever의 접근 방식을 사용할 수 있습니다.
개발을위한 빠른 수정
개발을 위해 Chrome 개발자 도구에서 캐시를 사용 중지 할 수 있습니다 ( 웹 사이트 개발을 위해 Chrome 캐시 사용 안함 ). 캐시 비활성화는 개발 도구 대화 상자가 열려있는 경우에만 발생하므로 정기적으로 탐색 할 때마다이 옵션을 전환 할 염려가 없습니다.
참고 : ' urlArgs '를 사용하면 프로덕션 환경에서 사용자가 최신 코드를 얻을 수있는 올바른 솔루션입니다. 그러나 크롬은 매번 새로 고침 할 때마다 새로 고침 할 때마다 중단 점이 무효화되므로 디버깅이 어려워집니다.
RequireJS 에서 캐시 버스 팅에 ' urlArgs '를 사용하지 않는 것이 좋습니다 . 이렇게해도 문제가 완전히 해결되지는 않습니다. no 버전을 업데이트하면 단일 리소스 만 변경하더라도 모든 리소스를 다운로드하게됩니다.
이 문제를 해결하려면 개정 번호를 만들 때 'filerev'와 같은 Grunt 모듈을 사용하는 것이 좋습니다. 이 외에도 Gruntfile에서 사용자 정의 작업을 작성하여 필요한 곳이없는 개정을 업데이트했습니다.
필요한 경우이 작업에 대한 코드 스 니펫을 공유 할 수 있습니다.
이것이 Django / Flask에서 수행하는 방법입니다 (다른 언어 / VCS 시스템에 쉽게 적용 할 수 있음).
귀하의 config.py
(python3에서 이것을 사용하므로 python2에서 인코딩을 조정해야 할 수도 있습니다)
import subprocess
GIT_HASH = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')
그런 다음 템플릿에서
{% if config.DEBUG %}
require.config({urlArgs: "bust=" + (new Date().getTime())});
{% else %}
require.config({urlArgs: "bust=" + {{ config.GIT_HASH|tojson }}});
{% endif %}
- 수동 빌드 프로세스가 필요하지 않습니다
git rev-parse HEAD
앱이 시작될 때 한 번만 실행 되어config
개체에 저장
urlArgs가없는 동적 솔루션
이 문제에 대한 간단한 해결책이 있으므로 모든 모듈에 대해 고유 한 개정 번호를로드 할 수 있습니다.
원래 requirejs.load 함수를 저장하고 자신의 함수로 덮어 쓰고 수정 된 URL을 원래 requirejs.load로 다시 구문 분석 할 수 있습니다.
var load = requirejs.load;
requirejs.load = function (context, moduleId, url) {
url += "?v=" + oRevision[moduleId];
load(context, moduleId, url);
};
우리의 구축 과정에서 나는 "gulp-rev"를 사용하여 사용중인 모든 모듈의 모든 개정판과 함께 매니페스트 파일을 작성했습니다. 내 gulp 작업의 단순화 된 버전 :
gulp.task('gulp-revision', function() {
var sManifestFileName = 'revision.js';
return gulp.src(aGulpPaths)
.pipe(rev())
.pipe(rev.manifest(sManifestFileName, {
transformer: {
stringify: function(a) {
var oAssetHashes = {};
for(var k in a) {
var key = (k.substr(0, k.length - 3));
var sHash = a[k].substr(a[k].indexOf(".") - 10, 10);
oAssetHashes[key] = sHash;
}
return "define([], function() { return " + JSON.stringify(oAssetHashes) + "; });"
}
}
}))
.pipe(gulp.dest('./'));
});
이렇게하면 main.js에 'oRevision'으로 포함 된 moduleNames의 개정 번호가있는 AMD 모듈이 생성됩니다. 여기에서 앞에서 설명한 것처럼 requirejs.load 함수를 덮어 씁니다.
이것은 @phil mccull의 승인 된 답변에 추가됩니다.
나는 그의 방법을 사용하지만 사전 빌드를 실행할 T4 템플릿을 만들어 프로세스를 자동화합니다.
사전 빌드 명령 :
set textTemplatingPath="%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
if %textTemplatingPath%=="\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe" set textTemplatingPath="%CommonProgramFiles%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
%textTemplatingPath% "$(ProjectDir)CacheBuster.tt"
T4 템플릿 :
require.config.js가로드되기 전에 변수에 저장하십시오.
require.config.js의 참조 :
필자의 경우 클릭 할 때마다 동일한 양식을로드하고 싶었지만 파일에서 변경 한 내용을 유지하고 싶지 않았습니다. 이 게시물과 정확히 관련이 없을 수도 있지만, config를 require로 설정하지 않고 클라이언트 쪽에서 가능한 해결책이 될 수 있습니다. 내용을 직접 보내지 않고 필요한 파일을 복사하여 실제 파일을 그대로 유지할 수 있습니다.
LoadFile(filePath){
const file = require(filePath);
const result = angular.copy(file);
return result;
}
참고 URL : https://stackoverflow.com/questions/8315088/prevent-requirejs-from-caching-required-scripts
'development' 카테고리의 다른 글
Javascript를 사용하여 문자열에서 문자를 제거하려면 어떻게해야합니까? (0) | 2020.03.16 |
---|---|
고해상도로 PDF를 이미지로 변환 (0) | 2020.03.16 |
Java-Foo 유형의 엔 클로징 인스턴스에 액세스 할 수 없음 (0) | 2020.03.16 |
렉서 vs 파서 (0) | 2020.03.16 |
iframe 작업에서 부모 창 리디렉션 (0) | 2020.03.16 |