javascripts/discourse/initializers/persistent-banner.gjs 파일에서 특정 플러그인 아웃렛에 템플릿을 삽입하려고 합니다.
코드:
import Component from "@glimmer/component";
import { apiInitializer } from "discourse/lib/api";
banner_plugin_outlet = settings.banner_position
export default apiInitializer("1.14.0", (api) => {
try {
banner_plugin_outlet = settings.banner_position
api.renderInOutlet(
banner_plugin_outlet,
class persistentbanner extends Component {
get bannerIsFilled() {
if (settings.banner_text_content == "") {
return false;
} else if (settings.banner_visible == "hide") {
return false;
} else {
return true;
}
}
<template>
{{#if this.bannerIsFilled}}
<div class='persistent-banner'>
<p>
{{html_safe (theme-setting 'banner_text_content')}}
</p>
</div>
{{/if}}
</template>
}
);
} catch (e) {
console.log(e);
}
}
하지만 <template> 태그 안의 HTML이 아웃렛 위치에 표시되지 않습니다. 실제로는 어디에도 표시되지 않습니다. 어디서 잘못되고 있을까요?
리포지토리 링크: GitHub - NateDhaliwal/discourse-persistent-banner: A theme component for Discourse that cannot be closed by the user. · GitHub
초기화자를 사용하지 마세요. connectors 폴더를 사용하세요. 예제가 많이 있습니다.
그 이유는 선택할 수 있는 다양한 아웃렛이 있기 때문입니다.
이 코드는 Notification Banner 저장소에서 가져와서 수정했습니다.
아, 알겠습니다. 네, 말이 되네요. 혹시 기능적인 의도인지는 확신이 없어서요. 코드를 더 자세히 읽어야 했는데 죄송합니다.
다시 시작할 수 있도록 몇 가지 팁을 드릴게요:
- 이 파일의
apiInitializer 호출 끝부분에 닫는 괄호가 하나 빠져 있습니다. 이대로는 동작하지 않습니다.
해당 문제를 수정하면 더 많은 오류가 보입니다.
-
banner_plugin_outlet이 선언되지 않았습니다. 여기에는 const가 필요합니다.
두 번 할당하고 있네요? 두 번은 필요 없을 것 같습니다 
banner_plugin_outlet = settings.banner_position
export default apiInitializer("1.14.0", (api) => {
try {
banner_plugin_outlet = settings.banner_position
-
임포트(import)가 누락되어 있습니다:
import { htmlSafe } from "@ember/template";
import themeSetting from "discourse/helpers/theme-setting";
-
… 하지만 여기에서 themeSetting을 헬퍼로 사용하려고 해도 동작하지 않았습니다. 오류는 뜨지 않고 단순히 화면이 비어 보였기 때문에, 대신 아래 코드를 사용해 보세요:
get bannerTextContent() {
return settings.banner_text_content;
}
<template>
{{#if this.bannerIsFilled}}
<div class='persistent-banner'>
<p>
{{htmlSafe this.bannerTextContent}}
-
항상 콘솔에서 오류를 확인하세요.
htmlSafe를 가져왔고, 정말 잘 작동했습니다!
정말 감사합니다!
david
(David Taylor)
8
네, 헬퍼는 gjs에서 작동하지 않습니다(그리고 필요도 없죠). getter를 정의하는 것은 괜찮습니다. 하지만 그렇게 하고 싶지 않다면 템플릿에서 settings "글로벌"에 직접 참조할 수 있습니다:
<template>
{{htmlSafe settings.banner_text_content}}
</template>
고마워요. 그게 별로 투명하지 않아 보이던데요! 
david
(David Taylor)
10
네, 그건 맞는 말이에요. 에러 메시지를 개선해 보겠습니다:
감사합니다. 개발자 경험에 정말 큰 도움이 됩니다.
알다시피, 위젯에 비해 .gjs를 사용하면서 개발자 경험이 극적으로 개선되었습니다.
하지만
gjs 컴포넌트를 사용할 때 매우 기이한 에러가 많이 발생하며, 이로 인해 문제를 찾기 쉽지 않습니다.
예를 들어, 헬퍼 이름을 잘못 입력해 보겠습니다:
{{html_safe this.bannerTextContent}}
그러면 다음과 같은 전형적인 에러가 발생합니다:
program.js:100 Uncaught (in promise) TypeError: Invalid value used as weak map key at WeakMap.set (<anonymous>)
(이름이 유효하더라도 import를 잊으면 여기에서도 같은 문제가 발생합니다)
뭐라고요?!
이런 사례가 정말 많습니다.
이것이 프레임워크를 사용하는 단점이라고 봐야 하나요?
david
(David Taylor)
12
아, 꽤 심각한 문제네요!
로컬에서 테스트해 보니 다음과 같은 내용이 표시됩니다:
WeakMap 오류를 어디서 확인하셨나요? 프로덕션 사이트에서 보셨다면… 아마도 성능 향상을 위해 프로덕션 빌드에서 최적화되어 제거되는 체크 중 하나일 수 있습니다.
가능하시다면 테마/플러그인을 개발할 때 반드시 적절한 개발 환경을 사용하시는 것을 권장합니다. 이 경우처럼 개발 환경에서는 더 나은 경험을 제공하는 경우가 많기 때문입니다.
네, 프로덕션 사이트에서 Theme CLI (를 사용하고 있는데, 이는 다른 면에서는 훌륭한 워크플로우이지만 아마도 단점 중 하나인 것 같습니다?
완전히 이해가 됩니다.
네, 플러그인이라면 제 1순위 선택지이지만, TC(테마 컴포넌트)의 경우 피드백의 즉각성 때문에(항상 유용하진 않지만!) 프로덕션 사이트에서 개발하려는 유혹이 큽니다.
하지만 방금 깨달은 것은, CLI로 로컬호스트를 입력하면 작동한다는 것입니다.
그러니까 그거였군요!

앞으로 그렇게 사용하겠습니다! 
왜 그게 불가능하다고 생각했는지 저도 모르겠습니다

항상 도움 주셔서 감사합니다. 덕분에 (앞으로) 많은 시간을 절약할 수 있을 것 같습니다 
david
(David Taylor)
14
맞아요! 테마 CLI를 사용하는 로컬호스트 환경에서 작업하는 방식을 선호하며, 다른 사람들에게도 추천합니다. 이러한 권장 워크플로를 문서화하는 부분에서는 확실히 더 나아질 수 있을 거예요 
또 다른 팁은 discourse.theme-creator.io가 개발 모드 Ember 에셋으로 실행된다는 점입니다. 따라서 더 자세한 오류 메시지도 확인할 수 있을 거예요.