ES2015 모듈을 사용하면 애플리케이션 코드를 재사용 가능하고 캡슐화 된 단일 작업 중심 모듈로 청크 할 수 있습니다.
https://dmitripavlutin.com/javascript-modules-best-practices/
모두 훌륭하지만 모듈을 어떻게 구성합니까? 모듈에는 몇 개의 함수, 클래스가 있어야 합니까?
이 게시물에서는 JavaScript 모듈을 보다 잘 구성하는 방법에 대한 4 가지 모범 사례를 제시합니다.
1. Prefer named exports
JavaScript 모듈을 사용하기 시작할 때 기본 구문을 사용하여 모듈이 정의한 단일 부분 (클래스 또는 함수)을 내보냈습니다.
예를 들어 다음은 Greeter 클래스를 기본값으로 내보내는 모듈 greeter입니다.
// greeter.js
export default class Greeter { constructor(name) {
this.name = name;
}
greet() {
return `Hello, ${this.name}!`;
}
}
시간이 지나면서 기본적으로 내 보낸 클래스 (또는 함수)를 리팩토링 하는 데 어려움이 있음을 알게 되었습니다. 원래 클래스의 이름이 바뀌었을 때 소비자 모듈 내의 클래스 이름은 변경되지 않았습니다.
게다가 에디터는 클래스 이름을 가져올 때 자동 완성 제안을 제공하지 않았습니다.
기본 수출은 눈에 띄는 이점을 제공하지 않는다고 결론지었습니다. 그런 다음 명명 된 내보내기로 전환했습니다.
Greeter를 명명 된 내보내기로 만들고 이점을 살펴 보겠습니다.
// greeter.js
export class Greeter { constructor(name) {
this.name = name;
}
greet() {
return `Hello, ${this.name}!`;
}
}
명명 된 내보내기를 사용하면 편집기의 이름을 더 잘 바꿀 수 있습니다. 원래 클래스 이름을 변경할 때마다 모든 소비자 모듈도 클래스 이름을 변경합니다.
자동 완성은 가져온 클래스를 제안합니다.
조언은 다음과 같습니다.
리팩토링 및 코드 자동 완성의 이름을 변경하여 명명 된 모듈 내보내기를 선호합니다.
참고 : React, Lodash와 같은 타사 모듈을 사용하는 경우 일반적으로 기본 가져 오기가 정상입니다. 기본 가져 오기 이름은 변경되지 않는 상수입니다 : React, _.
2. No work during import
모듈 수준 범위는 함수, 클래스, 조명 개체 및 변수를 정의합니다. 모듈은 이러한 구성 요소 중 일부를 내보낼 수 있습니다. 그게 다야.
// Module-level scope
export function myFunction() {
// myFunction Scope
}
모듈 수준 범위는 JSON 구문 분석, HTTP 요청, 로컬 저장소 읽기 등과 같은 과도한 계산을 수행해서는 안됩니다.
예를 들어, 다음 모듈 구성은 글로벌 변수 bigJsonString에서 구성을 구문 분석합니다.
// configuration.js
export const configuration = {
// Bad
data: JSON.parse(bigJsonString)};
bigJsonString 구문 분석이 모듈 레벨 범위에서 수행되기 때문에 문제가 됩니다. 구성 모듈을 가져올 때 bigJsonString 구문 분석이 실제로 발생합니다.
// Bad: parsing happens when the module is imported
import { configuration } from 'configuration';
export function AboutUs() {
return <p>{configuration.data.siteName}</p>;
}
더 높은 수준에서 모듈 수준 범위의 역할은 모듈 구성 요소를 정의하고, 종속성을 가져오고, 공용 구성 요소를 내보내는 것입니다. 이것이 종속성 해결 프로세스입니다. JSON 구문 분석, 요청, 이벤트 처리 등 런타임과 분리되어야 합니다.
지연 구문 분석을 수행하기 위해 구성 모듈을 리팩터링 합니다.
// configuration.js
let parsedData = null;
export const configuration = {
// Good
get data() { if (parsedData === null) {
parsedData = JSON.parse(bigJsonString);
}
return parsedData;
}
};
data 속성은 getter로 정의되므로 소비자가 configuration.data에 액세스 할 때만 bigJsonString이 구문 분석됩니다.
// Good: JSON parsing doesn't happen when the module is imported
import { configuration } from 'configuration';
export function AboutUs() {
// JSON parsing happens now
return <p>{configuration.data.companyDescription}</p>;}
소비자는 무거운 작업을 수행 할 시기를 더 잘 알고 있습니다. 소비자는 브라우저가 유휴 상태 일 때 작업을 수행하기로 결정할 수 있습니다. 또는 소비자가 모듈을 가져올 수 있지만 어떤 이유로 든 사용하지 마십시오.
이를 통해보다 강력한 성능 최적화 기회를 제공합니다. 대화식 시간을 단축하고 주요 스레드 작업을 최소화합니다.
모듈을 가져 오면 아무 작업도 수행해서는 안됩니다. 오히려 소비자는 런타임 작업을 수행 할 시기를 결정해야 합니다.
3. Favor high cohesion modules
Cohesion은 모듈 내부의 구성 요소가 서로 속하는 정도를 나타냅니다.
높은 응집력 모듈의 기능, 클래스 또는 변수는 밀접한 관련이 있습니다. 그들은 하나의 작업에 중점을 둡니다.
formatDate 모듈은 기능이 밀접하게 관련되어 있고 날짜 형식에 중점을 두기 때문에 응집력이 높습니다.
// formatDate.js
const MONTHS = [
'January', 'February', 'March','April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December'
];
function ensureDateInstance(date) {
if (typeof date === 'string') {
return new Date(date);
}
return date;
}
export function formatDate(date) {
date = ensureDateInstance(date);
const monthName = MONTHS[date.getMonth())];
return `${monthName} ${date.getDate()}, ${date.getFullYear()}`;
}
formatDate(), ensureDateInstance() 및 MONTHS는 서로 밀접한 관련이 있습니다.
MONTHS 또는 ensureDateInstance()를 삭제하면 formatDate()가 중단됩니다. 이는 응집력이 높다는 표시입니다.
3.1 The problem of low cohesion modules
반면에 응집력이 낮은 모듈이 있습니다. 서로 관련이 없는 구성 요소를 포함하는 구성 요소.
다음 utils 모듈에는 서로 다른 작업을 수행하는 3 가지 기능이 있습니다.
// utils.js
import cookies from 'cookies';
export function getRandomInRange(start, end) {
return start + Math.floor((end - start) * Math.random());
}
export function pluralize(itemName, count) {
return count > 1 ? `${itemName}s` : itemName;
}
export function cookieExists(cookieName) {
const cookiesObject = cookie.parse(document.cookie);
return cookieName in cookiesObject;
}
getRandomInRange(), pluralize() 및 cookieExists()는 다른 작업을 수행합니다. 난수 생성, 문자열 형식 지정 및 쿠키 존재 여부 확인. 이러한 기능을 삭제해도 나머지 기능에는 영향을 미치지 않습니다. 이는 응집력이 낮다는 표시입니다.
낮은 응집력 모듈은 대부분 관련이 없는 여러 작업에 중점을 두기 때문에 이러한 모듈에 대해 추론하기가 어렵습니다.
또한, 응집력이 낮은 모듈은 소비자가 항상 필요하지 않은 모듈에 의존하게 하여 불필요한 전이 의존성을 생성합니다.
예를 들어, ShoppingCartCount 구성 요소는 utils 모듈에서 pluralize() 함수를 가져옵니다.
// ShoppingCartCount.jsx
import { pluralize } from 'utils';
export function ShoppingCartCount({ count }) {
return (
<div>
Shopping cart has {count} {pluralize('product', count)}
</div>
);
}
ShoppingCartCount 모듈은 utils 모듈에서 pluralize() 함수 만 사용하지만 쿠키 모듈 (utils 내에서 가져옴)에 전 이적 종속성이 있습니다.
좋은 해결책은 낮은 응집력 모듈 유틸리티를 여러 높은 응집력 있는 유틸리티 유틸리티 (utils / random, utils / stringFormat 및 utils / cookies)로 나누는 것입니다.
ShoppingCart 모듈이 utils / stringFormat을 가져 오면 쿠키에 전 이적 의존성이 없습니다.
// ShoppingCartCount.jsx
import { pluralize } from 'utils/stringFormat';
export function ShoppingCartCount({ count }) {
// ...
}
높은 응집력 모듈의 가장 좋은 예는 fs, path, assert와 같은 노드 내장 모듈입니다.
함수, 클래스, 변수가 밀접하게 관련되어 있고 공통적 인 작업을 수행하는 높은 응집력 모듈을 선호합니다. 큰 낮은 응집력 모듈을 여러 개의 높은 응집력 모듈로 분할하여 리팩토링 합니다.
4. Avoid long relative paths
하나 이상의 상위 폴더가 포함 된 모듈의 경로를 이해하기가 어렵습니다.
import { compareDates } from '../../date/compare';import { formatDate } from '../../date/format';
// Use compareDates and formatDate
하나의 부모 선택기를 갖는 것이 일반적으로 문제가 되지 않지만, 2 개 이상을 갖는 것은 일반적으로 파악하기 어렵다.
그렇기 때문에 절대 경로를 선호하는 상위 폴더를 피하는 것이 좋습니다.
import { compareDates } from 'utils/date/compare';import { formatDate } from 'utils/date/format';
// Use compareDates and formatDate
절대 경로는 쓰기에 시간이 더 걸리지만 이를 사용하면 가져온 모듈의 위치가 명확 해집니다.
긴 절대 경로를 완화하기 위해 새 루트 디렉토리를 도입 할 수 있습니다. 예를 들어 babel-plugin-module-resolver를 사용하면 가능합니다.
긴 상대 경로 대신 절대 경로를 사용하십시오.
5. 결론
JavaScript 모듈은 응용 프로그램의 논리를 작은 독립된 청크로 분할하는 데 유용합니다.
기본 내보내기 대신 명명 된 내보내기를 사용하면 명명 된 구성 요소를 가져올 때 이름을 쉽게 바꿀 수 있는 리팩토링 및 편집기 자동 완성 지원의 이점을 얻을 수 있습니다.
'myModule'에서 {myFunc}를 가져 오는 유일한 목적은 myFunc 구성 요소를 가져 오는 것입니다. myModule의 모듈 수준 범위는 가벼운 내용의 클래스, 함수 또는 변수 만 정의해야 합니다.
컴포넌트는 몇 개의 함수 또는 클래스를 가져야 하며, 이러한 컴포넌트는 각 컴포넌트 또는 함수와 어떻게 관련되어야 합니까? 응집력이 높은 모듈 선호 : 구성 요소는 밀접한 관련이 있어야 하며 일반적인 작업을 수행해야 합니다.
많은 상위 폴더를 포함하는 긴 상대 경로 ../는 이해하기 어렵습니다. 절대 경로로 리팩토링 하십시오.
등록된 댓글이 없습니다.