Next.js의 router-loader.ts #prefetchViaDom()

function prefetchViaDom(
  href: string,
  as: string,
  link?: HTMLLinkElement
): Promise<any> {
  return new Promise<void>((resolve, reject) => {
    const selector = `
      link[rel="prefetch"][href^="${href}"],
      link[rel="preload"][href^="${href}"],
      script[src^="${href}"]`
    if (document.querySelector(selector)) {
      return resolve()
    }

    link = document.createElement('link')

    // The order of property assignment here is intentional:
    if (as) link!.as = as
    link!.rel = `prefetch`
    link!.crossOrigin = process.env.__NEXT_CROSS_ORIGIN!
    link!.onload = resolve as any
    link!.onerror = () =>
      reject(markAssetError(new Error(`Failed to prefetch: ${href}`)))

    // `href` should always be last:
    link!.href = href

    document.head.appendChild(link)
  })
}

이 함수는 미리 가져오는(prefetch) 역할을 하며 주요 특징은 다음과 같다.

  • 이미 prefetch 또는 preload된 리소스인지 확인.
  • 새로운 요소를 생성하여 리소스를 prefetch.
  • 로드 성공 또는 실패 시 적절한 처리.

Webpack의 Mini CSS Extract Plugin에서 CSS 청크 로드 실패 시 에러 처리 코드를 볼 수 있다.

 Template.indent([
  "var errorType = event && event.type;",
  "var realHref = event && event.target && event.target.href || fullhref;",
  'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + errorType + ": " + realHref + ")");',
  'err.name = "ChunkLoadError";',
  // TODO remove `code` in the future major release to align with webpack
  'err.code = "CSS_CHUNK_LOAD_FAILED";',
  "err.type = errorType;",
  "err.request = realHref;",
  "if (linkTag.parentNode) linkTag.parentNode.removeChild(linkTag)",
  "reject(err);",
]),

이 코드는 CSS 청크 로드 실패 시 발생하는 에러를 처리하며 주요 특징은 다음과 같다.

  1. 에러 타입과 실제 URL을 파악.
  2. 상세한 에러 메시지를 생성.
  3. 에러 객체에 추가 정보(name, code, type, request)를 설정.
  4. 실패한 <link> 태그를 DOM에서 제거.
  5. Promisereject하여 에러를 전파.

이 플러그인은 CSS를 별도의 파일로 추출하는 데 사용되며, 위 코드는 그 과정에서 발생할 수 있는 오류를 처리하는 중요한 부분.

#306

Google Sheets API를 활용하기 위해서는 Google Cloud Platform(GCP)에서 필요한 설정을 하고, google-spreadsheet 라이브러리를 통해 스프레드시트를 조작할 수 있습니다. 다음은 이를 위한 단계별 가이드입니다.

  1. 서비스 계정 설정
  2. Google Cloud 프로젝트 생성
  3. Google Sheets API 활성화
  4. API 자격 증명 생성
  5. 서비스 계정 생성
  6. 서비스 계정 키 생성
  7. 환경 변수 설정

#305

chrono는 다양한 형식의 날짜/시간을 처리하고 주어진 텍스트에서 정보를 추출할 수 있도록 설계된 자연어 날짜 파서.

  • “Today”, “Tomorrow”, “Yesterday”, “Last Friday” 등의 상대적 날짜 처리
  • “17 August 2013 - 19 August 2013”와 같은 날짜 범위 처리
  • “This Friday from 13:00 - 16.00”와 같은 시간 포함 날짜 처리
  • “5 days ago”, “2 weeks from now”와 같은 상대적 시간 표현 처리
  • “Sat Aug 17 2013 18:40:39 GMT+0900 (JST)“와 같은 표준 날짜 형식 처리
  • “2014-11-30T08:15:30-05:30”와 같은 ISO 8601 형식 처리

parse()123

parse(text: string, referenceDate?: ParsingReference | Date, option?: ParsingOption): ParsedResult[] {
  // 1. 파싱 컨텍스트 생성
  // 2. 모든 파서를 실행하고 결과 수집
  // 3. 결과를 인덱스 기준으로 정렬
  // 4. 모든 리파이너를 적용하여 결과 개선
  // 5. 최종 결과 반환
}

inclusive-dates는 자연어 입력을 지원하는 사용자 친화적이고 완전히 접근 가능한 데이트피커. 내부적으로 chrono를 사용하여 자연어 날짜 입력을 처리. 이는 두 라이브러리의 장점을 결합한 좋은 예시.

const parsedDate = await chronoParseDate(text, {
  locale: this.locale.slice(0, 2),
  minDate: this.minDate,
  maxDate: this.minDate,
  referenceDate: removeTimezoneOffset(new Date(this.referenceDate)),
  ...chronoOptions,
})
  1. chrono의 강력한 자연어 날짜 파싱 능력을 활용.
  2. inclusive-dates는 이를 사용자 친화적이고 접근성 높은 UI 컴포넌트로 구현.

이러한 조합을 통해, 개발자들은 사용자에게 직관적이고 유연한 날짜 입력 방식을 제공하면서도 접근성과 사용성을 높일 수 있음.


Footnotes

  1. executeParser

  2. sort

  3. refine

#304

grid view(또는 datagrid)는 데이터의 표 형식 보기를 제공하는 그래픽 제어 요소입니다.

일반적으로 다음 중 일부 또는 전부를 지원합니다.

  • 열 머리글을 클릭하여 그리드의 정렬 순서 변경
  • 열 머리글을 끌어서 크기 및 순서 변경
  • 보기 데이터의 제자리 편집
  • 행과 열 구분 기호 및 행 배경색 번갈아 지정하기

  • Cornerstone.js HTML5 canvas를 지원하는 웹 브라우저에서 가벼운 의료 이미지 표시에 사용되는 JavaScript 라이브러리
  • OpenSeadragon 데스크톱 및 모바일에서 사용 가능한 고해상도 줌 가능한 이미지를 위한 순수 JavaScript 뷰어
  • dicomParser DICOM 파일을 처리하여 의료 이미지 데이터를 JavaScript 객체로 변환하는 라이브러리
  • AMI Medical Imaging (AMI) 웹에서 의료 영상을 효과적으로 표시하고 주석을 추가하는 데 사용되는 JavaScript 라이브러리
  • OHIF Medical Imaging Viewer
  • itk-wasm 의료 영상 처리를 위한 JavaScript 라이브러리
  • Brainchop

예전에 관련 회사 기술 블로그 보다가 생각나서 찾아본 라이브러리 리스트. 대용량, 의학용 이미지 포멧을 다루기 위한 도구들.

Astro를 사용한 프로젝트에서 빌드를 하는데 JavaScript heap out of memory 에러가 발생했다. 쉽게 해결하자면 NODE_OPTIONS=--max_old_space_size(in megabytes) 설정해서 우회할수는 있겠지만 정리가 필요해서 메모를 남겨본다. 일단 원인은 파일사이즈가 크다는 점, 그리고 카테고리(국가)별 데이터가 많다는 점인데 개선할만한 부분은 두가지 정도인 듯.

  • 가능한 전처리해서 데이터를 다시 생성해서 참조
  • Astro.glob을 사용해서 조건부로 데이터를 가져오기

예상치 못한 에러였는데 역시 트레이드오프는 존재하기 마련이다.


#301

로컬에서만 실행 해야하는 프로젝트가 있길래 아무래도 사전설정 같은 귀찮은 문제가 있으니 pkg를 사용하면 좋을 것 같아서 들어가봤는데 개발이 중단 되었다.

노드 21버젼에서 해당 기능이 지원되는데 재미있는 시도들이 많이 나왔으면 좋겠다.


#300
[data-scope='slider'][data-part='thumb']

[data-scope='slider'][data-part='track']

[data-scope='slider'][data-part='control']

Ark UI의 각 컴포넌트 파트는 data-scopedata-part 속성으로 지정됩니다. data-scope 속성은 컴포넌트를 식별하고, data-part 속성은 컴포넌트의 개별 부분을 지정합니다.

ark-ui에서 사용하는 방식인데 적용해볼만한 컨셉이라고 생각한다.


#297

as로 간단하게 처리가 가능할정도의 복잡도라면 괜찮다고 보는데 더 복잡하게 된다면 asChild가 최선의 방법.

function Button({ asChild, ...props }) {
  const Comp = asChild ? Slot : 'button'

  return <Comp {...props} />
}

#295
class CustomError extends Error {
  name = 'CustomError'

  constructor(message?: string) {
    super(message)

    Object.setPrototypeOf(this, CustomError.prototype)
  }
}

try {
  throw new CustomError('This is a custom error message.')
} catch (error) {
  if (error instanceof CustomError) {
    console.log('CustomError occurred:', error.message)
    console.log('Error name:', error.name)
  } else {
    console.log('An error occurred:', error)
  }
}
#287
17 중 4페이지