3 반응속도 체크 게임
source: categories/study/vue-principle/vue-principle_3.md
3.1 반응속도 체크와 webpack watch
3.2 v-bind 와 vue style
3.3 webpack-dev-server
3.4 반응속도 체크 게임 완성하기
3.5 computed와 v-show, template
- 웹팩 로더의 역할을 잘 알고계셔야 합니다.
- 파일에 자바스크립트가 아닌 것들이 추가될 때마다
rules
에다loader
를 추가해주면 그 부분을 웹팩이 알아서 자바스크립트로 바꿔서 한번에 아웃풋으로 만들어준다..vue
파일은 자바스크립트 파일이 아니지만vue-loader
가vue
파일을 발견할 때마다 자바스크립트 파일로 내부적으로 전환해주기 때문에 한방에 자바스크립트 파일로 합칠 수가 있다.css
,image
,html
등 로더 설정만 해주면 자바스크립트 파일로 합쳐준다.- 어떤 파일이든 파일 하나로 합쳐준다가 웹팩의 장점이다.
1. vue-loader 에러 (vue-loader만으로 vue 안에 style 처리 못한다)
npm i -D vue-style-loader css-loader
# OR
yarn add -D vue-style-loader css-loader
2. webpack에서 loader와 plugins의 차이점은 무엇인가요?
- 로더: 자바스크립트 파일이 아니는 파일들을 자바스크립트 파일로 바꾸어 하나의 파일로 합쳐지게 해준다.
- 플러그인: 부가적인 역할을 수행
- 빌드한 파일을 내보내기 전에 압축할 수도 있고
- html에 자동으로 스크립트 추가해줄 수도 있고
- 아웃풋이 나오기 전에 추가적으로 몇가지 작업을 더 해주는 것이 플러그인
3. vue에서 sass 기능 사용?
yarn add -D sass sass-loader@10
sass-loader
10 버전 설치 이유vue 2.x
에선 11 이상의sass-loader
가 호환되지 않아서- 위와 같이 설치하면 자동으로
vue
에서scss
를 인식 webpack.config.js
에 이미 다 설정되어있기 때문
4. 새로고침마저 webpack이 자동으로 하게하려면?
npm i -D webpack-dev-server
# OR
yarn add -D webpack-dev-server
{
"name": "response-check",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --watch",
"dev": "webpack-dev-server --hot"
},
"author": "",
"license": "ISC",
"dependencies": {
"vue": "2.6.10"
},
"devDependencies": {
"vue-loader": "^15.7.0",
"vue-template-compiler": "2.6.10",
"webpack": "^4.35.2",
"webpack-cli": "^3.3.5"
}
}
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const path = require('path');
// webpack 처리를 할 때 아래 객체를 사용한다.
// entry, module, plugins, output 4가지가 주된 설정, 나머지는 부가적인 설정
module.exports = {
mode: 'development', // 개발중일 땐 development, 배포할 땐 production
devtool: 'eval', // 개발할 땐 eval, 배포할 땐 hidden-source-map
// eval로 하면 웹팩 빌드 속도가 빨라진다.
// 이 모드별로 app.js에 나오는 내용이 달라진다.
resolve: { // 확장자 처리 가능
extensions: ['.js', '.vue'], // 해당 확장자들은 import 할 때 생략 가능
},
entry: {
// app <- 하나로 합쳐질 파일의 이름 app.js
app: path.join(__dirname, 'main.js'),
},
module: { // webpack의 핵심
rules: [ // javascript 파일을 합칠 때 어떤 방식으로 합칠건지를 명시
{
test: /\.vue$/,
use: 'vue-loader', // use: 'vue-loader'라고 작성해도된다.
},
{
test: '/\.css$/',
use: [
'vue-style-loader',
'css-loader',
],
}
],
},
plugins: [ // module 처리 이후 output 으로 내보내기 전에 한번 더 가공해주는 역할
new VueLoaderPlugin(),
],
output: {
filename: '[name].js', // 위에 정의한 app 이라는 이름이 왼쪽 [name]에 매칭되어 들어온다.
path: path.join(__dirname, 'dist'), // output 경로
publicPath: '/dist',
},
}
npm run dev
# OR
yarn dev
5. 계산식은 template 태그 안에 안 넣는 것이 좋다! 그렇게하려면? computed
data
와computed
의 차이점- 그리고
computed
를 사용하는 이유?- 아래 코드에서
result
는 일반 데이터 - 그런 일반 데이터를 가공해서 사용할 때 보통
computed
사용
- 아래 코드에서
computed
를 사용하면 해당 값들이cashing
이 된다.message
값이 바뀌면 해당message
가 들어간template
부분이 다시 재렌더링된다.message
값이 바뀌면 전체template
이 다시 그려지는데, 만약computed
로 넣지않고 계산식으로template
안에 넣으면 해당 계산식도 다시 실행이된다.message
값만 바뀌었는데 다른 부분들도 다시 그려지게된다. 계산식부분.- 이런걸 막기 위해서
computed
로 작성. 캐싱돼서 값을 기억학있어서 다시 계산되지 않음. 시간단축, 속도 빠름. 성능상 중요한 문제. - 데이터들이 조금이라도 가공된다면
computed
를 적용해야 성능상 좋음. - 엄청 중요함
6. v-show, v-if 차이점
v-show
는style="display:none"
이 붙어있다.v-show
는 태그 자체는 존재v-if
는 태그도 존재하지 않음- 보통
v-if
를 많이 사용
7. root 태그에 template 태그 못쓴다.
- 리액트에선
fragment
태그 사용 가능한데.. - 그럼 무조건
div
로 감싸야되나? - 해결 방법이 있긴함. 7강에서 말해줄게. 근데 그 방법 사용 귀찮. 그냥 보통
div
씀
3.1.1 웹팩
- entry: 엔트리로 들어가서
- module (loader(rules)): 모듈을 거쳐서
- plugins: 마지막으로 플러그인 까지 거쳐서
- output: 아웃풋으로 결과물이 나온다.
위와 같은 과정을 거친다.
mode
,devtool
과 같은 부수적인 옵션 말고는 큰 틀에서 달라지는건 없다.- 위 4가지가 가장 중요하다 (entry, module, plugins, output)
3.1.2 반응속도 게임
‘초록색이 되면 클릭하세요.'
- 비동기 코드를 뷰와 같이 쓰는 것을 연습하기 위함
ResponseCheck.vue
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Response Check</title>
</head>
<body>
<div id="root"></div>
<script src="./dist/app.js"></script>
</body>
</html>
<template>
<div>
<div id="screen" :class="state" @click="onClickScreen">{{ message }}</div>
<template v-if="result.length">
<div>평균 시간: {{ average }}ms</div>
<button type="button" @click="onReset">리셋</button>
</template>
</div>
</template>
<script>
// 화면과 관련이 없기 때문에 data 안에 안 넣음
let startTime = 0;
let endTime = 0;
let timeout = null;
export default {
name: 'ResponseCheck',
data() {
return {
result: [],
state: 'waiting',
message: '클릭해서 시작하세요.',
}
},
computed: {
average() {
return this.result.reduce((a, b) => a + b, 0) / this.result.length || 0;
},
},
methods: {
onReset() {
this.result = [];
},
onClickScreen() {
if (this.state === 'waiting') {
this.state = 'ready';
this.message = '초록색이 되면 클릭하세요';
timeout = setTimeout(() => {
this.state = 'now';
this.message = '지금 클릭!';
startTime = new Date();
}, Math.floor(Math.random() * 1000) + 2000); // 2 ~ 3초
} else if (this.state === 'ready') {
clearTimeout(timeout);
this.state = 'waiting';
this.message = '너무 성급하시군요! 초록색이 된 후에 클릭하세요';
} else if (this.state === 'now') {
endTime = new Date();
this.state = 'waiting';
this.message = '클릭해서 시작하세요';
this.result.push(endTime - startTime);
}
}
}
}
</script>
<style scoped>
#screen {
width: 300px;
height: 200px;
text-align: center;
user-select: none;
}
#screen.waiting {
background-color: aqua;
}
#screen.ready {
background-color: red;
color: white;
}
#screen.now {
background-color: greenyellow;
}
</style>
import Vue from 'vue';
import ResponseCheck from './ResponseCheck';
new Vue(ResponseCheck).$mount('#root');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const path = require('path');
// webpack 처리를 할 때 아래 객체를 사용한다.
// entry, module, plugins, output 4가지가 주된 설정, 나머지는 부가적인 설정
module.exports = {
mode: 'development', // 개발중일 땐 development, 배포할 땐 production
devtool: 'eval', // 개발할 땐 eval, 배포할 땐 hidden-source-map
// eval로 하면 웹팩 빌드 속도가 빨라진다.
// 이 모드별로 app.js에 나오는 내용이 달라진다.
resolve: { // 확장자 처리 가능
extensions: ['.js', '.vue'], // 해당 확장자들은 import 할 때 생략 가능
},
entry: {
// app <- 하나로 합쳐질 파일의 이름 app.js
app: path.join(__dirname, 'main.js'),
},
module: { // webpack의 핵심
rules: [ // javascript 파일을 합칠 때 어떤 방식으로 합칠건지를 명시
{
test: /\.vue$/,
use: 'vue-loader', // use: 'vue-loader'라고 작성해도된다.
},
{
test: '/\.css$/',
use: [
'vue-style-loader',
'css-loader',
],
}
],
},
plugins: [ // module 처리 이후 output 으로 내보내기 전에 한번 더 가공해주는 역할
new VueLoaderPlugin(),
],
output: {
filename: '[name].js', // 위에 정의한 app 이라는 이름이 왼쪽 [name]에 매칭되어 들어온다.
path: path.join(__dirname, 'dist'), // output 경로
publicPath: '/dist',
},
}
{
"name": "response-check",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --watch", // --watch 를 붙이면 파일들을 감시한다.
"dev": "webpack-dev-server --hot"
},
"author": "",
"license": "ISC",
"dependencies": {
"vue": "2.6.10"
},
"devDependencies": {
"vue-loader": "^15.7.0",
"vue-template-compiler": "2.6.10",
"webpack": "^4.35.2",
"webpack-cli": "^3.3.5"
}
}