ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Vue.js 사용하기 -2 ( 환경 설정 하기 )
    JavaScript/Vue.js 2019. 1. 31. 17:14
    반응형

    환경 설정 시작 !! 


     이제부터 적게 될 이하 내용들은 내가 직접 환경을 구축한게 아니라 먼저 Vue.js 개발 환경을 구축한 팀원에게 도움을 받아 팀원이 구축한것을 내 프로젝트에 적용하기위해 내가 진행한것을 그대로 기록한것이다.  나중엔 내 스스로 멋지게 Vue.js 프로젝트를 만드리라 ! 



    https://nodejs.org/en/


     위 사이트에서 npm 을 다운받아 설치한다. 팀원의 조언으로는 zip 버전을 받아서 설치하고 직접 환경설정을 하는것을 추천했지만 난 자동 설치를 믿어 보기로하고 ( 청개구리 심보 ! ) 윈도우 설치 버전을 설정했다 ! 남자라면 무조건 최신 버전 !!! 


    설치가 완료 되면 자동으로 환경설정이 되기 때문에 윈도우 cmd 창에서 어디서나 npm 명령어를 쳐보면 npn 동작이 된다는걸 확인이 가능하다. 


    그리고 spring boot 프로젝트를 하나 만들었다. 당연 Intellij 에서 자동 프로젝트 생성으로 편하게 만들고 그다음 webapp 폴더를 프로젝트에 생성해주자 



     폴더가 생성 됬다면 그다음 폴더 세팅이 필요하다. 




    - build : webpack 을 위한 설정들이 들어가 있다. 개발환경일때 실제 서비스 환경일때 구분해서 구성도 가능하다. 

    - dist : 실제 번들링된 js 들이 모이게 되는 곳이다. 왜 이곳에 이게 있냐면 지금 구축한 환경은 이곳에 개발/테스트 중에는 여기 모두 모아 두었다가 상용 빌드 명령을 내리면 모아둔것을 실제 프로젝트 폴더로 복사하는 구성이기 때문에 테스트 시에는 이곳에 모아진다. 

       안에는 css 폴더가 있고  그안에 CSS 가 포함되어 있다. 

    - node_modules : npm 에서 플러그인을 받으면 이곳에 모이게 된다. 옵션에 따라서 실제로 이곳에 저장되지 않게 하기도 하는데 난 다 저장하도록 했다. 다 저장하게 했더니 나중에 프로젝트 복사할일이 있었는데 10GB 용량이 나오는거보고 플러그인 추가를 남발 안하게 됬다.

    - src : 실제 vue 파일들이 있는 곳이다. 이곳에 파일들을 생성하면 될거 같다. 

    - test : webpack 에서 제공하는 테스트 서버를 사용하고 있다. 그래서 그 테스트 서버에서 인식할 리로스들을 위해 이안에는 호출될 html 과 css ( 위와 동일한 파일이야 함 ) 들이 들어 있다. 개발시에는 html 을 여기다 추가해놓고 나중에 상용버전으로 빌드시에는 이곳의 html 을 사용 프로젝트 안으로 옴겨줘야한다. 


    Webpack + Babel 환경 설정 


     일단 webapp 폴더안에 아래 세가지 파일을 만들어 줘야 한다.  


     package.json

    {
    "name": "webapp-template",
    "version": "0.0.1",
    "description": "vue project",
    "main": "index.js",
    "scripts": {
    "test": "npm run build:development && npx cross-env NODE_ENV=development SERVER_ENV=development TARGET_ENV=all webpack-dev-server --mode production --config ./build/webpack.config.dev.js --hot --inline",
    "build:development": "npx cross-env NODE_ENV=development SERVER_ENV=production TARGET_ENV=all webpack --mode production --config ./build/webpack.config.dev.js --progress --hide-modules",
    "build": "npx cross-env NODE_ENV=production SERVER_ENV=production TARGET_ENV=all webpack --mode production --config ./build/webpack.config.prod.js --progress --hide-modules",
    "build:debug": "npx cross-env NODE_ENV=development SERVER_ENV=production TARGET_ENV=all webpack --mode production --config ./build/webpack.config.prod.js --progress --hide-modules --profile --json > stats.json"
    },
    "author": "",
    "license": "MIT",
    "dependencies": {
    "@kazupon/vue-i18n-loader": "^0.3.0",
    "axios": "^0.18.0",
    "babel": "^6.23.0",
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.6.0",
    "babel-preset-stage-3": "^6.24.1",
    "billboard": "^1.0.0",
    "billboard.js": "^1.5.1",
    "copy-webpack-plugin": "^4.5.2",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.11",
    "filepond": "^3.4.0",
    "filepond-plugin-file-validate-type": "^1.2.0",
    "junk": "^2.1.0",
    "puetify": "^0.3.26",
    "puetify-chart": "0.0.3",
    "vue": "^2.5.13",
    "vue-cli": "^2.9.3",
    "vue-country-flag": "^1.0.1",
    "vue-filepond": "^4.0.1",
    "vue-i18n": "^7.8.0",
    "vue-loader": "^14.2.2",
    "vue-monthly-picker": "^0.2.5",
    "vue-template-compiler": "^2.4.4",
    "vue2-timepicker": "^0.1.4",
    "vuejs-datepicker": "^1.5.2",
    "vuex": "^3.0.1",
    "webpack": "^4.5.0",
    "webpack-bundle-analyzer": "^2.13.1",
    "webpack-cli": "^2.0.14",
    "webpack-dev-server": "^3.1.1",
    "xlsx": "^0.14.0"
    }
    }

    npm install 옵션에서 --save 를 주면 denpencies 안에 자동으로 내용이 추가 되는거 같다.  필요 없다면 --save-dev 옵션을 주는걸 추천한다. 


     package-lock.json

     이녀석이 처음에 잘이해가 안갔는데 이녀석은 mode_modules 나 package.json 이 수정되면 자동 생성 된다. 내용만 봐서는 이것이 왜 생기는지 왜 필요한지는 잘몰랐는데 내가 이해하기에는 dependency 에 대한 수정 시점의 정보를 가지고 있는것으로 보인다. 아마 dependency에 문제가 생길경우 이것을 이용해서 롤백에 이용 되지 않나 싶다. 그리고 추가적으로 확인한건데 node_modules 없이 배포하는 상황이 생기면 꼭 필요하다고 한다. 

    ( https://docs.npmjs.com/files/package-lock.json) 


     .babelrc 

    {
    "presets": [
    ["env", { "modules": false }],
    "stage-3"
    ]
    }

     javascript 스펙을 총 5개로 구분한다고 한다. 그리고 babel 은 이 stage 에대해서 preset 을 제공한다고 한다. preset 은 0~4까지 있고 stage-4 일경우 babel-preset-es2015를 의미한다고 한다.  babel 이 트랜스파일링을 하기 위해선 이 설정을 해줘야 하는거 같다. 


    그리고 이 설정 파일들을 사용할 build 환경 설정 파일을 만들어 줘야 한다. 


    file-utils.js 


     번들링된 js 파일들을 복사 이동 수정 등을 하기 위한 단순한 Utillity js 이다 개인적으로 만들어 써도 될거 같다. 

    'use strict'

    const fs = require('fs')
    const junk = require('junk');
    // const path = require('path')

    function getDirectories (path) {
    let list = []
    fs.readdirSync(path).filter(function (file) {
    if(fs.statSync(`${path}/${file}`).isDirectory()) {
    console.log("Build Target App: " + file);
    list.push({ path: '', app: file })
    }
    })

    return list;
    }

    function getAllDirectories (path) {
    let list = []
    fs.readdirSync(path).filter(function (file) {
    if(junk.is(file) === false) {
    fs.readdirSync(`${path}/${file}`).filter(function (file2) {
    let endPath = `${path}/${file}/${file2}`
    if(fs.statSync(`${path}/${file}/${file2}`).isDirectory()) {
    console.log("Build Target App: " + file2);
    list.push({ path: file, app: file2 });
    }
    });
    }
    })
    return list;
    }

    exports.generateWebpackEntries = function (viewPath, target, scriptFilename) {
    // let generateWebpackEntries = function (viewPath, target, scriptFilename) {
    let entries = {}
    let directories = []
    let targetPath = ``

    if(target === "all") {
    targetPath = viewPath
    directories = getAllDirectories(targetPath)
    } else {
    targetPath = `${viewPath}/${target}`
    directories = getDirectories(targetPath)
    }

    directories.forEach(function (pathAndApp) {
    let path = `${targetPath}${pathAndApp.path === '' ? '' : '/' + pathAndApp.path }/${pathAndApp.app}/${scriptFilename}`
    if(fs.existsSync(path)){
    entries[pathAndApp.app] = path
    }
    })

    return entries
    }
    // const rootPath = path.resolve(__dirname, '..')
    // console.dir(generateWebpackEntries(rootPath + "/src/components", "all", "index.js"))


    webpack.config.dev.js 


     webapck 개발 환경시 사용될 설정 값들이다 설정중에는 webpack-dev-server 사용을 위한 설정이 있다.  port 뿐만 아니라 proxy 설정도 있다. 

    기본적으로 css, vue , babel 등 설정 값들을 지정할수 있다.  만들어진것을 사용하다보니 아직 다 파악 안된 값들이 많다. 나중에 추가적으로 더 뜯어 봐야할거 같다. 

    const path = require('path')
    const webpack = require('webpack')
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
    const fileUtil = require("./file-util")
    // const CopyWebpackPlugin = require('copy-webpack-plugin')
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

    var PACKAGE = require('./../package.json');
    var banner = `${PACKAGE.name} v${PACKAGE.version}
    (c) ${new Date().getFullYear()} ${PACKAGE.author}
    Released under the ${PACKAGE.license} License.`;

    const rootPath = path.resolve(__dirname, '..')
    const nodeEnvironment = process.env.NODE_ENV || 'development'
    const serverEnvironment = process.env.SERVER_ENV || 'development'
    const target = process.env.TARGET_ENV || 'all'

    let entry = fileUtil.generateWebpackEntries( rootPath + '/src/components', process.env.TARGET_ENV, "index.js");

    module.exports = {
    entry: entry,
    output: {
    // path: rootPath + '/dist/static/js',
    // path: rootPath + '/test/resource/js', // for test
    // publicPath: rootPath + '/test/resource/js',
    publicPath:"http://localhost:9000/js/",
    filename: '[name].bundle.js'
    },

    module: {
    rules: [
    {
    test: /\.css$/,
    use: [
    'vue-style-loader',
    'css-loader'
    ],
    }, {
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
    hotReload: true, // disables Hot Reload
    loaders: {
    i18n: '@kazupon/vue-i18n-loader'
    }
    }
    },
    {
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/
    },
    {
    test: /\.(png|jpg|gif)$/,
    use: [
    {
    loader: 'file-loader',
    options: {}
    }
    ]
    }
    ]
    },
    resolve: {
    alias: {
    '@': rootPath + "/src"
    },
    extensions: ['.js', '.vue', '.json']
    },
    plugins: [
    // new CopyWebpackPlugin([
    // {
    // from: '**/*',
    // to: path.resolve(rootPath, '../resources/'),
    // context: rootPath + '/dist'
    // }
    // ]),
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: `'${nodeEnvironment}'`,
    SERVER_ENV: `'${serverEnvironment}'`
    }
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.BannerPlugin(banner)
    // new BundleAnalyzerPlugin()
    ],
    optimization: {
    minimizer: [
    // we specify a custom UglifyJsPlugin here to get source maps in production
    new UglifyJsPlugin({
    cache: true,
    parallel: true,
    uglifyOptions: {
    compress: false,
    ecma: 6,
    mangle: true,
    comments:false
    },
    sourceMap: true
    })
    ],
    splitChunks: {
    cacheGroups: {
    commons: {
    test: /[\\/]node_modules[\\/]/,
    name: "vendors",
    enforce: true,
    chunks: "all"
    }
    }
    }
    },
    // webpack-dev-server 설정
    devServer: {
    // 기본 html 파일 위치
    contentBase: rootPath + '/test/resource',
    // path에서 .html 생략하기 위한 설정
    proxy: {

    '/backoffice/**' : {
    target: 'http://localhost:8443',
    changeOrigin : true
    }

    },
    watchContentBase: true,
    host: "localhost",
    historyApiFallback: true,
    compress: true,
    hot: true,
    inline: true,
    port:9000,
    },
    devtool: '#source-map'
    };


    webpack.config.prodjs

     

     위에 내용과 거의 비슷하지만 상용버전으로 빌드 할때의 설정값이기 때문에 약간씩 다른 부분들이 있다.  경로라든가 일부 설정값등이 다르다 .

    const path = require('path')
    const webpack = require('webpack')
    const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
    const fileUtil = require("./file-util")
    // const CopyWebpackPlugin = require('copy-webpack-plugin')
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

    var PACKAGE = require('./../package.json');
    var banner = `${PACKAGE.name} v${PACKAGE.version}
    (c) ${new Date().getFullYear()} ${PACKAGE.author}
    Released under the ${PACKAGE.license} License.`;

    const rootPath = path.resolve(__dirname, '..')
    const outputPath = path.resolve(rootPath, '../resources')
    const nodeEnvironment = process.env.NODE_ENV || 'development'
    const serverEnvironment = process.env.SERVER_ENV || 'development'
    const target = process.env.TARGET_ENV || 'all'

    let entry = fileUtil.generateWebpackEntries( rootPath + '/src/components', process.env.TARGET_ENV, "index.js");


    module.exports = {
    entry: entry,
    output: {
    path: outputPath + '/static/js',
    // path: rootPath + '/test/resource/js', // for test
    filename: '[name].bundle.js'
    },

    module: {
    rules: [
    {
    test: /\.css$/,
    use: [
    'vue-style-loader',
    'css-loader'
    ],
    }, {
    test: /\.vue$/,
    loader: 'vue-loader',
    options: {
    loaders: {
    i18n: '@kazupon/vue-i18n-loader'
    }
    }
    },
    {
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/
    },
    {
    test: /\.(png|jpg|gif)$/,
    use: [
    {
    loader: 'file-loader',
    options: {}
    }
    ]
    }
    ]
    },
    resolve: {
    alias: {
    '@': rootPath + "/src"
    },
    extensions: ['.js', '.vue', '.json']
    },
    plugins: [
    // new CopyWebpackPlugin([
    // {
    // from: '**/*',
    // to: path.resolve(rootPath, '../resources/'),
    // context: rootPath + '/dist'
    // }
    // ]),
    new webpack.DefinePlugin({
    'process.env': {
    NODE_ENV: `'${nodeEnvironment}'`,
    SERVER_ENV: `'${serverEnvironment}'`
    }
    }),
    new webpack.BannerPlugin(banner)
    // new BundleAnalyzerPlugin()
    ],
    optimization: {
    minimizer: [
    // we specify a custom UglifyJsPlugin here to get source maps in production
    new UglifyJsPlugin({
    cache: true,
    parallel: true,
    uglifyOptions: {
    compress: false,
    ecma: 6,
    mangle: true,
    comments:false
    },
    sourceMap: true
    })
    ],
    splitChunks: {
    cacheGroups: {
    commons: {
    test: /[\\/]node_modules[\\/]/,
    name: "vendors",
    enforce: true,
    chunks: "all"
    }
    }
    }
    },
    // webpack-dev-server 설정
    devServer: {
    // 기본 html 파일 위치
    contentBase: rootPath + '/test/resource',
    // path에서 .html 생략하기 위한 설정
    proxy: {
    '/applist' : {
    target: 'http://localhost:17070',
    changeOrigin : true
    }
    },
    host: "localhost",
    historyApiFallback: true,
    // secure: false,
    hot: false,
    port:9000,
    },
    devtool: '#source-map'
    };

    이제 개발환경구성이 어느정도 된거 같다. 미리 자신이 더써야할 플러그인이 있다면 npm install --save [ 플러그인 명 ] 으로 세팅해놓고 사용하는게 좋을거 같다.  지금 이구성을 하면 실제 한국 vue.js 커뮤니티에서 가이드한것과는 좀 다른 구성이 될거 같고 내가 슬쩍봤던 몇 vue.js 책들과는 좀 다른 형식으로 구현이 될거 같다. ( 책을 서점에서 좀더 다 볼걸 그랬다... ) 물론 같다면 다행이다. 


    간단하게 vue.js 파일을 생성하고 index.js , html 파일을 작성후 webpack-dev-server 구동하여 확인이 잘된다면 설정인 걱정끝! 이젠 잘 만들고 빌드해서 Spring boot 에 붙이면 된다. 


     끝으로 개발환경을 구성해준 조영진 선임에게 감사합니다 !! 잘쓸게요 !! 

    반응형
Designed by Tistory.