Translate

2019년 5월 16일 목요일

[Vue.js 2.x][Error] strict 모드에서는 속성을 여러 번 정의할 수 없습니다. (IE11에서만 발생)




증상

 - Chrome, Edge 브라우저에서는 문제 없지만 IE11 에서만 다음과 같은 오류가 발생하며 화면이 정상적으로 렌더링 되지 않는다.
1004lucifer


[Vue warn]: Failed to resolve async component: function component() {
          return __webpack_require__.e(/*! import() */ 53).then(__webpack_require__.bind(null, /*! @/views/board/noti/NotiModifySvc */ "./src/views/board/noti/NotiModifySvc.vue"));
        }
Reason: SyntaxError: strict 모드에서는 속성을 여러 번 정의할 수 없습니다.



외국에서는 아래와 같이 나오나보다.. (링크)

[Vue warn]: Failed to resolve async component: function ShippingAddress() {
return __webpack_require__.e/* import() */(30).then(__webpack_require__.bind(null, "./vue-src/components/checkout/components/address-pickers/shipping-address.vue"));
}
Reason: SyntaxError: Multiple definitions of a property not allowed in strict mode





원인
1004lucifer
 - 이것저것 확인해가면서 알아보니 결국 아래의 부분이었는데 v-model을 이용해서 checkbox에 값을 넣어주고 있었는데 :checked 를 이용해 중복으로 속성을 추가해줘서 문제가 발생한 것이다.
(:checked 부분을 제거하니 정상적으로 작동이 되었다.)

<div class="form-check">
  <label class="form-check-label" for="ch1">
 <input class="form-check-input" type="checkbox" id="ch1" v-model="urgencyYn" :checked="urgencyYn">
 <span class="form-check-sign"></span>
  </label>
</div>





PS.
Chrome 및 Edge 에서는 문제가 발생하지 않고 IE11에 대해서만 증상이 발생한 원인에 대해서 고민하며 알아보니 ECMAScript6(2015)가 IE11에서는 제대로 동작이 안되는걸 발견했다. (링크1, 링크2)

strict mode 에서는 기본적으로 중복된 속성을 허용하지 않는다고 한다.
var obj= {
  property1: 0,
  property2: 1,
  property1: 2
};


첫번째 JSFiddle 에서 Result 탭을 누르면 IE11의 콘솔에서 strict모드 에러가 나는것을 볼 수 있으며 모습또한 정상적으로 렌더링이 되지 않아 크롬과 모습이 다르다.
두번째 JSFiddle 에서는 Result 탭을 눌러도 IE11의 콘솔에서 에러가 발생하지 않는다.
(이 블로그 글을 IE에서 열고서 개발자도구를 연 상태로 Result 탭을 눌러 실행 시 확인이 가능하다.)




추가로 vue 확장자 파일을 사용하는 프로젝트를 새로 생성하여 테스트 코드를 만들어 테스트 해보니 예상한대로 재현이 되었다.
1004lucifer
<template>
  <div id="app">
    <input type="checkbox" v-model="var1" :checked="var2">
  </div>
</template>

<script>

export default {
  name: 'app',
  data () {
    return {
      var1: true,
      var2: true
    }
  }
}
</script>

<style>
</style>



빌드된 app.js 의 839, 840라인을 확인해보니 다음과 같았다.
(eval 부분은 한줄인데 보기좋게 여러줄로 나눠놨다.)

"use strict";
eval("__webpack_require__.r(__webpack_exports__);
  ...
  attrs: { 
    type: \"checkbox\" },\n      
    domProps: {\n        
    checked: _vm.var2,\n        
    checked: Array.isArray(_vm.var1)\n          
    ? _vm._i(_vm.var1, null) > -1\n          
    : _vm.var1\n      
  },\n      
  on: {\n        
    change: function($event) {\n          
  ...
");
1004lucifer
같은 app.js를 사용하는데 IE11 에서만 strict 모드 에러가 발생한다는 것은
IE에서 작동하는 ECMAScript5와
Chrome에서 작동하는 ECMAScript6의
strict 모드가 다르게 동작하지 않을까 싶어서 ECMAScript 명세를 찾아보니
역시나 strict 모드의 명세가 달랐다.



[ ECMAScript5 ]
 - https://www.ecma-international.org/ecma-262/5.1/#sec-16

Attempts in strict mode code to define an ObjectLiteral that has multiple data property assignments with the same name.


[ ECMAScript6 ]
 - http://www.ecma-international.org/ecma-262/6.0/




결론

 - ECMAScript5 strict모드에서는 같은 이름의 속성을 2개 사용시 에러가 발생을 하며 IE11 에서는 ECMAScript5 를 사용하기 때문에 문제가 발생한다.
1004lucifer
 - Vue.js 사용 시 간단한 프로젝트의 new Vue 방법으로 애플리케이션 작성 시 위의 이슈에 대해서 문제가 되지는 않지만 싱글파일컴포넌트(vue확장자) 애플리케이션의 경우 빌드된 파일 수행 시 IE11에서 에러가 발생한다.

 - new Vue 방법으로 IE11에서 문제가 없는것은 실제 HTML에 작성된 Element 속성의 이름이 같지 않고 동적으로 DOM을 조작하기 때문이고,
  싱글파일컴포넌트에서 문제가 되는 이유는 각각의 vue 파일마다 프리컴파일(precompile)이 되기 때문에 정말로 같은 이름의 속성이 생성되기 때문이라고 생각한다.



댓글 4개 :

  1. 감사합니다ㅠㅜ! 현재 작업하는데 정말 많은 도움이 되었습니다.

    추가적으로,
    처음 이 문제를 디버깅 하실때 어떻게 먼저 접근하셨는지 알수 있을까요?

    답글삭제
    답글
    1. 네~ 안녕하세요.

      콘솔로그에 나오는..
      ===========================
      'strict 모드에서는 속성을 여러 번 정의할 수 없습니다.'
      app.js (840,1)
      ===========================
      항목에 대해서 840 위치를 찾아 어떤 코드가 있나 확인을 했고 저게 왜 문제가 되었는지 고민을 하다가 IE 자체 버그로 생각을 했었는데 혹시나 싶어 스펙을 찾아보니 저런 항목이 있어서 알게되었네요.

      포스팅에는 원인과 결과만 있어서 금방 읽히겠지만..
      처음에 IE문제로 치부하다가 나중에 다시 스펙을 하나하나 찾아보고..
      시간을 엄청나게 들여서 디버깅 한거예요..ㅠ

      삭제
    2. 네 저도 ie 문제로 인식했었는데
      덕분에ㅠㅠㅠ 금방해결할 수 있었습니다 ㅠㅠ
      다시한번 감사드려요

      다른 글들도 도움이 많이 되고 있어요!

      삭제
    3. 다른 글들도 도움이 된다니 힘이나네요!! ;)

      삭제