register_asset를 통해 js 라이브러리 로드

플러그인을 통해 register_asset로 추가된 js 파일들이 eval 함수에 문자열로 전달되는 것을 확인했습니다.

eval의 문제는, 여기에서 논의된 대로 전역 스코프에 객체를 추가하지 않는다는 점입니다. https://stackoverflow.com/questions/4670805/javascript-eval-on-global-scope 이는 js 라이브러리를 사용하려면 필수적인 부분입니다.

구체적으로, 플러그인에서 https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js를 사용하려고 했으나, 함수들이 ember 파일에서 접근할 수 없었습니다.

이 문제의 우회 방법은 webpack으로 파일을 처리하는 것이며, libraryTarget을 umd로 설정하면 됩니다.

많은 라이브러리가 이 방식으로 처리되며, 이는 기본적으로 잘 작동하는 것 같습니다.

저는 이 분야에 전문가가 아니지만, discourse가 등록된 에셋을 전역 스코프에 추가하는 것이 합리적인지 궁금합니다.

참고: 일부 내용이 부끄럽게 들릴 수 있어 죄송합니다. js 라이브러리를 discourse와 함께 작동시키기 위해 webpack을 만져야 한다는 것은 예상치 못했던 일이며, 이것이 이 글을 작성하게 된 동기였습니다. :wink:

여기 뭔가 이상한 것 같습니다. lazyYT 플러그인을 확인해 봤는데, register_asset를 사용하여 에셋을 포함하고 있었지만 eval 블록에 있지 않았습니다.

문제를 재현하는 작은 예제 플러그인을 제공해 주시겠습니까?

이것이 의도치 않은 부작용인지 궁금합니다.

(즉, 이 문제는 개발 환경에서만 발생하는 것일까요?)

저도 그점에 대해 궁금했어요 - 만약 그렇다면 우회 방법은 있지만, 재현 가능한 예시를 원합니다.

물론입니다.

흥미롭네요. 실제로 그런지 확인해 보기 위해 프로덕션 환경에서 플러그인을 실행해 보겠습니다.

@eviltrout
OP에서 언급된 동일한 라이브러리를 사용한 작은 플러그인입니다: GitHub - fzngagan/js-test · GitHub

저는 단순히 이니셜라이저에서 라이브러리가 추가한 함수를 호출해 보았더니, JS 콘솔에서 ReferenceError: RecordRTC is not defined 오류가 발생했습니다.

디버깅에 도움이 될 수 있도록 라이브러리의 미미니파이드(minified)되지 않은 버전을 사용했습니다.

또한, 전체 코드가 eval 함수로 전달되었음을 보여주는 sources 탭의 스크린샷입니다.

또 다른 발견은 discourse-spoiler-alert와 lazy-yt에 포함된 js 파일들이 모두 전역 jQuery 객체에 함수를 주입하지만, 최상위 함수를 선언하지 않는다는 것입니다.

플러그인을 확인해 보니 eval이 개발 모드에서만 존재하는 것을 확인할 수 있었습니다. 프로덕션 환경에서는 전역 스코프에 삽입됩니다. 이상적인 방법은 아니지만, 라이브러리는 일반적으로 모듈 지원(예: UMD) 없이 배포되어서는 안 된다고 생각합니다.

제안하는 방법은 JS를 UMD 지원을 포함하도록 다시 패키징한 후 import하는 것입니다. 다만, 모듈에 대한 JS 경험이 많지 않다면 설정이 다소 까다로울 수 있습니다.

대신, 이 문제를 해결하는 쉬운 방법은 RecordRTC.js를 편집하여 다음 줄을 추가하는 것입니다:

window.RecordRTC = RecordRTC;

전체 내용을 IIFE로 감싸는 것이 더 좋습니다:

(function(exports) {
  // original file contents go here
  exports.RecordRTC = RecordRTC;
})(window);

네, 동의합니다. 많은 라이브러리가 그렇게 배포되고 있으며, 그런 것들은 원활하게 작동합니다. 이 문제를 살펴봐 주시고 확인해 주셔서 감사합니다 :+1: 저는 webpack으로 라이브러리를 패키징하는 방식을 선택했는데, import를 하지 않아도 작동합니다. 하지만 프로덕션 모드에서 테스트를 했어야 했는데 그러지 못했습니다.