webpack-template-basic
npx degit 디렉토리/저장소명 vue3-webpack-template
npx degit 설치하지 않고도 명령 실행
버전관리 없이 프로젝트 복제 (cf. npx degit과 git clone의 차이)
💎 Vue VSCODE 공식 추천 Extensions 설치
Vue3 패키지 설치
npm i vue@next
npm i -D vue-loader@next vue-style-loader @vue/compiler-sfc
vue-loader@next : Vue3 패키지
vue-style-loader : .vue 파일에서 style을 해석해주는 로더
webpack.config.js 수정
💎 webpack
- 수많은 JS 파일을 하나로 묶어(bundling) 네트워크 비용을 최소화시켜주는 도구 (모듈화)
- 왜 사용하는가
webpack.config.js 설정 참고
// 현재 프로젝트에서 모듈 경로를 찾을 수 있도록 지정.
// 특히 Windows에서 발생하는 오류 해결을 위한 코드.
// 이 코드가 없어도 잘 동작하는 경우 필요치 않음.
const _require = id => require(require.resolve(id, { paths: [require.main.path] }))
// path: NodeJS에서 파일 및 디렉토리 경로 작업을 위한 전역 모듈
const path = _require('path')
const HtmlPlugin = _require('html-webpack-plugin')
const CopyPlugin = _require('copy-webpack-plugin')
const { VueLoaderPlugin } = _require('vue-loader')
module.exports = {
resolve: {
// 경로에서 확장자 생략 설정
extensions: ['.js', '.vue'],
// 경로 별칭 설정
alias: {
'~': path.resolve(__dirname, 'src'),
'assets': path.resolve(__dirname, 'src/assets')
}
},
// 파일을 읽어들이기 시작하는 진입점 설정
entry: './src/main.js',
// 결과물(번들)을 반환하는 설정
output: {
// 주석은 기본값!, `__dirname`은 현재 파일의 위치를 알려주는 NodeJS 전역 변수
// path: path.resolve(__dirname, 'dist'),
// filename: 'main.js',
clean: true
},
// 모듈 처리 방식을 설정
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.s?css$/,
use: [
// 순서 중요!
'vue-style-loader',
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/, // 제외할 경로
use: [
'babel-loader'
]
},
{
// 파일 로더 설정 규칙
test: /\.(png|jpe?g|gif|webp)$/,
use: 'file-loader'
}
]
},
// 번들링 후 결과물의 처리 방식 등 다양한 플러그인들을 설정
plugins: [
new HtmlPlugin({
template: './index.html'
}),
new CopyPlugin({
patterns: [
{ from: 'static' }
]
}),
new VueLoaderPlugin()
],
// 개발 서버 옵션
devServer: {
host: 'localhost',
port: 8080,
hot: true
}
}
src/App.vue
<template>
<h1>{{ message }}</h1>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!!!'
}
}
}
</script>
src/main.js
// CDN mode
import Vue from 'vue'
import App from './App.vue'
Vue.createApp(App).mount('#app')
// CLI mode
import { createApp } from 'vue' // 객체구조분해를 통해 바로 createApp 가져올 수 있음
import App from './App.vue'
createApp(App).mount('#app')
App.vue 파일이 프로젝트의 시작이 될 수 있도록 main.js에 import
root: index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webpack project!</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.1/reset.min.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
div id="app"으로 프로젝트가 동작할 수 있는 구조가 됨
npm run dev
8080 포트로 프로젝트 열림
npm i -D file-loader
(개발의존성으로) 특정한 파일을 읽어서 브라우저에 출력해주는 로더 설치한 후
위에 webpack.config.js을 참조하여 파일로더 설정, 경로 별칭 설정 추가
src/components/HelloWorld.vue
이미지 삽입하기
<template>
// 설정한 경로 별칭 ~
<img src="~assets/image.png" alt="productuidev" />
</template>
src/App.vue
HelloWorld 컴포넌트 불러오기
<template>
<HelloWorld /> // 컴포넌트 삽입
</template>
<script>
// 설정한 경로 별칭 ~ 으로 (상대경로)
import HelloWorld from '~/components/HelloWorld'
export default {
components: {
HelloWorld
},
data() {
return {
message: 'Hello Vue!'
}
}
}
</script>
npm i -D eslint eslint-plugin-vue babel-eslint
module.exports = {
// 브라우저와 node에서 동작하는 전역 개념 코드 검사 규칙 설정
env: {
browser: true,
node: true
},
// Vue와 JavaScript 코드 검사 규칙 설정
extends: [
// Vue (Lv2로 설정)
// 'plugin:vue/vue3-essential', // Lv1
'plugin:vue/vue3-strongly-recommended', // Lv2
// 'plugin:vue/vue3-recommended', // Lv3
// JavaScript
'eslint:recommended'
],
// 코드 분석기 (구문 분석)
parserOptions: {
parser: 'babel-eslint' // es6 > es5
},
// extends에서 기본적인 규칙을 설정한 경우 rules를 별도로 설정하지 않아도 됨
// 예외 규칙이 있다면 추가
rules: {
}
}
💎 ESLint Plugin
- eslint-plugin-vue 관련 User Guide
- eslint 관련 Available rules
ㄴ Lv2로 설정한 경우 Priority B: Strongly Recommended의 규칙에 따라 코드 작성하도록 가이드됨
ESlint를 통해 규칙(컨벤션)을 설정할 수 있고, 여러명이 작성하는 코드일 경우
팀에서 사용할 경우 합의하여 설정을 변경하여 사용도 가능하다.
💎 ESLint
ESLint는 코드를 정적으로 분석하여 문제를 빠르게 찾습니다. 대부분의 텍스트 편집기에 내장되어 있으며 지속적 통합 파이프라인의 일부로 ESLint를 실행할 수 있습니다.
Rules권장되는 코드 규칙을 협업 시 합의하여 설정 가능 (단, 절대적인 개념은 아님)
💎 ESLint + Prettier
- 코딩 컨벤션을 사용하는 이유
- ESLint, Prettier Setting, 헤매지 말고 정확히 알고 설정하자. - 보통 ESLint + Prettier 조합
- ESLint(포매팅+문법수정) + Prettier(포매팅 특화)
1. <YourComponent></YourComponent>
2. <YourComponent/> (self-closing)
{
"vue/html-self-closing": ["error", {
"html": {
"void": "never",
"normal": "always",
"component": "always"
},
"svg": "always",
"math": "always"
}]
}
💎 eslint 규칙으로 코드 자동 수정
VSCODE > F1 > Preferences : Open Settings (JSON) 설정 변경
"editor.codeActionsOnSave": { "source.fixAll.eslint": true, },
💎 template 내 에러 해결 참고
컴포넌트 작성 시 template나 작성한 tag에 빨간줄(에러) 뜰 경우 해결 방법
- [vue3] vue/no-multiple-template-root 오류
- VSCODE > F1 > Preferences : Open Settings (JSON) 설정 변경
"vetur.validation.template": false, "vetur.validation.script": false, "vetur.validation.style": false,
- .eslintrc의 rules 추가
rules: { "vue/no-multiple-template-root": "off", "vue/valid-template-root": "off", }
완성한 Vue3 템플릿을 npx degit 하여 새로운 프로젝트 복제하여 생성
.vue 확장자를 사용하는 단일 컴포넌트
현재 템플릿에서는 SCSS 설정도 추가되어 있음 (webpack.config.js)
count라는 데이터가 변경되면 브라우저가 갱신된다 (모던 프론트엔드 프레임워크의 핵심)
<template>
<!-- h1을 클릭하면 함수 실행 -->
<h1 @click="increase">
{{ count }}
</h1>
</template>
<script>
export default {
data() { // data 정의
return {
count: 0 // 초기값 지정
}
},
methods: { // methods
increase() { // function
this.count += 1 // this = script 전체, count에 접근하여 함수가 실행되면 1씩 증가
}
}
}
</script>
<style>
h1 { font-size:50px; color:royalblue; }
</style>
- v- : Directive (디렉티브)
- v-if : 조건문
- v-for : 반복문
<template>
<!-- h1을 클릭하면(onClick) 함수 실행 -->
<h1 @click="increase">
{{ count }}
</h1>
<!-- v-if 조건문 -->
<div v-if="count > 4">
4보다 큽니다!
</div>
<ul>
<!-- v-for 반복문 -->
<!-- fruit in fruits : fruits 배열 데이터 반복, fruit라는 변수에 담기 -->
<!-- 해당 data가 고유한지 증명 :key="fruit" -->
<li
v-for="fruit in fruits"
:key="fruit">
{{ fruit }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
count: 0,
fruits: ['Apple', 'Banana', 'Cherry'], // 배열 추가
}
},
methods: {
increase() {
this.count += 1
}
}
}
</script>
<style lang="scss">/* scss 사용 시 lang 설정 */
h1 { font-size:50px; color:royalblue; }
ul {
li { font-size:40px; }
}
</style>
참고자료
src/components/Fruit.vue
<template>
<li>{{ name }}</li> <!-- 데이터 출력 -->
</template>
<script>
export default {
props: {
name: {
type: String, // 데이터 타입
default: '' // 데이터가 들어오지 않으면 빈 문자
}
}
}
</script>
<style lang="scss">
</style>
src/App.vue
Fruit 컴포넌트 import
<template>
<h1 @click="increase">
{{ count }}
</h1>
<div v-if="count > 4">
4보다 큽니다!
</div>
<ul>
<Fruit
v-for="fruit in fruits"
:key="fruit"
:name="fruit">
{{ fruit }}
</Fruit>
</ul>
</template>
<script>
import Fruit from '~/components/Fruit'
export default {
components: {
Fruit: Fruit // 같으면 :Fruit이 생략가능
},
data() {
return {
count: 0,
fruits: ['Apple', 'Banana', 'Cherry'],
}
},
methods: {
increase() {
this.count += 1
}
}
}
</script>
<style lang="scss">
h1 { font-size:50px; color:royalblue; }
ul {
li { font-size:40px; }
}
</style>
<style scoped lang="scss">
h1 { color:red !important; }
</style>
scoped : 다른 컴포넌트에는 영향을 미치지 않고, 현재 컴포넌트에만 영향을 줌 (유효범위를 잡는 속성)
이 속성을 활용하면 컴포넌트 내부에 스타일을 복잡하게 작성하지 않더라도 손쉽게 관리할 수 있음
참고자료
💬 모던 프론트엔드 개발을 하려면... 설치와 설정이 50% 이상
이므로
처음 프로젝트 시작 시 알 수 없는 에러로 다소 지연이 되더라도
마음의 여유
를 갖고 시작하지 않으면 초반부에 에너지를 다 써버려서 지칠 수 있다.
(🔑 모던 프론트엔드 개발 리빙포인트 : 구글링
을 하면 개발이 수월해진다.)
💬 패스트캠퍼스 초격차 패키지 챕터 순서상 Vue.js가 먼저였는데 작년 말~올해 초 의욕이 너무 앞선 나머지 React부터 들었었는데...
- 작년 리액트가 전자정부 표준프레임워크에 추가됐다는 소식 (공공기관에도 변화의 바람이..?)
- 대부분의 디자인시스템은 리액트
- 대세는 리액트라는 분위기
ㄴ Declarative UI
ㄴ 선언적 렌더링
ㄴ 선언형 UI 프로그래밍을 사용하는 이유
이 강의 들으니 Vue부터 들었으면 이해가 더 빨랐겠다
는 생각..(SPA 비교 시 대부분 리액트가 러닝커브가 높다고도 했는데, Vue 강의 들어보니 리액트랑 비슷하면서도 전반적인 방식의 흐름을 알 거 같다) 물론 한 입 크기로 먹는 리액트를 듣지 않았다면 힘들었겠지..(그 강의는 리액트 강의지만 진짜 백미는 자바스크립트를 정말 쉽게 알려준다 😀) 그리고 대부분 리액트를 쓰는 프론트엔드 개발자 모집을 보면 리액트보다 자바스크립트를 잘하는 게 더 중요한 거 같고... 결국 기본은 자바스크립트
💬 박영웅 강사님이 설명이 쉬워서 찾아보니 타입스크립트 강의도 있어서 구름EDU도 가입했다.
문서로 된 강의인데 책같아서 짬짬히 보는 중..
💬 이 강의를 들으면서 올해 초 실습해보고 싶었던 것을 조금씩 할 수 있을 거 같다.. 백엔드 몰라도 혼자 서비스 만들 수 있어요 (퇴근하고 천천히 학습하다보니 무려 반년이나 걸렸군 😳 나름 다 계획이 있었으나..)