# 페이지별 커스텀 JS를 설정하는 'on-discourse' JavaScript에 대한 피드백을 구합니다.

**URL:** https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647
**Category:** Development
**Created:** [11월 16, 2023, 3:48오전 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647 "2023-11-16T03:48:54Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 16, 2023, 3:48오전 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/1 "2023-11-16T03:48:55Z")

</div>

페이지마다 설치되어야 하는 Svelte 앱을 개발하고 있습니다. JS 파일을 head 섹션에 추가하고 첫 번째 페이지 로드 시 로드되도록 하는 방법을 알아냈습니다. 하지만 실험을 해보면서 discourse가 XHR를 통해 새로운 콘텐츠를 가져와 특정 섹션을 교체한다는 사실을 깨달았고, 이로 인해 새 페이지가 로드될 때 제 앱이 다시 초기화되지 않는 문제가 발생했습니다.

페이지가 변경될 때 알림을 받기 위해 여러 가지 시도를 해보았지만, Ember가 이러한 훅을 제공하지 않는 것으로 보이며, 경청할 수 있는 커스텀 이벤트도 찾을 수 없었습니다.

한 가지 방법은 DOM에 mutation observer를 추가하여 변경 사항을 관찰하는 것입니다. "#topic div가 다시 로드되는(속성이 변경되므로 속성 변경만 관찰하면 됩니다) 요소인 것을 발견했습니다. 저는 그곳에 mutation observer를 설정했습니다(mutation observer는 DOM 변경 사항을 관찰하는 비교적 새로운 방식으로, 성능이 좋습니다). 작동 원리는 변경 사항을 관찰하고, 변경이 발생하면 해당 페이지의 Svelte 앱을 다시 로드하기 위해 콜백을 실행하는 것입니다.

이 접근 방식을 마음에 들어 하고, 피드백을 받고 싶습니다.

한 가지 질문: 대신 URL 변경 사항을 관찰해야 하나요? popstate에 대한 리스너를 등록하는 것이 더 나은 아이디어일까요?

사용하려면 테마의 head에서 다음과 같이 하세요:

```plaintext
<script src="https://files.extrastatic.dev/community/on-discourse.js"></script>
<script src="https://files.extrastatic.dev/community/index.js"></script>
<link rel="stylesheet" type="text/css" href="https://files.extrastatic.dev/community/index.css" ></link>

```

그런 다음 라이브러리 내부에서 on-discourse를 다음과 같이 호출할 수 있습니다:

```plaintext
function log(...msg) {
  console.log('svelte', ...msg);
}

// This is the Svelte install code
function setup() {
  try {
    const ID = 'my-special-target-id';
    log('Inside setup()');
    const el = document.getElementById(ID);
    if (el) {
      log('Removed existing element', ID);
      el.remove();
    }
    const target = document.createElement("div");
    target.setAttribute("id", ID);
    log('Created target');
    document.body.appendChild(target);
    log('Appended child to body');
    const app = new App({
      // eslint-disable-next-line no-undef
      target
    });
    log('Created app and installed');
  } catch(err) {
    console.error('Unable to complete setup()', err.toString() );
  }
}

(function start() {
  log('Starting custom Svelte app');
  // Re-install on changes
  window.onDiscourse && window.onDiscourse( setup );
  // Load the app the first page load
  window.addEventListener('load', () => {
    setup();
  });
  log('Finished custom Svelte app);  
})();

```

기본적으로 콜백(여러 번 실행하여 여러 콜백을 설치할 수 있음)과 함께 `window.onDiscourse(callback)`를 호출하기만 하면 되고, 변경 사항이 발생하면 해당 콜백이 실행되어 앱을 초기화합니다.

다음은 on-discourse.js의 전체 코드입니다. (수정: #topic를 사용하도록 업데이트했는데, 페이지 로드 시 속성이 변경되므로 관찰하기에 좋은 대상인 것 같습니다. 그러면 mutation은 #main-outlet의 DOM 트리 전체를 살펴보는 대신 속성 변경 사항만 관찰하면 됩니다.)

```plaintext
let mutationObservers = [];

function log(...msg) {
  console.log("on-discourse", ...msg);
}

function observeMainOutlet() {
  log('Observing main outlet');
  // Select the node that will be observed for mutations
  const targetNode = document.getElementById("topic");
 
  if (targetNode) {
    // Options for the observer (which mutations to observe)
    const config = { attributes: true };
    
   // create an observer instance to reset when childList changes
    const observer = new MutationObserver(function(mutations) {
      let reset = false;
      mutations.forEach(function(mutation) {
	if (mutation.type === 'attributes') {
	  log('Found main-outlet mutation, running callbacks');
	    mutationObservers.forEach( (s,i) => {
		try {
		    log(`Running div callback ${i+1}`);	    
		    s();
		    log(`Finished div callback ${i+1}`);	    
		} catch( err ) {
		    log(`Div callback error (${i+1})`, err );	    	      
		}
	 });
       }
      });
    });
    
    // Start observing the target node for configured mutations
    observer.observe(targetNode, config);
    
    // Later, you can stop observing
    // observer.disconnect();
    log('Done with outlet observer');
  } else {
    console.error('on-discourse FATAL ERROR: Unable to find main-outlet');
  }
}

window.addDiscourseDivMutationObserver = (cb) => {
    log('Adding on-discourse div mutation callback');  
    mutationObservers.push(cb);
    log('Added on-discourse div mutation callback');    
}

window.addEventListener("load", () => {
    log('Setting up topic observer');
    if (mutationObservers.length > 0) {
	observeMainOutlet();
    }
    log('Created topic observer');  
});

log('Completed setup of on-discourse.js');

```

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [11월 16, 2023, 10:56오전 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/2 "2023-11-16T10:56:18Z")

</div>

코드를 head에 넣는 대신 초기화 파일(initializer)에 넣으려는 것 같습니다. 개발자 가이드를 참고하여 JS를 별도의 파일로 분리하는 방법을 확인해 보세요.

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 16, 2023, 1:15오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/3 "2023-11-16T13:15:20Z")

</div>

답변 주셔서 정말 감사합니다!

이것이 제가 혼란을 느끼는 이유 중 하나인 것 같습니다. Discourse를 확장하기 위해 제 own JS를 추가하는 방법에 대한 참고 자료를 찾기가 어렵습니다.

"Discourse developer guide"를 DuckDuckGo로 검색하면 나오는 첫 번째 링크는 GitHub 저장소로 가는 링크입니다.

그다음 링크는 "Discourse Advanced Developer Install Guide"입니다. 이 가이드는 개발을 위해 Rails를 설정하는 방법을 알려주지만, AFAICT(제가 아는 한) 커스텀 JS를 설치하는 방법에 대한 링크는 없습니다. Rails 시절에 기억하는 것처럼 복잡한 빌드 프로세스를 피하고 싶습니다. 저는 이 JS 확장 코드를 독립적으로 개발한 후, 제 사이트에 스크립트 태그를 넣는 방식을 정말로 원합니다. 따라서 로컬에 Rails 환경을 설정해서 빌드해야 하는 상황은 정말로 피하고 싶습니다. 아마도 그 방식의 유용함을 제가 놓치고 있는 걸까요? 하지만 저는 테마와 몇 개의 \<script\> 태그를 사용하는 도커 컨테이너를 업데이트하는 방식이 정말 좋습니다.

그다음 링크는 "Beginner’s guide to developing Discourse Themes"인데, 이는 테마 개발에 관한 것으로 제가 필요한 것이 맞을까요?

Discourse API에 대한 링크도 보이는데, 당연히 제가 원하는 것이 아닙니다.

"discourse javascript initializer"를 검색하면 5년 전의 이 링크를 볼 수 있습니다: [Execute JavaScript code from a plugin once after load](https://meta.discourse.org/t/execute-javascript-code-from-a-plugin-once-after-load/85580) 하지만, 이것은 Rails에 플러그인을 꽂는 것처럼 보이고, 더 간단한 방법이 있을 것 같으며, 이 스레드도 해결되지 않은 것처럼 보입니다.

"discourse javascript initializer"에 대한 또 다른 링크는 제가 JS를 설치하는 방식을 제안하지만, 페이지 콘텐츠가 변경될 때마다(전체 페이지 새로고침 또는 XHR “turbolinks” 유사 요청을 통해) 어떻게 처리할지에 대한 제안은 없습니다: [https://stackoverflow.com/questions/48611621/how-do-i-add-an-external-javascript-file-into-discourse](https://stackoverflow.com/questions/48611621/how-do-i-add-an-external-javascript-file-into-discourse)

이 토론을 살펴봐야 하나요? [A versioned API for client side plugins](https://meta.discourse.org/t/a-versioned-api-for-client-side-plugins/40051)

아니면, 이것이 될까요? 첫눈에 문법을 이해하지 못하겠습니다(그 주석들은 JS처럼 보이지 않고, Rails 관례인가요?) 그래서 이것이 제가 필요한 것인지 확신이 서지 않습니다: [Using Plugin Outlet Connectors from a Theme or Plugin](https://meta.discourse.org/t/using-plugin-outlet-connectors-from-a-theme-or-plugin/32727)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11월 16, 2023, 1:36오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/4 "2023-11-16T13:36:38Z")

</div>

네, 모든 것이 자명한 것은 아닙니다.

Discourse는 EmberJS 애플리케이션입니다.

이상적으로는 JavaScript 확장을 Theme Component(또는 Plugin), 적절한 경우 Discourse JavaScript API, 그리고 플러그인 아웃렛을 사용하여 EmberJS 프레임워크 안에서 작성해야 합니다.

임의의 외부 스크립트를 사용할 때 마주칠 주요 문제는 스크립트가 올바른 시점에 실행되도록 하는 것입니다.

이를 보장하려면 컴포넌트의 동작(삽입 또는 업데이트 시 실행되도록 구성 가능)에 스크립트를 연결해야 합니다.

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 16, 2023, 1:38오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/5 "2023-11-16T13:38:06Z")

</div>

좋은 확인입니다. 하지만 솔직히 말씀드리면, 제 mutation observer 코드가 정말 마음에 듭니다. 페이지 내용이 변경되면 정확히 감지하고, 그 후 제 커스텀 JS 코드를 실행할 수 있게 해줍니다. 아주 잘 작동하고 있고, Ember를 배우거나 RoR 앱을 어떤 방식으로든 수정할 필요가 없었습니다. 당분간 이 솔루션에 정말 만족합니다. 모든 댓글에 감사드립니다.

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 16, 2023, 1:45오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/6 "2023-11-16T13:45:42Z")

</div>

방금 popstate 이벤트 관찰자를 사용해 봤습니다. 만약 그것이 작동했다면, 코드는 20줄 대신 5줄로 줄었을 것입니다. 그러나 여기저기를 클릭해도 해당 이벤트가 트리거되지 않는 것 같습니다. 앞으로/뒤로 버튼을 사용하면 이벤트를 확인할 수 있습니다. popstate에 대해 충분히 이해하고 있다고는 할 수 없지만, 당분간은 div 변형 관찰자를 사용하겠습니다.

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 18, 2023, 4:04오전 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/7 "2023-11-18T04:04:14Z")

</div>

여기서 제가 한 가지 어리석은 짓을 하고 있다는 것을 깨달았습니다. 테마를 수정하고 head 부분에 코드를 추가하고 있었거든요. 다른 테마로 전환하면 그 변경 사항이 사라집니다. 올바른 방법은 플러그인을 사용하여 코드를 추가하는 것입니다. 저는 여기 템플릿을 사용했습니다: [GitHub - discourse/discourse-plugin-skeleton: Template for Discourse plugins · GitHub](https://github.com/discourse/discourse-plugin-skeleton/). 그런 다음 다음과 같은 JavaScript 코드를 추가했습니다:

```plaintext
export default {
  name: 'alert',
    initialize() {
        const scripts = [
            'https://files.extrastatic.dev/community/on-discourse.js',
            'https://files.extrastatic.dev/community/index.js'
        ];
        scripts.forEach( s => {
            const script = document.createElement('script');
            script.setAttribute('src', s);
            document.head.appendChild(script);
        });

        const link = document.createElement('link');
        link.setAttribute('rel', "stylesheet");
        link.setAttribute("type", "text/css");
        link.setAttribute("href", "https://files.extrastatic.dev/community/index.css");
        document.head.appendChild(link);
    }
};

```

그 다음 `./launcher rebuild app`을 실행하고 플러그인을 활성화했습니다.

마지막으로, 해당 스크립트를 로드할 수 있도록 설정에 CSP 정책을 추가해야 했습니다. admin-\>settings-\>security로 이동하여 files.extrastatic.dev를 "content security policy script src"에 추가하고 apply를 클릭했습니다.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11월 18, 2023, 7:45오전 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/8 "2023-11-18T07:45:50Z")

</div>

> [@Chris\_Dawson](#):
>
> 정확한 방법은 플러그인을 사용하여 코드를 추가하는 것입니다.

그렇지 않습니다.

API를 수정하지 않는 경우(예: 100% JavaScript 사용)에는 배포와 교체에 더 번거로운 플러그인을 사용할 필요가 없습니다.

JavaScript를 수정하거나 추가하는 것이라면 테마 컴포넌트만으로도 충분합니다.

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 18, 2023, 1:45오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/9 "2023-11-18T13:45:52Z")

</div>

알겠습니다. 그런데 테마를 전환할 때(또는 사용자가 원하는 테마를 직접 선택할 수 있도록 할 때), 각 테마가 1) 새로운 head 태그를 추가할 수 있도록 편집 가능해야 하고, 더 나쁜 것은 2) 모든 테마에 걸쳐 제 코드를 유지 관리해야 한다는 문제에 직면하지 않을까요?

다른 테마를 사용하기 시작했을 때, 일부 테마는 테마를 편집하려면 GitHub 저장소를 수정해야 한다고 표시됩니다. 이는 매우 번거롭고 비유연해 보입니다. 하지만 각 테마에 걸쳐 스크립트 태그를 유지 관리하는 것은 오타가 생기기 쉬울 뿐만 아니라 더 큰 문제입니다.

제가 놓치고 있는 것이 있을까요? 테마만 사용하여 이 문제들을 해결할 방법이 있을까요?

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11월 18, 2023, 1:47오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/10 "2023-11-18T13:47:22Z")

</div>

이 경우 이를 Theme Component로 만들어 모든 Theme에 해당 Component를 추가하면 됩니다. (이 방식이 추가적인 복잡성을 초래한다는 점은 인정합니다.)

사이트를 전문적으로 운영하려면 모든 코드를 GitHub에 올려두는 것이 매우 좋은 아이디어입니다.

그러나 처음에 아이디어를 시험해 보는 단계라면, 원하시는 대로 로컬 환경에서 자유롭게 실험해 볼 수 있습니다.

코드 변경 사항이 안정화되면 소스 컨트롤에 저장하는 것이 좋지만, 저는 가능하면 빠를수록 좋다고 생각합니다.

GitHub와 결합하여 빠른 이터를 가능하게 하는 방법 중 하나는 다음과 같은 방식을 함께 사용하는 것입니다:

> [@Install the Discourse Theme CLI console app to help you build themes](https://meta.discourse.org/t/install-the-discourse-theme-cli-console-app-to-help-you-build-themes/82950):
>
> The [[discourse] Discourse Theme CLI](https://github.com/discourse/discourse_theme) is a ruby gem that allows you to use your editor of choice when developing Discourse themes and theme components. As you save files the CLI will update the remote theme or component and changes to it will appear live! Installing To play with it, make sure you have Ruby 2.5 or up installed. If you are on Windows, you have 2 options: Option 1: [Windows Subsystem for Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux). Windows 10 has access to a full Linux environment, you can use it to install …

이 방식은 Test Theme의 Test Theme Component에 배포할 수 있게 해줍니다 … 하지만 여기서부터는 꽤 복잡한 영역에 들어갑니다 …

이 방법을 사용하면 즉시 배포할 수 있으며, 결과에 만족하면 변경 사항을 git 저장소에 안전하게 저장할 수 있습니다.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [11월 18, 2023, 1:52오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/11 "2023-11-18T13:52:09Z")

</div>

[https://github.com/discourse/discourse-theme-skeleton을](https://github.com/discourse/discourse-theme-skeleton%EC%9D%84) 확인해 보세요.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [11월 18, 2023, 1:56오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/12 "2023-11-18T13:56:27Z")

</div>

> [@Chris\_Dawson](#):
>
> 페이지가 변경될 때 알림을 받기 위해 여러 가지 시도를 해 보았지만, Ember가 필요한 훅을 제공하는 것 같지 않고, 경청할 수 있는 커스텀 이벤트도 찾지 못했습니다.

여기에 필요한 링크입니다: [How do you force a script to refire on every page load in Discourse? - #5 by simon](https://meta.discourse.org/t/how-do-you-force-a-script-to-refire-on-every-page-load-in-discourse/74856/5)

```plaintext
<script type="text/discourse-plugin" version="0.8">
    api.onPageChange(() =>{
        // code
    });
</script>
```

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 18, 2023, 5:17오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/13 "2023-11-18T17:17:38Z")

</div>

와, @RGJ 정말 완벽해 보여요! 감사합니다!

---

<div class="post-metadata">

### Author: ![Chris\_Dawson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chris_dawson/32/184486_2.png) [@Chris\_Dawson](https://meta.discourse.org/u/Chris_Dawson)
#### Post date: [11월 19, 2023, 1:48오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/14 "2023-11-19T13:48:47Z")

</div>

안녕하세요 @RGJ. 이 방법을 어떻게 적용해야 할지 알아보고자 노력해 왔는데, 솔직히 좀 혼란스럽습니다. 플러그인 API가 몇 년간 조금씩 변경된 것 같고, 현재 최신 버전이 무엇인지, 또는 예제를 어디서 볼 수 있는지 확신이 서지 않습니다.

제시하신 코드는 스크립트 태그로 감싸져 있어 어딘가의 HTML 페이지에 삽입되는 것처럼 보입니다. 저는 다음과 같은 코드를 사용하고 있었는데, 이는 JS 파일 자체입니다.

[https://extrastatic.dev/publicdo/publicdo-discourse-plugin/-/blob/main/assets/javascripts/discourse/initializers/kanji.js?ref\_type=heads](https://extrastatic.dev/publicdo/publicdo-discourse-plugin/-/blob/main/assets/javascripts/discourse/initializers/kanji.js?ref_type=heads)

제 플러그인을 수정하여 제공해 주신 코드를 사용하려면 어떻게 해야 하나요? 제안해 주신 이 코드는 플러그인에 들어가는 건가요, 테마에 넣어야 하나요, 아니면 다른 방식으로 페이지에 추가해야 하나요?

다음과 같은 코드를 사용해 보았지만:

```plaintext
export default {
  name: 'publicdo',
    initialize() {
     withPluginApi('0.1', api => {
                api.onPageChange(() => {
                   console.log('Run my code here.');
                });
      });
    }
}

```

`Uncaught (in promise) ReferenceError: withPluginApi is not defined` 오류가 발생했습니다. 따라서 이는 일반적으로 로드되는 JS가 수신하는 것이 아님을 분명히 알 수 있습니다.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [11월 19, 2023, 2:26오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/15 "2023-11-19T14:26:45Z")

</div>

아래를 단순히

`import { withPluginApi } from "discourse/lib/plugin-api";`

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [11월 19, 2023, 6:29오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/16 "2023-11-19T18:29:33Z")

</div>

정말 #Customization > Theme component 에 링크된 소스들을 살펴보는 것이 좋습니다 (이 생태계는 거의 전부 오픈소스입니다 - 마음껏 활용해 보세요!).

Imports가 자주 필요하고 일반적이며(`api.onPageChange`와 같은 유용한 api 함수 사용도 마찬가지)라는 점을 알게 될 것입니다.

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [12월 19, 2023, 6:30오후 UTC](https://meta.discourse.org/t/feedback-on-on-discourse-javascript-for-setting-up-custom-js-for-each-page/285647/17 "2023-12-19T18:30:28Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
