JS에 CSS를 두고 좋은 이전 CSS 프로세서로 돌아가는 이유
나는 일찍이 JS의 CSS(JSS)를 매우 좋아했지만, 지금은 다시 예처리된 CSS로 돌아왔다.회귀기술 공포증?아니면 합리적인 선택?설명 좀 할게요.
1. JSS가 해결한 문제
우선 JSS는 개념적 증명만이 아니라 두 가지 난제를 해결했다.'해결' 이라는 뜻으로 그것들을 완화시키는 수단만 제공하는 것이 아니다.
1.1. 모듈 범위 CSS
CSS는 본질적으로 전 세계적이다.CSS 파일을 모듈로 가져오는 것은 모듈 역할 영역처럼 보일 수 있지만 실제로는 그렇지 않습니다.
A.css
.a {
color: red;
}
A.jsx
import './A.css'
function A() {
return <span class='b'>Hi</span>
}
문제 보셨어요?대답하다.
A.jsx
는 b
에서 언급하지 않은 A.css
류를 사용했다.JSS 및 TypeScript를 사용하면 이러한 오류가 발생할 수 없습니다.
A.tsx
const useStyles = createUseStyles({
a: {
color: 'red';
}
})
function A() {
const styles = useStyles()
return <span class={styles.b}>Hi</span>
}
A.tsx
는 컴파일할 수 없습니다.1.2. CSS와 JS 간에 변수 공유
가능한 비 JSS 솔루션은 css-modules에서 지원되는 css-loader입니다. 이것은 약간의 설정이 필요합니다.새 브라우저의 경우 CSS custom properties와 getComputedStyle가 함께 작동합니다.
JSS가 있으면 일은 가능한 한 간단해진다. 너는 일반적인 JS 변수 하나만 있으면 된다. 네가 쓰고 싶은 대로 써라!
const itemHeight = 72
const useStyles = createUseStyles({
item: {
height: itemHeight,
},
})
function Showcase({items, topItem}) {
const styles = useStyles()
return <div style={{translateY: -itemHeight * topItem}}>
{
items.map(item =>
<div class={styles.item}>{item}</div>
)
}
</div>
}
2.가격
2.1. 성과 벌금
styled-components와 react-jss의 가방 비용은 각각 33kB와 61kB로 축소되었다.또 하나는runtime overhead,이것은is not argued,심지어libs의 저자이다.
2.2. 개발자의 경험이 실제로는 더 나쁘다
편집자는 CSS를 알고 있습니다.그들은 문법 강조 표시, 코드 완성, 기타 도움말 서비스를 제공한다.JS가 생기면 많은 것을 놓치게 될 것이다. 왜냐하면 IDE는 JS 대상만 볼 수 있기 때문이다.
const styles = createUseStyles({
btn: {
border: '1px dark gray',
boxSizing: 'border',
padding: '4px 12px',
whiteSpace: 'nowrap',
},
});
심심해 보이고 실수하기 쉽다.겸사겸사 한마디 하자면, 너는 발견했니?대답하다.
색상은
darkgray
이지 dark gray
여야 합니다.IDE가 도움이 되지 않음;하지만 CSS가 있으면스타일링 구성 요소 문법이 더 엉망입니다.
const Btn = styled.button`
border: 1px dark gray;
boxSizing: border;
padding: 0 12px 6px;
whiteSpace: nowrap;
`
2.3. Libs에는 우울한 버그가 포함될 수 있습니다.
예제this one 참조.이 간단한 질의가 작동하지 않는 경우가 있습니다.
const styles = createUseStyles({
item: ({param}) => ({
'@media (min-width: 320px)': {
// ...
},
}),
})
문제는 1년 전이다.이것은 구석이 아닌 하찮은 용법이지만, 여전히 개방되어 있다. making devs suffer정말 아깝다!3. 그렇다면 JSS는 가치가 있는가?
나는 기술을 선택하는 것이 균형의 문제라는 것을 안다.어떤 사람은 이익이 폐단보다 크다는 것을 발견할 수 있다.개인적으로 JSS의 성능과 개발 경험이 가치가 있는지 의심스럽습니다.
근데 JS 없이 어떻게 살아요?유행하는 옵션을 보여 주세요.
3.1. CSS modules
CSS 모듈도 클래스 이름을 생성하지만 JS와 달리 컴파일할 때 클래스 이름을 생성하고 실행할 때 비용을 분배하지 않습니다.만약 당신configured everything correctly이 이렇다면:
유리 진열장.css
.showcase {
display: flex;
}
.item {
width: 33%;
}
.highlighted {
background-color: lightgray;
}
유리 진열장.css.d, td(생성됨)
export const showcase: string
export const item: string
export const highlighted: string
유리 진열장.tsx
import styles from './Showcase.css'
type Props = {items: string[], highlighted: number}
function Showcase({items, highlighted}: Props) {
return <div className={styles.showcase}>{
items.map((item, i) => {
const c = `${styles.item} ${i===highlighted ? styles.highlighted : ''}`
return <div className={c}>{item}</div>
})
}</div>
}
괜찮아 보여요!JSS의 장점이 있지만 실행 시 벌칙이 삭제되었습니다.그러나 보시다시피 type definitions generated가 있기 때문에 개발 과정을 순조롭게 하기 위해서는 적절한 설정을 하고 코드를 작성할 때 개발 서버를 시종일관 실행해야 합니다.물론 이것은 나의 경험이다.3.2. BEM
BEM은 가장 유명한 CSS 클래스 이름 규약일 수 있습니다.전체 사양은 상세해 보이지만 본질은 간단합니다.
block__element
block_modifier
block__element_modifier
유리 진열장.scss
.showcase {
display: flex;
&__item {
width: 33%;
&_highlighted {
background-color: lightgray;
}
}
}
유리 진열장.jsx
import './Showcase.scss';
import {withNaming} from '@bem-react/classname';
const cn = withNaming({e: '__', m: '_', v: '_' })
const showcaseCn = cn('showcase');
const itemCn = cn('showcase', 'item')
function Showcase({items, highlighted}) {
return <div className={showcaseCn()}>{
items.map((item, i) => {
const c = itemCn({highlighted: i===p.highlighted})
return <div className={c}>{item}</div>
})
}</div>
}
BEM 과정을 간소화할 수 있습니까?
나는 BEM을 매우 좋아하지만, 접두사나 긴 명칭을 사용하는 것은 나에게 매우 지루한 것 같다.만약 우리가 CSS 조합부호로 그것들을 바꾸면?한 번 시도해 봅시다.
유리 진열장.scss
.b-showcase {
display: flex;
>.item {
width: 33%;
&.highlighted {
background-color: lightgray;
}
}
}
유리 진열장.jsx
import './Showcase.scss';
function Showcase({items, highlighted}) {
return <div className='b-showcase'>{
items.map((item, i) => {
const c = `item ${i===p.highlighted ? 'highlighted' : ''}`
return <div className={c}>{item}</div>
})
}</div>
}
이게 더 자연스러워 보여요.노트:b-
블록 이름이 아닌 경우Descendant combinator 은(는) 실수로 네스트된 블록
어떻게 블록 클래스가 대형 응용 프로그램에서 유일하다는 것을 확보합니까?
이것은 아마도 BEM의 가장 어려운 부분일 것이다.그러나 scss-parser의 도움말 아래 SCSS 파일을 분석하고 검증하는 프로그램(또는 패키지 플러그인)을 작성할 수 있습니다.
검증하다.ts(약식)
import {parse} from 'scss-parser'
const clsToFile = new Map<string, string>()
for await (const file of walkDir(__dirname)) {
const cn = getTopLevelClass(String(await fs.promises.readFile(file)))
if (!cn) {
throw new Error(`No top level class: ${file}`)
}
if (clsToFile.has(cn)) {
throw new Error(`Duplicate class '${cn}' in ${clsToFile.get(cn)} and ${file}` )
}
clsToFile.set(cn, file)
}
// Walks a dir recursively yielding SCSS files
async function* walkDir(dir: string): AsyncGenerator<string> {
// ...
}
// Returns top-level class if there is one
function getTopLevelClass(scss: string) {
const ast = parse(scss)
// ...
}
완전 검증.tsimport {parse, Node} from 'scss-parser'
import fs from 'fs'
import path from 'path'
main()
main() {
const clsToFile = new Map<string, string>()
for await (const file of walkDir(__dirname)) {
const cn = getTopLevelClass(String(await fs.promises.readFile(file)))
if (!cn) {
throw new Error(`No top level class: ${file}`)
}
if (clsToFile.has(cn)) {
throw new Error(`Duplicate class '${cn}' in ${clsToFile.get(cn)} and ${file}` )
}
clsToFile.set(cn, file)
}
}
async function* walkDir(dir: string): AsyncGenerator<string> {
const entries = await fs.promises.readdir(dir, {withFileTypes: true})
for (const e of entries) {
const file = path.resolve(dir, e.name)
if (e.isFile() && /\.scss$/.exec(e.name)) {
yield file
} else if (e.isDirectory()) {
yield* walkDir(file)
}
}
}
function getTopLevelClass(scss: string) {
const ast = parse(scss)
if (Array.isArray(ast.value)) {
const topLevelClasses = ast.value
.filter(node => node.type === 'rule')
.flatMap(ruleNode => ruleNode.value as Node[])
.filter(node => node.type === 'selector')
.flatMap(selectorNode => selectorNode.value as Node[])
.filter(node => node.type === 'class')
.flatMap(classNode => classNode.value as Node[])
.filter(node => node.type === 'identifier')
.map(identifierNode => identifierNode.value as string);
if (topLevelClasses.length === 1) {
return topLevelClasses[0];
}
}
}
변수 공유 어떡하지?
이것은 결코 그렇게 간단하지는 않지만 몇 가지 선택이 있다.
요구 사항에 맞지 않는 경우 다음과 같은 몇 가지 명명 규칙을 도입할 수 있습니다.
유리 진열장.scss
$shared-pad-size: 6px;
.showcase {
padding: $pad-size;
// ..
}
유리 진열장.jsx
const sharedPadSize = 6;
export function Showcase() {
// ...
}
3.3. Tailwind CSS
솔직히 나는 그것을 좋아하지 않지만 2021년 CSS를 언급할 때 그것을 언급하지 않을 수는 없다.네.개발자들은 이 문제를 논쟁할 뿐만 아니라 이 문제를 논쟁할 수도 있다.이것은 매우 재미있지만, 나는 옆에 있을 것이다😉
3.4. Web components
이것은 완전히 다른 세계다.그것은 새로운 것이 아니지만, 모든 주류 브라우저가 그것을 완전히 지원하는 것은 아니다.어쩌면 이것이 미래의 주류일지도 모르는데, 누가 알겠는가🙂
그래서 마지막으로...무엇을 선택하시겠습니까?
이거 어려워요.은탄이 없고 타협과 절충이 있다.나는 연결되지 않은 경계원법이나 단지 경계원법을 더 좋아한다.너는?
Reference
이 문제에 관하여(JS에 CSS를 두고 좋은 이전 CSS 프로세서로 돌아가는 이유), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/alekseiberezkin/why-i-left-css-in-js-and-returned-to-good-old-css-preprocessors-2mko텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)