Nuxtjs + Typescript 프로젝트를 진행하고 있는데, 초반 설정부터 많은 문제가 생겼다.

이전에 작업할 때는 내가 린트 설정한 적이 없어서 생기는 문제인지, (내 머리탓)

아니면 버전(현재 v2.15.8)이 달라져서 혹은 Typescript 설정으로 생기는 문제인지 모르겠으나.

결론은 골치아픈 린트 설정 문제였다.

 

그래서 이렇게 골치아픈 김에 이것저것 검색해보고 설정하는데 꽤나 시간을 들이고 있다. (eslint, prettier, stylelint....)

덕분에 설정에만 시간을 엄청 쏟고 있다.

뻘짓에 대한 기록글과 해결한 방법 (은 하단에!)

 

과정에 대한 글

.stylelintrc.js - 실패

이렇게 더러운걸 커밋했다고? ㅎㅎㅎㅋㅋㅋㅋ

module.exports = {
  customSyntax: "postcss-html",
  extends: "stylelint-config-standard",
  plugins: ["stylelint-scss", "stylelint-order"],
  rules: {
    "string-quotes": "single",
  },
  overrides: [
    {
      files: [
        '**/**/*.scss',
        '**/**/**/*.scss',
      ],
      customSyntax: "postcss-scss",
      extends: "stylelint-config-standard-scss",
      rules: {
        "no-eol-whitespace": true, // 줄 끝, 닫는 중괄호 뒤 공백 허용 여부
        "color-hex-length": "long", // 16진수 색상에 대해 표기법 지정
        "declaration-block-trailing-semicolon": "always", // 선언 블록 내 후행 세미콜론을 요구
        "color-no-invalid-hex": true, // 잘못된 16진수 색상을 허용 여부
        "font-family-no-duplicate-names": true, // 중복 폰트 선언 여부
        "declaration-block-no-duplicate-properties": true, // 같은 선언 내 중복 속성 선언 여부
        "declaration-block-no-duplicate-custom-properties": true, // 같은 선언 내 중복 사용자 속성 선언 여부
        "no-duplicate-at-import-rules": true, // 중복 @import 규칙을 허용 여부
        "media-query-list-comma-newline-after": "always", // 미디어 쿼리 목록 쉼표 뒤 줄 바꿈이나 공백

        // 개행
        "rule-empty-line-before": "always-multi-line", // 규칙 앞에 빈줄 속성
        "block-opening-brace-newline-before": "never-single-line", // 여는 중괄호 앞 (선택자와 괄호 사이)
        "block-opening-brace-newline-after": "always", // 여는 중괄호 다음 개행
        "block-closing-brace-newline-after": "always", // 닫는 중괄호 뒤
        "block-closing-brace-newline-before": "always", // 닫는 중괄호 앞
        "block-opening-brace-space-before": "always", // 여는 중괄호 앞
      },
    }
  ]
}

 

postCSS를 제거하고 SCSS로 작업하려고 했더니, 종속성때문에 에러가 났다.

그래서 그냥 삭제하지 않고 customSyntax 설정만 제거했는데 이때도 에러가 났다.

그래서 위와 같이 overrides를 통해 files에서 scss파일만 추가해서 작업했다.

이때 생기는 문제는 vue파일에서 상단 postcss-html이 적용되고 있어서 어쩔수 없이 룰에 string-quotes를 single를 추가해야했다. (이때 .vue 파일때문이 아닐까?? 생각했다. 생각해보니 검색법이 잘못된듯 postCSS를 사용한다는 전제로 검색했던 것인가 휴.)

폴더 구조

이렇게 작업을 하고 나니까 생각해보니 vue파일을 ignore 시키면 될 것 같아서 stylelint의 ignore 설정법을 찾아봤고,,,

https://stylelint.io/user-guide/ignore-code

 

Ignoring code | Stylelint

You can ignore:

stylelint.io

 

결론

.stylelintrc.js

module.exports = {
  extends: "stylelint-config-standard-scss",
  plugins: ["stylelint-scss", "stylelint-order"],
  rules: {
  	"order/properties-alphabetical-order": true, // 알파벳 정렬
    "no-eol-whitespace": true, // 줄 끝, 닫는 중괄호 뒤 공백 허용 여부
    "color-hex-length": "long", // 16진수 색상에 대해 표기법 지정
    "declaration-block-trailing-semicolon": "always", // 선언 블록 내 후행 세미콜론을 요구
    "color-no-invalid-hex": true, // 잘못된 16진수 색상을 허용 여부
    "font-family-no-duplicate-names": true, // 중복 폰트 선언 여부
    "declaration-block-no-duplicate-properties": true, // 같은 선언 내 중복 속성 선언 여부
    "declaration-block-no-duplicate-custom-properties": true, // 같은 선언 내 중복 사용자 속성 선언 여부
    "no-duplicate-at-import-rules": true, // 중복 @import 규칙을 허용 여부
    "media-query-list-comma-newline-after": "always", // 미디어 쿼리 목록 쉼표 뒤 줄 바꿈이나 공백

    // 개행
    "rule-empty-line-before": "always-multi-line", // 규칙 앞에 빈줄 속성
    "block-opening-brace-newline-before": "never-single-line", // 여는 중괄호 앞 (선택자와 괄호 사이)
    "block-opening-brace-newline-after": "always", // 여는 중괄호 다음 개행
    "block-closing-brace-newline-after": "always", // 닫는 중괄호 뒤
    "block-closing-brace-newline-before": "always", // 닫는 중괄호 앞
    "block-opening-brace-space-before": "always", // 여는 중괄호 앞
  },
}

 

.stylelintignore

루트에 파일 생성

*.vue

그렇다 걍 vue 파일을 ignore시키면 되는 것이었다. 

(postcss, postcss-html, postcss-scss 모두필요엄슴 uninstall)

 

stylelint 적용

 

뒤에 필수표시(*)를 적용 시키려고 하다가 발견한 이슈로...

 

word-break="keep-all"이 아닌 경우에는 붙이기가 굉장히 쉬웠다.

그냥 position: absolute해서 우측에 가져다가 붙이면 되니까.

word-break: normal
word-break: normal

 

여기서 이제 모바일에서 단어 기준으로 끊으려고 하다 발견.

떨어지는 공백 '자차'의 크기만큼 영역이 유지되고 있다.

따라서 떨어지는 글자수의 값이 다르면 필수표시(*)의 위치 값도 달라진다.

word-break: keep-all
word-break: keep-all

 

중요한 이슈가 아니다보니, 그냥 줄 바꿈 처리를 위해서 문자열 끝에 붙이기로 했다.

 

this.$router.push(동일path)일 경우 에러가 나고 새로 고침을 하자니 SPA페이지에서 낭비인 것 같기도 해서

어떤 방식을 써야하나? 고민을 하다가 찾은 방식. (기록을 위한 작성)

검색하다가 알게된 블로그에서 3가지 방식을 알려주고 있었다. 

v-if 방식, forceUpdate 방식, 그리고 key를 통한 방식.

가장 추천하는 방식으로 (vue가 원하는..?) 진행했다.

 

레이아웃 단계에서 진행.

base-header 컴포넌트에 gnb가 있으며  nuxt 컴포넌트는 페이지이다. 

// BaseLayout.vue
<template>
	<div>
    	<base-header @forceUpdate="handleForceUpdate"/>
    </div>
    <div>
    	<Nuxt :key="componentRenderKey"/>
    </div>
    <div>
    	<base-footer />
    </div>
</template>

<script>
export default {
  name: 'BaseLayout',
  data() {
    return {
      componentRenderKey: 0,
    }
  },
  methods: {
  	handleForceUpdate() {
      // 키 값이 올라가면서 :key의 값이 변하여 Nuxt가 리렌더링된다. 
      this.componentRenderKey = this.componentRenderKey + 1;
      // 이때 스크롤까지 초기화되는 것은 아니므로 top으로 올려주기
      window.scroll(0, 0);
    },
  }
}
</script>

 

// base-header.vue
<template>
	<header>
    	<ul>
        	<li v-for="nav in gnb">
            	<nuxt-link 
                  :to="nav.path" 
                  @click.native="() => handleForceUpdate(nav.path)"  
                >
                  {{nav.name}}
                </nuxt-link>
            </li>
            // ....
        </ul>
    </header>
</template>

<script>
export default {
  name: 'BaseHeader',
  methods: {
	handleForceUpdate(to) {
      if (to === this.$route.path) {
        // 상위컴포넌트(Base Layout)로 이벤트 발생 (emit)
        this.$emit('forceUpdate');
      } else {
        this.$router.push(to);
      }
    }
  }
}
</script>

 


* 출처: 3가지 방식을 안내해줌

https://michaelnthiessen.com/force-re-render/

 

isUndefined와 isEmpty 비교

    console.log('빈 배열', `isUndefined: ${isUndefined([])} / isEmpty: ${isEmpty([])}`);
    console.log('빈 오브젝트', `isUndefined: ${isUndefined({})} / isEmpty: ${isEmpty({})}`);
    console.log('빈 문자열', `isUndefined: ${isUndefined('')} / isEmpty: ${isEmpty('')}`);
    console.log('null', `isUndefined: ${isUndefined(null)} / isEmpty: ${isEmpty(null)}`);
    console.log('undefined', `isUndefined: ${isUndefined(undefined)} / isEmpty: ${isEmpty(undefined)}`);

    console.log('숫자', `isUndefined: ${isUndefined(1234)} / isEmpty: ${isEmpty(1234)}`);
    console.log('문자열', `isUndefined: ${isUndefined('hello')} / isEmpty: ${isEmpty('hello')}`);
    console.log('불린 값: true', `isUndefined: ${isUndefined(true)} / isEmpty: ${isEmpty(true)}`);
    console.log('불린 값: false', `isUndefined: ${isUndefined(false)} / isEmpty: ${isEmpty(false)}`);

 

console.log로 확인 한 값

isUndefined와 isEmpty 비교

 

정리

빈 배열, 오브젝트, 문자열, null 확인: isEmpty

null 확인 : isEmpty (-> ?? (Nullish coalescing operator) 등으로 해결)

undefined 확인: 둘다 값으로 인식 (-> value === undefined 등으로 해결)

숫자 확인: isEmpty는 숫자를 넣으면 비어있다고 인식하는 버그(?)가 있다.

불린 값 확인: isUndefined는 둘다 비어있다고 인식한다. (-> value, !value 등으로 해결)

 


lodash doc: https://lodash.com/docs/4.17.15

+ Recent posts