본문 바로가기
Programming/Javascript

Vue 프로젝트 만들기 - with Webpack Template

by Wilkyway 2021. 5. 21.
반응형

 

1. 프로젝트 구성 (Template Download)

  /node_modules

  .babelrc.js

  .gitignore

  .postcssrc.js

  .babelrc.js

  .package-lock.json

  .package.json

  .webpack.config.js

 

  index.html

  /src/App.vue

  /src/main.js

  /src/assets/logo.jpg

    ㄴ/components/HelloWorld.vue

  /scss/main.scss

  /static/fabicon.ico

 

2. Package 설치

   npm i vue@next

   npm i -D vue-loader@next vue-style-loader @vue/compiler-sfc

   npm i -D file-loader

   npm i -D eslint eslint-plugin-vue babel-eslint

 

3. webpack.config.js 수정

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'], // 추가: vue 확장자 자동 인식
        alias: {
            '~': path.resolve(__dirname, 'src'),
            'assets': path.resolve(__dirname, 'src/assets')
        }
    }, 
    
	// 파일을 읽어들이기 시작하는 진입점 설정
    entry: './src/main.js',	// 엔트리 파일 인식. 번들링 결과물에 포함시킴
    output: {
    	// 현재는 path와 filename이 기본값과 동일하므로 생략 가능
    	// path: path.resolve(__dirname, 'dist'),	//절대경로 필요, 폴더명
        // filename: 'main.js',
        clean: true	// 새로 build 시 기존 필요없는 파일/폴더 삭제
    },
    
   module: {
        rules: [
            {
                test: /\.vue$/,     // 추가
                use: 'vue-loader'   // 추가
            },
            {
                test: /\.s?css$/,	// .css 또는 scss로 끝나는 파일 인식
                use: [
                    'vue-style-loader', // 추가
                    'style-loader',	// html에 삽입해주는 역할
                    'css-loader',	// 먼저 해석됨. js에서 css에서 인식하도록 해석
                    'postcss-loader',	// 공급업체 접두사 적용
                    'sass-loader'	// 가장 먼저 해석됨. js에서 scss에서 인식하도록 해석
                ]
            },
            { 
                test:/\.js$/,
                use: [
                    'babel-loader'  //바벨이 적용될 수 있도록 설정
                ]
            },
            {
                test:/\.(png|jpe?g|gif|webp)$/,
                use: 'file-loader'
            }        
        ]
    },
    
    plugins:[
    	new HtmlPlugin({
        	template: './index.html'	// 번들링 결과물에 html을 포함시킴
        }),
        new CopyPlugin({
        	patterns: [
            	{ from: 'static' }		// 번들링 결과물에 스태틱 파일을 포함시킴
            ]
        }),
        new VueLoaderPlugin()   // 추가
    ],
    
    devServer:{
    	host: 'localhost'	// 서버 호스팅 주소
    }
}

4. index.html

<!DOCTYPE html>
<html lang="en">
<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>Document</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>

5. main.js

import { createApp } from 'vue'
import App from './App'

createApp(App).mount('#app')

6. App.vue

<template>
  <h1>{{ message }}</h1>
  <HelloWorld />
</template>

<script>
import HelloWorld from '~/components/HelloWorld'

export default {
  components:{
    HelloWorld
  },
  data() {
    return{
      message: 'Hello Vue!!!'
    }
  }
}
</script>

7. HelloWorld.vue

<template>
  <img src="~assets/background.png" alt="logo">
</template>

<style>
  img {
    width: 600px;
    border-radius: 10px;
  }
</style>

 

8. eslint 설정(.eslintrc.js)

module.exports = {
  env:{
    browser: true,
    node: true
  },
  extends:[
    // vue
    //'plugin:vue/vue3-essential',
    'plugin:vue/vue3-strongly-recommended',
    //'plugin:vue/vue3-recommended'
    //js
    'eslint:recommended'
  ],
  parserOptions:{
    parser: 'babel-eslint'
  },
  rules:[
    "vue/html-closing-bracket-newline": ["error", {
      "singleline": "never",
      "multiline": "never"
     }],
    "vue/html-self-closing": ["error", {
      "html": {
        "void": "always",
        "normal": "never",
        "component": "always"
      },
      "svg": "always",
      "math": "always"
    }],
    "vue/html-indent": ["error", "tab", {
        attribute: 1,
        baseIndent: 1,
        closeBracket: 0,
        alignAttributesVertically: true,
        ignores: [],
      }],
  ]
}

 

9. package.json

{
  "name": "11_webpack3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --mode development",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.3",
    "@babel/plugin-transform-runtime": "^7.14.3",
    "@babel/preset-env": "^7.14.2",
    "@vue/compiler-sfc": "^3.0.11",
    "autoprefixer": "^10.2.5",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^8.2.2",
    "copy-webpack-plugin": "^8.1.1",
    "css-loader": "^5.2.5",
    "eslint": "^7.27.0",
    "eslint-plugin-vue": "^7.9.0",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.3.1",
    "postcss": "^8.2.15",
    "postcss-loader": "^5.3.0",
    "sass": "^1.32.13",
    "sass-loader": "^11.1.1",
    "style-loader": "^2.0.0",
    "vue-loader": "^16.2.0",
    "vue-style-loader": "^4.1.3",
    "webpack": "^5.37.1",
    "webpack-cli": "^4.7.0",
    "webpack-dev-server": "^4.0.0-beta.3"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ],
  "dependencies": {
    "vue": "^3.0.11"
  }
}
반응형

댓글