함께 배치된 JS 파일을 사용하여 Blazor에서 격리된 JavaScript
이전에 Blazor 및 JS Interop을 사용해 본 적이 있다면 아마도 다양한 구성 요소에 대한 임의의 기능으로 가득 찬 대규모 app.js 파일을 갖게 되었을 것입니다. 작동하지만 빨리 지저분해집니다. 운 좋게도 훨씬 더 깔끔한 접근 방식이 있습니다. 바로 JavaScript 파일을 함께 배치하는 것입니다.
아이디어
CSS 격리와 마찬가지로 Blazor를 사용하면 구성 요소 옆에 .razor.js 파일을 배치할 수 있습니다. JavaScript 모듈은 구성 요소에 실제로 필요한 경우에만 요청 시 로드됩니다. 전역 스크립트도 없고 오염도 없습니다.
설정하기
텍스트를 클립보드에 복사하는 Clipboard.razor 구성 요소가 있다고 가정해 보겠습니다. 바로 옆에 Clipboard.razor.js라는 파일을 만듭니다.
export function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
console.log("Copied to clipboard!");
});
}
export 키워드에 주목하세요. 이는 중요합니다. Blazor는 이를 표준 ES 모듈로 로드합니다.
Blazor에 모듈 로드
구성 요소에서 IJSRuntime를 사용하여 모듈을 가져옵니다. 경로는 라이브러리의 경우 ./_content/{ASSEMBLY_NAME}/{COMPONENT_PATH}.razor.js 또는 현재 프로젝트의 상대 경로라는 규칙을 따릅니다.
@inject IJSRuntime JS
@implements IAsyncDisposable
<button @onclick="Copy">Copy to clipboard</button>
@code {
[Parameter]
public string Text { get; set; }
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>(
"import", "./Components/Clipboard.razor.js");
}
}
private async Task Copy()
{
if (module is not null)
{
await module.InvokeVoidAsync("copyToClipboard", Text);
}
}
public async ValueTask DisposeAsync()
{
if (module is not null)
{
await module.DisposeAsync();
}
}
}
여기서 주목해야 할 몇 가지 사항은 다음과 같습니다.
- 서버 측 사전 렌더링 중에는 JS Interop을 사용할 수 없기 때문에
OnAfterRenderAsync에 모듈을 로드합니다. IJSObjectReference을 사용하여 모듈에 대한 참조를 유지합니다.- 구성요소가 파괴될 때 모듈을 정리하기 위해
IAsyncDisposable를 구현합니다.
이게 더 나은 이유
이전에는 모든 것을 단일 wwwroot/js/app.js에 덤프했습니다. 작동했지만 기능을 찾는 것이 어려웠고 모든 페이지에 필요하지 않은 JavaScript가 로드되었습니다. 함께 배치된 JS 파일 사용:
- 각 구성 요소는 자체 JavaScript를 소유합니다.
- 모듈은 필요할 때만 느리게 로드됩니다.
- 전역 함수 이름이 충돌하지 않습니다.
- 유지 관리 및 삭제가 더 쉽습니다. 구성 요소를 삭제하면 해당 구성 요소와 함께 JS도 삭제됩니다.
경로 문제
import에 전달하는 경로는 독립 실행형 Blazor 앱에 있는지 아니면 Razor 클래스 라이브러리에 있는지에 따라 달라집니다. 일반 Blazor 앱의 경우 경로는 wwwroot에 상대적입니다. .razor.js 파일은 빌드 시 복사되므로 프로젝트의 구성 요소 위치에서 참조할 수 있습니다.
모듈을 로드할 때 404가 표시되면 경로를 다시 확인하고 파일이 .js가 아닌 .razor.js로 끝나는지 확인하세요.
게시물이 마음에 드셨기를 바랍니다! @emimontesdeoca로 소셜 미디어를 통해 언제든지 저에게 연락해주세요.