참고자료

Vue CLI 란

Vue CLI 는 커맨드라인 인터페이스 기반의 Vue 프로젝트 생성 도구입니다. Vue 애플리케이션을 개발할 때 기본적인 폴더 구조, 라이브러리 등을 설정해줍다.

1. 설치

npm i -g @vue/cli // vue-cli 3.x
npm i -g vue-cli // vue-cli 2.x

2. 프로젝트 생성

프로젝트를 생성할때 2.x 버전에서는 eslint, unit test, night watch 등등 낯선것들에 대해 선택을 해야만 했는데, 3.x 에서는 default (babel, eslint) 를 선택하면 가장 기본적인 설정으로 프로젝트가 생성됩니다.(나중에 언제든지 옵션을 추가할 수 있습니다.)

vue create '프로젝트 명' // vue-cli 3.X
vue init webpack '프로젝트 명' // vue-cli 2.X

3. 로컬 서버 실행

npm run serve // vue-cli 3.x
npm run dev // vue-cli 2.x

4. node_modules

  • vue-cli 3.x - vue create를 통한 프로젝트 생성 단계에서 함께 설치됩니다.
  • vue-cli 2.x - 프로젝트 생성 후 npm install을 통해 설치합니다.

5. 웹팩 설정 파일

  • vue-cli 3.x 노출 X
  • vue-cli 2.x 노출 O

2.x에서는 webpack.config.js 파일이 루트 디렉토리에 있습니다. 3.x에서는 없기 때문에 설정을 추가하기 위해서는 루트 디렉토리에 vue.config.js 파일을 설정하고 내용을 작성해줍니다. vue-cli 3.x vue.config.js

// vue.config.js
module.exports = {
  // 여기에 옵션을 작성해준다.
}

6. 프로젝트 구성

  • vue-cli 3.x 플러그인 기반으로 기능 추가
  • vue-cli 2.x github의 템플릿 다운로드

2.x 에서는 simple, webpack, webpack-simple, pwa 등 템플릿 리스트 중 하나를 선택해서 프로젝트를 구성했다면, 3.x 에서는 프로젝트에 플러그인 기반으로 원하는 설정 추가합니다.

7. ES6 이해도

  • vue-cli 3.x 필요 O
  • vue-cli 2.x 필요 X

3.x 에서는 ES6 기본 문법 뿐만아니라 축약 문법 또한 알고 있어야 합니다.

 

출처: <https://velog.io/@skyepodium/Vue-CLI-3.X-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0>

 

 

Posted by 철냄비짱
,

vue-axios

Front-End/Vue.js 2019. 12. 30. 08:02

A small wrapper for integrating axios to Vuejs

How to install:

CommonJS:

 

npm install --save axios vue-axios

And in your entry file:

 

import Vue from 'vue'

import axios from 'axios'

import VueAxios from 'vue-axios'

 

Vue.use(VueAxios, axios)

Script:

Just add 3 scripts in order: vue, axios and vue-axios to your document.

Usage:

This wrapper bind axios to Vue or this if you're using single file component.

You can axios like this:

 

Vue.axios.get(api).then((response=> {

  console.log(response.data)

})

 

this.axios.get(api).then((response=> {

  console.log(response.data)

})

 

this.$http.get(api).then((response=> {

  console.log(response.data)

})

 

출처: <https://www.npmjs.com/package/vue-axios>

 

Posted by 철냄비짱
,

Spring boot와 Vue.js를 연동해봅니다.

이 문서에서는 Controller를 어디에 만드는지, cd 명령어는 어디에 입력하는지 등의 모든 과정을 설명하지는 않습니다.

결과물은 이쪽에 --> https://github.com/febdy/Spring-boot-vuejs

 

 

 

Version

Spring boot 2.0.3

Vue.js 2.5.16

Webpack 3.12.0

Gradle 4.x

 

 

 

최종 폴더 구조 예시

 

project

├ src (Spring boot)

│├ main

││ ├ java

││ └ resources

│└ test

├ frontend (Vue.js)

│├ build

│├ config

│├ node_modules

│├  src

││ ├ assets

││ │├ css

││ │├ images

││ │└ js

││ │

││ ├ router

││ ├ shared-components

││ ├ spa

││ │ ├ Member

││ │ │ ├ components

││ │ │ └ Login.vue

││ │ │

││ │ └ Qna

││ │   ├ components

││ │   └ Qna.vue

││ │

││ ├ App.vue

││ └ main.js

││

│├ static

│├ test

│├ .bablerc

│├ .editorconfig

│├ .eslintingore

│├ .eslintrc.js

│├ index.html

│├ package.json

│└ package-lock.json

├ build.gradle

├ gradlew

├ gradlew.bat

└ settings.gradle

 

frontend 구조 참고 : https://github.com/vuejs-kr/vuejs-kr.github.io/issues/28

 

 

 

STEP

 

1. Spring boot

 

 

 

https://start.spring.io/

 

Spring boot는 매우 쉽고 편한 프로젝트 생성 방법을 제공합니다.

Gradle Project를 선택하고 Dependencies엔 Web Thymeleaf 정도 추가해주고 Generate Project로 프로젝트를 받습니다.

옆에 패키지 이름은 원하는 대로 설정.

 

 

 

2. Controller

 

간단히 Controller를 만들어봅니다.

주소/hi를 입력하면 thymeleaf에 의해 resources/templates 안에 있는 index.html에 연결됩니다.

 

 

 

Vue.js

 

1. node.js 설치

 

https://nodejs.org/ko/

 

현재(180718) 기준 8.11.3 LTS 설치했습니다.

 

 

 

2. vue-cli install / init webpack project

 

cd [만들어놓은 Spring boot 폴더] 로 이동해 실행합니다.

 

$ npm install --g vue-cli

$ vue init webpack frontend

 

 

 

3.

 

 

$ cd frontend

$ npm install

 

frontend 폴더 안에 가서 package들을 install합니다.

node_modules라는 폴더가 생깁니다.

 

 

 

4. config/index.js

 

  build: {

    // Template for index.html

    index: path.resolve(__dirname, '../../src/main/resources/static/index.html'),

 

    // Paths

    assetsRoot: path.resolve(__dirname, '../../src/main/resources/static'),

    assetsSubDirectory: 'static',

    assetsPublicPath: '/',

 

 

config/index.js 파일의 경로를 이렇게 수정합니다.

 

 

 

 

 

+) 

application.properties 파일에서

 

spring.thymeleaf.prefix=classpath:/static/

 

추가해줍니다.

static/ index.html 를 읽으려면 thymeleaf의 prefix를 templates가 아닌 static으로 바꿔주어야 합니다.

Vue.js config/index.js의 index 경로를 templates으로 잡으면 spring 설정 없이 그대로 index를 사용 가능 하지만 배포할 때 js 파일을 못 읽을 수도 있습니다.

 

해결 방법은

1. Spring boot에서 thymeleaf의 경로를 바꾸거나

2. Vue.js에서 빌드 설정을 바꿔 static/static/을 인식하게 하는 건데

위가 쉽고 간단하므로 이렇게 해봅니다.

 

 

5. npm run build

 

 

 

$npm run build

 

밑에 파란 글씨의 Build Complete.을 확인합니다.

 

 

 

6. Spring boot server run

 

각자에게 맞는 방법으로 실행해봅니다.

이클립스로는 프로젝트 우클릭 -> Run as -> Spring Boot App.

 

 

 

5. localhost:포트번호/hi

 

브라우저에서 localhost:포트번호/hi를 입력하고 확인해봅니다. Vue 페이지가 뜨면 성공입니다.

 

 

 

* Vue.js 파일 수정 후 바로바로 확인하기

 

Vue.js 파일을 바꾸고 확인할 때마다 build를 해볼 수는 없겠지요.

 

 

 

 

$ npm run dev

 

명령어를 입력하면 개발 모드로 들어가며 파일을 수정하고 저장하는 즉시 바로바로 확인할 수 있습니다.

나오는 방법은

Ctrl + C

 

 

이 서버는 스프링 부트 서버와 별도입니다.

따라서 Vue.js 프로젝트를 확인하기 위해 꼭 Spring boot 서버를 실행할 필요는 없으며

Spring boot 서버에서 확인하고 싶으면 npm run build를 해주어 build된 파일이 다시 src/main/resources에 들어가도록 해야 합니다.

 

다른 툴은 모르겠고 이클립스를 사용중이라면 npm run build를 했을 때 프로젝트 폴더에서 F5를 눌러 새로고침을 한 번 해주세요.

src/main/resources 반영이 제때제때 자동으로 안 됩니다. 스프링 부트 서버도 종료했다가 다시 실행해야 합니다.

 

끝~

 

출처: https://febdy.tistory.com/65 [집]

 

출처: https://febdy.tistory.com/65 [집]

 

출처: <https://febdy.tistory.com/65>

 

Posted by 철냄비짱
,

npm 명령어

Front-End/Vue.js 2019. 12. 30. 08:01

 

안녕하세요. 이번 시간에는 npm 명령어에 대해 알아보겠습니다. npm 명령어는 명령 프롬프트에 입력하는 명령어입니다. 지금까지 봤던 명령어는 npm init, npm start npm run, npm install 정도가 있겠네요. 다양한 명령어가 많지만, 그중에서도 자주 쓰이는 것들에 대해 알아보겠습니다.

npm help 또는 npm 명령어 help는 가장 먼저 알려드릴 명령어입니다. 명령어가 뭐가 있는지 모를 때는 npm help를, 해당 명령어가 무슨 역할을 하고, 가능한 옵션은 뭐가 있는지 궁금하면 가운데 명령어를 넣어서 help하면 됩니다. 예를 들어 init이 무슨 명령어인지 모르겠다면 npm init help하면 되는 거죠.

설치 관련

npm init package.json을 만드는 명령어였죠? 새로운 프로젝트나 패키지를 만들 때 사용합니다.

npm install은 이미 아시다시피 패키지를 설치하는 명령어입니다. npm install 패키지@버전하면 특정한 버전을 설치할 수 있고, npm install 주소하면 특정한 저장소에 있는 패키지를 설치할 수 있습니다. 주소는 주로 Github에만 있는 패키지를 설치할 때 사용합니다. 옵션을 줄 수 있는데 뒤에 --save 또는 -S를 하면 dependencies에(npm5부터는 --save옵션이 기본적으로 설정되어 있기 때문에 안 붙여도 됩니다), --save-dev 또는 -D하면 devDependencies에 추가됩니다. 그리고 -g를 하면 글로벌 패키지에 추가됩니다. 글로벌 패키지에 추가하면 이 프로젝트뿐만 아니라 다른 프로젝트도 해당 패키지를 사용할 수 있습니다.

npm update는 설치한 패키지를 업데이트하는 명령어입니다.

npm dedupe는 npm의 중복된 패키지들을 정리할 때 사용합니다. 가끔 쳐주면 용량도 줄이고 좋습니다.

npm docs는 패키지에 대한 설명을 보여줍니다. 하지만 그냥 npm 홈페이지에 가서 보는 게 정신 건강에 좋습니다.

조회 관련

npm root node_modules의 위치를 알려줍니다.

npm outdated는 오래된 패키지가 있는지 알려줍니다. 오래되었고 package.json에 적어둔 버전 범위와 일치하면 빨간색으로, 오래되었지만 버전 범위와 일치하지 않으면 노란색으로 표시됩니다.

npm ls는 패키지를 조회하는 명령어입니다. 현재 설치된 패키지의 버전과 dependencies를 트리 구조로 표현합니다. npm ll을 하면 더 자세한 정보를 줍니다. npm ls [패키지명]을 하면 해당 패키지가 있는지와, 해당 패키지가 어떤 패키지의 dependencies인지 보여줍니다.

npm search는 npm 저장소에서 패키지를 검색하는 명령어입니다. 패키지의 이름, 설명 또는 키워드를 바탕으로 검색 결과가 나옵니다. 그냥 npm 홈페이지에서 검색하는 게 정신 건강에 좋습니다.

npm owner는 패키지의 주인이 누군지 알려주는 명령어입니다. 또는 여러 명의 주인을 설정하거나 지울 수 있습니다.

npm bugs는 버그가 발생했을 때 어떻게 패키지의 주인에게 연락을 취할지 알려줍니다. 주로 Github의 issues 탭을 엽니다.

로그인 관련

npm adduser은 npm에 회원가입하는 명령어입니다. 로그인도 됩니다. npm login도 똑같은 역할을 합니다.

npm logout은 반대로 logout할 때 사용합니다.

npm whoami는 귀여운 명령어입니다. 이름 그대로 내가 누군지 물어보는 명령어죠. 로그인한 상태라면 자신의 아이디를 알려줍니다.

출시 관련

npm publish는 패키지를 직접 출시하거나 버전 업그레이드를 할 때 사용하는 명령어입니다. .gitignore또는 .npmignore 파일에 적혀있지 않은 파일들은 npm 저장소에 업로드되어 출시됩니다. 여러분도 이제 자신의 패키지를 가질 수 있는거죠. 이 명령어를 사용하려면 여러분은 로그인한 상태여야 합니다. 그리고 패키지의 이름은 선점하는 사람이 계속 쓰기 때문에 이름을 선점하는 것도 중요합니다.

npm deprecate는 이미 낸 패키지를 사용하지 않도록 권고하는 명령어입니다. 자신이 어떤 버전을 출시했는데 치명적인 버그가 있다면 이 명령어를 사용해서 다른 사람들에게 사용하지 말도록 말해줍시다.

npm unpublish는 publish한 패키지를 다시 unpublish하는 겁니다. 하지만 deprecate를 쓰는 게 나은 게 이미 자신의 패키지를 다운로드한 사람들에게 피해를 입힐 수 있습니다.

npm star는 자신이 좋아하는 패키지를 표시하는 기능입니다. 이 star이 많을 수록 인기 패키지이기도 합니다. 심심하시면 제 react-vote나 react-filepicker에 star 해보세요.

npm starts는 특정 사람이 star한 패키지 목록을 확인할 수 있습니다.

npm version은 버전 업데이트를 할 때 사용합니다. 새로운 버전이 나왔다면 npm version [버전]하면 됩니다.

실행 관련

npm start package.json의 scripts에 있는 start 명령어를 실행하는 부분입니다. 만약 start 명령어를 따로 설정하지 않았다면 node server.js가 실행됩니다.

npm stop은 뭔지 알겠죠? npm start했던 것을 멈추는 명령어입니다.

npm restart npm stop 후에 다시 npm start를 하는 명령어입니다.

npm test는 test 명령어를 실행합니다.

npm run은 그 이외의 scripts를 실행하는 명령어입니다. 예를 들어 scripts에 build 명령어가 있다하면, npm run build하면 됩니다.

설정 관련

npm cache는 npm 내의 cache를 보여줍니다. 만약 npm에 문제가 생기거나 하면 제일 먼저 하는 게 npm cache clean으로 cache를 지우는 겁니다.

npm rebuild는 npm을 다시 설치하는 명령어입니다. 에러가 발생했을 시 주로 npm cache clean을 한 후 이 명령어를 쳐서 재설치해봅니다.

npm config는 npm의 설정을 조작하는 명령어입니다. npm config list 하면 현재 설정들을 볼 수 있고, npm set [이름] [값], npm get [이름]으로 속성을 설정하거나 조회할 수 있습니다.

명령어가 많죠? 이중에 자주 쓰이는 명령어는 설치나 업데이트 또는 조회 관련 명령어일 겁니다. 하지만 다른 명령어도 종종 쓰이기 때문에 알아두는 것이 좋습니다.

 

출처: <https://www.zerocho.com/category/NodeJS/post/58285e4840a6d700184ebd87>

 

 

Posted by 철냄비짱
,

자바스크립트뿐만 아니라 모든 언어에서 시간 차이를 구하는 함수는 많이 사용됩니다.

오늘은 자바스크립트에서 Moment.js를 사용하여 시간차이를 구하는 방법에 대해서 알아보도록 하겠습니다.

 

 

Moment.js란?

 

 

Moment.js를 사용하여 시간차이 구하기

(시간1: 과거시간, 시간2: 현재시간 임을 가정합니다.)

      • Sample 1)
        - 시간 1, 시간 2 사이의 일(day) 차이 구하기
        console.log('일 차이: ', moment.duration(t2.diff(t1)).asDays());
      • Sample 2)
        - 시간 1, 시간 2 사이의 시간(hour) 차이 구하기
        console.log('시간 차이: ', moment.duration(t2.diff(t1)).asHours());
      • Sample 3)
        - 시간 1, 시간 2 사이의 분(minute) 차이 구하기
        console.log('분 차이: ', moment.duration(t2.diff(t1)).asMinutes());
      • Sample 4)
        - 시간 1, 시간2 사이의 밀리세컨드(ms) 차이 구하기
        console.log('밀리세컨즈 차이: ', moment.duration(t2.diff(t1)).asMilliseconds());
        <Sample 1,2,3,4 code>

<결과>

      • Sample 5)
        - 시간1, 시간2 사이의 시분초(X시간 Y분 Z초) 차이 구하기

 

 

참조

 

 

출처: https://ithub.tistory.com/196 [Fall in IT.]

 

출처: <https://ithub.tistory.com/196>

 

Posted by 철냄비짱
,

vue-ads-pagination

Vue ads pagination is a vue js pagination component. On the left side you find some information about the shown items. On the right side you can select a specific, the first, last, next or previous page.

All the components can be overriden by your own components, or you can add your own styles to the default components.

View Demo Download Source

Installation

You can install the package via npm or yarn.

NPM

npm install vue-ads-pagination --save

YARN

yarn add vue-ads-pagination

Usage

You can add the vue-ads-pagination component by using the following code in your project.

<template>
    <div id="app">
        <vue-ads-pagination
            :total-items="200"
            :max-visible-pages="5"
            :page="page"
            :loading="loading"
            @page-change="pageChange"
            @range-change="rangeChange"
        >
            <template slot-scope="props">
                <div class="vue-ads-pr-2 vue-ads-leading-loose">
                    Items {{ props.start }} tot {{ props.end }} van de {{ props.total }}
                </div>
            </template>
            <template
                slot="buttons"
                slot-scope="props"
            >
                <vue-ads-page-button
                    v-for="(button, key) in props.buttons"
                    :key="key"
                    v-bind="button"
                    @page-change="page = button.page"
                />
            </template>
        </vue-ads-pagination>
    </div>
</template>

<script>
import '../node_modules/@fortawesome/fontawesome-free/css/all.css';
import '../node_modules/vue-ads-pagination/dist/vue-ads-pagination.css';

import VueAdsPagination, { VueAdsPageButton } from 'vue-ads-pagination';

export default {
    name: 'App',
   
    components: {
        VueAdsPagination,
        VueAdsPageButton,
    },

data () {
        return {
            loading: false,
            page: 5,
        };
    },

methods: {
        pageChange (page) {
            this.page = page;
            console.log(page);
        },
       
        rangeChange (start, end) {
            console.log(start, end);
        },
    },
};
</script>

Vue

Components

VueAdsPagination

Properties

      • page: (type: number, default: 0) A zero-based number to set the page.
        Be aware you need to update the page property by the result of the page-change action!
      • items-per-page: (type: number, default: 10) The maximum amount of items on one page.
      • max-visible-pages: (type: number, default: 5) The maximum number of pages to be visible if their are too many pages.
      • total-items: (type: number, required) The total amount of items.
      • loading: (type: boolean, default: false) Indicates if the current page is loading.

Events

      • page-change: Emitted on creation, to know the initial state, and if another page is clicked. It contains the following parameters:
      • page: (type: number) The zero-based current page.
      • range-change: Emitted on creation, to know the initial state, and if another page is clicked or the total items change and you're on the last page.
        It contains the following parameters:
      • start: (type: number) A zero-based number to identify the first item.
      • end: (type: number) A zero-based number to identify the last item.

Templates

Default

You can add a default template to use a custom pagination detail box.

The scope contains 3 variables:

      • start: (type: number) The included start item.
      • end: (type: number) The included end item.
      • total: (type: number) The total number of visible items.

<template slot-scope="props">
    {{ props.start }} - {{ props.end }} : Total {{ props.total }}
</template>

Vue

Buttons

If you want to use your own buttons, control their behaviour our style them in a different way.

You can create your own button component and loop over it in this slot or use the predefined VueAdsPageButton.

This is a scoped slot that contains an array of buttons.

      • buttons: (type: Array) A list of all buttons currently used. One button is an object that contains the following attributes:
      • page: (type: number||string) This is the zero based page or the string '...'.
        Note that the value of this attribute for the next and previous icons is calculated by the current page.
        If the current page is 2, the previous page will be 1 and the next page is 3.
      • active: (type: boolean) Is the current page active?
      • disabled: (type: boolean) Is the current button disabled?
      • html: (type: string) This string is shown in the button. So you can use icons for the previous and next button.
      • title: (type: string) If you want to add a title to the button, you can fill this attribute.
      • loading: (type: boolean) Indicates if the button has to show a loading icon.

<template
    slot="buttons"
    slot-scope="props"
>
    <vue-ads-page-button
        v-for="(button, key) in props.buttons"
        :key="key"
        v-bind="button"
        @page-change="page = button.page"
    />
</template>

Vue

VueAdsPageButton

This is the default button. If you want to add extra classes. Add the template above and add the class attribute.

Properties

      • page: (type: number||string, default: 0) A zero-based number that represents the page or '...'.
      • active: (type: boolean, default: false) Is the current button active?
      • disabled: (type: boolean, default: false) Is the current button disabled?
      • html: (type: string, required) This string is shown in the button.
      • title: (type: string, default: '') If you want to add a title to the button, you can fill this attribute.
      • loading: (type: boolean, default: false) Indicates if the button has to show a loading icon.
      • disable-styling: (type: boolean, default: false) Remove all styling classes.

Events

      • page-change: Emitted when the button is clicked.

Testing

We use the jest framework for testing this pagination component. Run the following command to test it:

npm run test:unit

GitHub

arnedesmedt/vue-ads-pagination

215

Vue pagination component  Read More

Latest commit to the develop branch on 1-19-2019

Download as zip

Vue.js Examples

A nice collection of often useful examples done in Vue.js

 

출처: <https://vuejsexamples.com/vue-ads-pagination-is-a-vue-js-pagination-component/>

 

Posted by 철냄비짱
,

Moment.js란?

      • 자바스크립트에서는 날짜를 표시할때 Date 객체를 사용합니다. 이때, 특정 형태의 날짜를 나타내기 위해선 직접 함수를 개발해야합니다.
      • 또, 브라우저에 따라 시간대가 다를 경우 이를 고려하여 개발해야하는 번거러움이 있습니다.
      • Moment.js를 사용하면 이 두가지 문제를 해결할 수 있습니다.

 

 

Moment.js 공식 홈페이지

 

Moment.js 설치

      • 홈페이지에서 직접 다운받을 수 있으며, npm과 같은 패키지매니저를 사용하여 설치 할 수 있습니다.

 

Moment.js 사용법

      • 다운받은 js파일은 프로젝트에 import합니다.
      • moment 객체를 사용하여 아래와 같이 여러 형태의 날짜 형태로 표현이 가능합니다.

 

 

 

Moment.js의 다양한기능

 

 

출처: https://ithub.tistory.com/99 [Fall in IT.]

 

출처: <https://ithub.tistory.com/99>

Posted by 철냄비짱
,

Babel

Babel  ES2015+ 문법을 ES5 지원 브라우저에서 해석할 수 있도록 변환해주는 트랜스파일러이다. 하지만 새롭게 추가된 전역 객체들(Promise, Map, Set..)과 String.padStart 등 전역 객체에 추가된 메서드들은 트랜스파일링만으론 해결하기 어렵기 때문에 core-js  regenerator-runtime 와 같은 별도의 polyfill 이 필요하다.

Babel 기반에서 폴리필을 추가하는 방법은 두 가지가 존재한다. babel-polyfill 을 사용하는 방법과 babel-plugin-transform-runtime 을 사용하는 방법이다. 차례대로 살펴보자.

 

 

 

babel-polyfill

babel-polyfill 은 내부적으로 페북에서 만든 Generator Function 폴리필인 regenerator runtime 과 ES5/6/7 폴리필인 core-js 를 주요 디펜던시로 가지고 있다. 가장 유명하고 안정적인 폴리필들을 사용하기 편리하게 랩핑해 놓은 모듈이라고 생각하면 편하다.

babel-polyfill을 사용하려면 먼저 아래와 같이 npm 으로 설치해준다.

# babel-polyfill 디펜던시 추가
$ npm
install --save babel-polyfill

 

그런 뒤에 스크립트 중 최상위 시작지점에 require 혹은 import 해주면, babel-polyfill 은 전역에 직접 폴리필을 추가한다. 즉, 전역 오염이 발생한다.

require('babel-polyfill');

//혹은

import 'babel-polyfill';

babel-polyfill 을 사용할 때의 장점은 어떤게 있을까?

core-js는 먼저 전역에 폴리필을 추가하기전에 해당 기능이 있는지를 체크하므로, 폴리필이 필요없는 최신 브라우저에서는 폴리필없이 동작하게 되어 (babel-plugin-transform-runtime 를 사용하는 것에 비해) 빠르다.

또 전역 객체를 직접 수정하기 때문에 Array.prototype.includes 등 ES2015+에서 새로 추가된 프로토타입 메서드도 문제없이 사용 가능하고, 덕분에 내가 짠 코드가 아닌 npm에서 디펜던시로 받은 라이브러리가 ES2015+ 에서 새롭게 추가된 객체나 프로토타입 메서드를 사용하는지 신경쓸 필요가 없게 되어 개발할 때도 편리하다.

babel-polyfill 을 사용할 때의 단점이라면 실제 사용하지 않는 폴리필도 몽땅 추가되므로 번들링되는 파일의 크기가 커지게 된다는 점이다.

 

 

 

babel-polyfill 사용 시 주의할 점

한가지 꼭 주의할 부분이 있는데, 한 페이지에서 딱 하나의 babel-polyfill 만 허용된다는 점이다. 두 개의 babel-polyfill 을 실행하게 되면 반복적인 전역 객체 수정을 막기 위해 아래의 오류를 발생시킨다.

Uncaught Error : only one instance of babel-polyfill is allowed

 

babel-polyfill 소스를 살펴보면 내부적으로 전역 변수 하나를 두어 babel-polyfill 이 이미 실행되었는지를 체크하고 이미 실행되었다면 무조건(!!!) 오류를 던지는 구조이다.

if (global._babelPolyfill) {
 
throw new Error("only one instance of babel-polyfill is allowed");
}
global._babelPolyfill =
true;

import "core-js/shim";
import "regenerator-runtime/runtime";

...

 

왜 이렇게 극단적으로 오류를 던지게 했을까?

babel-polyfill 의 디펜던시인 core-js 의 ES6/7 폴리필의 경우 두 번 호출되면 내부적으로 오류가 발생되어 정상적으로 폴리필이 적용되지 않는다. 아마도 core-js 가 가지는 이러한 문제점 때문에 babel-polyfill 에 이런 예외처리가 추가된 게 아닐까 추정된다. 

따라서 babel-polyfill 이 두 번 호출되지 않도록 주의해야 한다. 단순히 babel-polyfill 이 두 번 호출되는 것 뿐만 아니라 core-js 의 ES6/7 폴리필이 로드된 상태에서 babel-polyfill 이 로드되거나 babel-polyfill 이 로드된 상태에서 core-js 의 ES6/7 폴리필이 로드되는 것 역시 주의해야 한다.

정리해보면, 싱글 페이지 어플리케이션에서 또다른 폴리필이 호출될 염려가 전혀 없는 환경이라면, babel-polyfill 만으로 IE8 과 같은 레거시 브라우저에서 큰 문제없이 트랜스파일링된 코드를 실행시킬 수 있기 때문에 babel-polyfill 은 가장 편하고 빠르게 폴리필을 적용할 수 있는 방법으로 추천 할 만하다.

 

 

 

babel-plugin-transform-runtime

babel-polyfill 외에 또 하나의 방법은 babel-plugin-transform-runtime 플러그인을 사용해서 Babel 이 트랜스파일링을 하는 과정에서 폴리필이 필요한 부분을 내부의 헬퍼 함수를 사용하도록 치환해주는 방법이다.

Babel 은 내부적으로 _extend 처럼 공통 함수를 위한 작은 헬퍼들을 사용하는데, 기본적으로 모든 파일에 이런 헬퍼들이 추가되기 때문에 이런 낭비를 막기 위해 transform-runtime 플러그인을 사용해서 모든 헬퍼들을 babel-runtime 이라는 모듈을 참조하도록 해준다. babel-plugin-transform-runtime 은 플러그인 이기때문에 빌드 단계(트랜스파일링 단계)에서 동작하게 된다.

transform-runtime 은 코드에 대한 샌드박스도 제공해주는데 내부적으로 core-js 내장하고 여기에 대한 alias 를 생성해서 트랜스파일링 과정에서 폴리필이 필요한 부분들이 이 alias 를 참조하도록 변경해서 전역 오염없이 폴리필이 적용되도록 만들게 된다.

babel-plugin-transform-runtime 플러그인은 내부적으로 babel-runtime 을 디펜던시로 갖는데, babel-runtime 은 또 core-js 와 regenerator-runtime 을 디펜던시로 갖는다. 자동적으로 babel-runtime/regenerator 와 babel-runtime/core-js 를 내장하게 되며 트랜스파일링 과정에서 인라인 Babel 헬퍼들을 제거하고 babel-runtime/helper 들을 사용하도록 변경하게 된다.

 

babel-plugin-transform-runtime 플러그인을 사용하려면 디펜던시는 아래의 두 가지 모두가 필요하다.

# babel-plugin-transform-runtime 디펜던시 추가
$ npm
install --save-dev babel-plugin-transform-runtime

# babel-runtime 디펜던시 추가
$ npm
install --save babel-runtime

babel-plugin-transform-runtime 은 트랜스파일링 과정에서 헬퍼들을 babel-runtime 모듈이 참조하도록 변경해주는 역할을 하고, babel-runtime 은 실제 실행 환경에서 헬퍼함수들이 참조할 수 있는 폴리필을 내장한 모듈로서 동작한다.

babel-plugin-transform-runtime 을 설정하는건 웹팩 기준으로는 webpack config 에서 babel 의 plugins 에 추가해주기만 하면 된다. 웹팩 설정 파일은 1.x 버전 기준이다. 웹팩 2.x 버전부터는 IE8 지원을 하지 않기 때문에 IE8 지원을 위해 폴리필이 필요한 상황이라면 웹팩 1.x 버전을 사용하는 것이 좀더 안전할 것으로 보인다. (웹팩 2.x 이상 버전도 IE8 에서 동작하기는 하는 것 같다)

loaders: [
   
//Babel 변환
    {
        test:
/\.(js|jsx)$/,
        include: [
           
/src\/js/,
           
/node_modules\/axios/
        ],
        loader:
'babel',
        query: {
            cacheDirectory:
true,

//plugins는 presets 보다 먼저 실행되며,
           
//plugins내의 순서는 처음 -> 나중으로 실행된다.
            plugins: [
               
// ['transform-class-properties'],
               
// ['transform-object-rest-spread', { useBuiltIns: true }],
                [
'transform-runtime'],
            ],
           
           
//presets내의 순서는 나중 -> 처음으로 실행된다.
            presets: [
                [
'env', {
                    targets: {
                        browsers: [
'ie >= 8']
                    },
                    loose:
true,
                }],
               
// ['react'],
            ],
        }
    },

...
],

앞서 설명한 것처럼 babel-plugin-transform-runtime 플러그인은 plugins 항목에 transform-runtime 을 추가해주는 것만으로 충분하다.

 

그 외에 주목해서 볼 부분은, include 로 node_modules 아래에 위치한 axios 를 추가해준 부분이다. 보통 트랜스파일링 대상에서 node_modules 아래에 있는 모듈들은 제외하는 것이 상식이다. 그런데 왜 추가해줬을까? 

axios 는 내부적으로 Promise 를 사용하는 라이브러리인데 Promise 가 전역 레벨에 선언되어 있지 않으면 오류가 발생하게 된다. 앞서 설명한 것처럼 babel-plugin-transform-runtime 플러그인은 전역 레벨에 폴리필을 적용하는 방식이 아니기 때문에 axios 가 실행될 때 Promise 를 찾지 못해 오류가 발생하게 되는 것이다. 이런 오류를 막기 위해 axios 도 babel-plugin-transform-runtime 플러그인을 통해 트랜스파일링 될 수 있도록 include를 사용해서 트랜스파일링 대상으로 추가해주어야 하는 것이다. 이런 부분이 babel-plugin-transform-runtime 플러그인을 사용할 때 주의할 부분이다.

 

babel-plugin-transform-runtime 플러그인은 아래와 같이 추가적인 옵션을 지정해줄 수 있으나 대부분 기본값으로 충분하다.

["transform-runtime", {
   
"helpers": true, // 인라인 바벨 헬퍼 (classCallCheck, extends, 등)을 moduleName. 으로 치환
   
"polyfill": true, // Promise, Set, Map 과 같은 새로운 내장 객체를 전역 오염없이 내부 객체를 참조하도록 변환
   
"regenerator": true, // generator 함수를 전역 오염없이 regenerator runtime 을 사용하도록 변환
   
"moduleName": "babel-runtime" // 헬퍼를 가져올 때 사용할 모듈의 이름
}]

 

 

 

babel-plugin-transform-runtime 플러그인이 적용된 코드

아래와 같은 간단한 코드를 babel-plugin-transform-runtime 을 사용하면 어떻게 트랜스파일링 될까?

class Person {
}

 

앞서 설명한 것처럼 babel-plugin-transform-runtime 은 트랜스파일링 과정에서 헬퍼들을 babel-runtime 모듈이 참조하도록 변경해주는 역할을 하고, babel-runtime 은 실제 실행 환경에서 헬퍼함수들이 참조할 수 있는 폴리필을 내장한 모듈로서 동작하게 된다.

"use strict";

var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var Person = function Person() {
  (
0, _classCallCheck3.default)(this, Person);
};

 

babel-plugin-transform-runtime 을 사용하게 되면 트랜스파일링이 필요한 부분이 너무 많을 경우 용량이 증가할 수 있으나 대체적으로 babel-polyfill 을 사용할 떄보다는 용량이 줄어든다.

하지만 babel-polyfill 과 달리 최신 브라우저에 관계없이 폴리필 코드가 무조건 물려서 동작하기 때문에 더 느려질 수 있다.

 

 

 

babel-plugin-transform-runtime 사용 시 주의할 점

그리고 치명적인 단점이 있는데, Object.assign 처럼 내장 객체의 static 메서드는 사용가능하지만, 새롭게 추가된 인스턴스 메서드 예를들면, [1,2,3,4,5].includes(3) 과 같은 메서드는 트랜스파일링 되지 않기 때문에 오류가 발생한다. 따라서 새롭게 추가된 프로토타입 메서드들은 사용하지 않도록 주의해야 한다.

또 한가지 주의할 점은 디펜던시들의 ES2015 기능들 사용 여부이다. babel-polyfill 은 전역을 직접 수정하기 때문에 npm 을 통해 설치한 디펜던시들이 Promise 와 같은 새로운 내장 객체를 사용하는지 여부를 걱정할 필요가 없지만, babel-plugin-transform-runtime 을 사용하면 이 부분까지 고려해주어야 한다. 예를들어 내부적으로 Promise 를 사용하는 디펀덴시가 있다면 이 디펜던시도 함께 트랜스 파일링 될 수 있도록 바벨 설정을 추가해주어야 한다. 앞의 예시에서는 axios 가 Promise 를 사용하기 때문에 include 로 트랜스파일링 대상에 추가해주었었다.

이런 불편함이 있지만, 전역을 오염시키지 않기 때문에 라이브러리 형태로 동작하는 경우 babel-polyfill 보다는 babel-plugin-transform-runtime 을 사용하는게 바람직하다. 내 라이브러리가 사용될 곳에서 이미 babel-polyfill 을 쓰고 있을 수도 있기 때문이다.

 

 

 

babel-plugin-transform-runtime 과 IE8

babel-plugin-transform-runtime 을 사용해서 IE8을 지원하려면, babel 은 기본적으로 ES5 환경이라고 가정하므로 core-js 의 es5 polyfill 은 필수적으로 필요하다. 앞서 core-js 가 여러번 호출될 경우 오류가 발생한다고 했었는데, 다행히 core-js 의 ES5 폴리필은 여러번 호출되어도 오류가 발생하지 않는다.

import 'core-js/es5';

babel 설정은 앞서 살펴본 것처럼 ES2015+ 관련 프리셋의 loose 모드를 활성화하고, transform-runtime 플러그인을 추가해주면 된다. 여기에서는 바벨의 env 프리셋으로 ES2015 관련 프리셋들을 추가해주고 있다. loose 모드를 활성화하지 않으면 IE8 과 호환성이 없는 코드로 트랜스파일링 되므로 주의해야 한다.

loaders: [
   
//Babel 변환
    {
        test:
/\.(js|jsx)$/,
        include: [
           
/src\/js/,
           
/node_modules\/axios/
        ],
        loader:
'babel',
        query: {
            cacheDirectory:
true,
            plugins: [
                [
'transform-runtime'],
            ],           
            presets: [
                [
'env', {
                    targets: {
                        browsers: [
'ie >= 8']
                    },
                    loose:
true,
                }],
            ],
        }
    },

...
],

그런데 이렇게 Babel을 사용해서 transform을 해줘도 실제로 번들링된 결과물에는 여전히 IE8 에서 오류가 발생하는 default, catch 등의 키워드에 대한 처리가 이루어지지 않는다.

그래서 한번더 최종적으로 es3ify-loader 혹은 babel-plugin-transform-es3-member-expression-literals, babel-plugin-transform-es3-property-literals 플러그인으로 트랜스파일링을 해주어야 완전하게 IE8과의 호환성을 갖추게 된다.

postLoaders: [
    {
        test:
/\.js$/,
        loader:
'es3ify-loader',
    }
]

또 uglify 를 해줄 경우 screw_ie8 옵션을 true 로 줄경우 IE8에서 오류가 발생하므로 반드시 이 옵션을 false 로 주어야 한다.

new webpack.optimize.UglifyJsPlugin({
    compressor: {
        screw_ie8:
false,
        warnings:
false
    },
    mangle: {
        screw_ie8:
false
    },
    output: {
        comments:
false,
        screw_ie8:
false
    }
}),

 

 

 

마치며

IE8 을 지원해야 하는 안타까운 상황이 꽤 오래 가고 있다. 점점 라이브러리들이 IE8 지원을 중단해가는 상황인데 국내에서도 IE8 을 지원하지 않는 상황이 빨리 오기를 기대한다. (최근 개편한 네이버 메인 페이지가 IE7을 지원하는 상황이니 언제쯤에야 그런 날이 올지 모르겠다) 

 

 

 

참조

https://babeljs.io/docs/usage/caveats/

https://babeljs.io/docs/usage/polyfill/

http://babeljs.io/docs/plugins/transform-runtime/

 BABEL, BABEL-PLUGIN-TRANSFORM-RUNTIME, BABEL-POLYFILL, ES2015, WEBPACK

 

출처: <https://programmingsummaries.tistory.com/401>

Posted by 철냄비짱
,

@babel/polyfill

카테고리 없음 2019. 12. 30. 07:45

https://babeljs.io/docs/en/babel-polyfill

 

 

@babel/polyfill

🚨 As of Babel 7.4.0, this package has been deprecated in favor of directly including core-js/stable(to polyfill ECMAScript features) and regenerator-runtime/runtime (needed to use transpiled generator functions):

import "core-js/stable";
import "regenerator-runtime/runtime";

Copy

Babel includes a polyfill that includes a custom regenerator runtime and core-js.

This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool. (this polyfill is automatically loaded when using babel-node).

This means you can use new built-ins like Promise or WeakMap, static methods like Array.from or Object.assign, instance methods like Array.prototype.includes, and generator functions (provided you use the regenerator plugin). The polyfill adds to the global scope as well as native prototypes like String in order to do this.

Installation

npm install --save @babel/polyfill

Copy

Because this is a polyfill (which will run before your source code), we need it to be a dependency, not a devDependency

Size

The polyfill is provided as a convenience but you should use it with @babel/preset-env and the useBuiltInsoption so that it doesn't include the whole polyfill which isn't always needed. Otherwise, we would recommend you import the individual polyfills manually.

TC39 Proposals

If you need to use a proposal that is not Stage 4, @babel/polyfill will not automatically import those for you. You will have to import those from another polyfill like core-js individually. We may work towards including this as separate files in @babel/polyfill soon.

Usage in Node / Browserify / Webpack

To include the polyfill you need to require it at the top of the entry point to your application.

Make sure it is called before all other code/require statements!

require("@babel/polyfill");

Copy

If you are using ES6's import syntax in your application's entry point, you should instead import the polyfill at the top of the entry point to ensure the polyfills are loaded first:

import "@babel/polyfill";

Copy

With webpack, there are multiple ways to include the polyfills:

      • When used alongside @babel/preset-env,
      • If useBuiltIns: 'usage' is specified in .babelrc then do not include @babel/polyfill in either webpack.config.js entry array nor source. Note, @babel/polyfill still needs to be installed.
      • If useBuiltIns: 'entry' is specified in .babelrc then include @babel/polyfill at the top of the entry point to your application via require or import as discussed above.
      • If useBuiltIns key is not specified or it is explicitly set with useBuiltIns: false in your .babelrc, add @babel/polyfill directly to the entry array in your webpack.config.js.

module.exports = {
 
entry: ["@babel/polyfill", "./app/js"],
};

Copy

      • If @babel/preset-env is not used then add @babel/polyfill to webpack entry array as discussed above. It can still be added at the top of the entry point to application via import or require, but this is not recommended.

We do not recommend that you import the whole polyfill directly: either try the useBuiltIns options or import only the polyfills you need manually (either from this package or somewhere else).

Usage in Browser

Available from the dist/polyfill.js file within a @babel/polyfill npm release. This needs to be included before all your compiled Babel code. You can either prepend it to your compiled code or include it in a <script> before it.

NOTE: Do not require this via browserify etc, use @babel/polyfill.

Details

If you are looking for something that won't modify globals to be used in a tool/library, checkout the transform-runtime plugin. This means you won't be able to use the instance methods mentioned above like Array.prototype.includes.

Note: Depending on what ES2015 methods you actually use, you may not need to use @babel/polyfill or the runtime plugin. You may want to only load the specific polyfills you are using (like Object.assign) or just document that the environment the library is being loaded in should include certain polyfills.

 CLITRANSFORM-RUNTIME →

 

 

출처: <https://babeljs.io/docs/en/babel-polyfill>

 

 

Posted by 철냄비짱
,

창 크기 조절

Front-End 2019. 12. 30. 07:43

 

 

 

샘플 코드 작성시 사용된 주요객체의 프로퍼티와 메서드 

 

 

screen.availWidth, screen.availHeight

실제로 사용할 수 있는 디스플레이의 크기

이 크기에는 데스크톱의 작업 표시줄 등에 의해 사용되는 공간이 제외되어있다. 

 

 

window.​open(url, name, features, replace) 새창을 생성하여 화면에 띄운다.​

url : 새창에서 보여줄 URL을 지정하는 문자열이며 생략 가능. 이 전달인자가 생략되거나 빈문자열이로 지정되면 새창의 화면에는 아무 문서도 출력되지 않는다.

 

name : 새창의 이름, 만약 특정 이름의 창이 이미 열려있는 상태라면, open()은 새창을 생성하지 않고 해당 이름의 창에 대한 참조를 반환한다. 이때 features 전달인자는 무시된다.

 

features : 새 창에 표준 브라우저 창의 어떤 특성들을 보여줄지를 지정하는 문자열이다. 

width, height , left, top, location, menubar, resizable, scrollbars, status

 

replace : 창에 로딩되는 URL이 창의 방문 기록에 새내용을 생성할지 방문 기록의 현재 내용을 대체해야할지 지정하는 불리언 값이면 생략 가능. 이 전달 인자의 값이 true이면, 새기록이 만들어지지 않는다. 이 전달 인자는 이름 붙은 기존 창의 내용을 바꾸는데 사용하기 위해 만들어졌다는점을 명심.

 

window.​moveTo(x, y창을 절대위치로 이동 

window.moveBy(x, y) 창을 상대적인 크기만큼 이동한다.

window.resizeTo(width, height) 창 크기를 지정된 크기로 재조정한다.

window.resizeBy(width, height창 크기를 지정한 양만큼 재조정한다.

 

 

 

열리는 문서에 다음 스크립트를 추가하면 열리는 창을 최대화 시킬수 있다. 

 

      1. <script type="text/javascript">
      2.     self.moveTo(0,0); //창위치
      3.     self.resizeTo(screen.availWidth, screen.availHeight); //창크기
      4. </script>

 

단지 열리는 문서를 바로 실행한다면 위 코드가 있다고 하더라도 바로 적용되지 않을것이다.

 

출처: <https://m.blog.naver.com/PostView.nhn?blogId=javaking75&logNo=220077600650&proxyReferer=https%3A%2F%2Fwww.google.com%2F>

 

 

 

Posted by 철냄비짱
,