Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

라라벨 5.4에서 LaravelMix(구 Elixir) 사용 #11

Open
appkr opened this issue Apr 12, 2017 · 1 comment

Comments

Projects
None yet
2 participants
@appkr
Copy link
Owner

commented Apr 12, 2017

2017/04/29에 내용을 수정했습니다.

  1. version() API는 적용하지 않았습니다.
  2. 빌드 레시피를 변경했습니다.

변경 전에 이 문서를 따라하셨던 분이라면, 아래 두 개의 파일의 변경 사항을 반영해 주세요.

  • resources/views/layouts/app.blade.php
  • webpack.mix.js

라라벨 5.4부터 "Elixir"라는 이름이 컴퓨터 랭귀지 "Elixir"와 헷갈린다는 이유로 "Mix"로 이름이 변경되고, 빌드 시스템도 gulp에서 webpack으로 완전히 변경되었습니다. 라라벨 5.4로 학습하시는 분들은 다음 절차대로 시도해 보시기 바랍니다.

프로젝트를 처음 시작해서 package.json에 아무것도 없는 상태로 가정합니다. 저도 이렇게 해서 테스트했습니다.

~ $ laravel new laravel-mix-test && cd laravel-mix-test
# ...

~/laravel-mix-test $ php artisan --version
# Laravel Framework 5.4.19

Node.js 패키지를 설치하고, 프런트엔드 에셋 빌드가 잘 작동하는 지 확인합니다.

~/laravel-mix-test $ npm install
# ...

~/laravel-mix-test $ npm run dev
# ...

책에서 사용한 Node.js 패키지들을 설치합니다. vuevue-resource는 버전을 지정해야 합니다.

~/laravel-mix-test $ npm install autosize bootstrap-sass dropzone \
font-awesome highlightjs jquery-tabby marked select2 select2-bootstrap-css \
vue@1.0.26 vue-resource@0.9.3 --save-dev
# ...

설치 후에 package.json 파일에 설치한 버전이 잘 기록되었나 확인합니다.

{
  "private": true,
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch-poll": "npm run watch -- --watch-poll",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  },
  "devDependencies": {
    "autosize": "^3.0.20",
    "axios": "^0.15.3",
    "bootstrap-sass": "^3.3.7",
    "cross-env": "^3.2.3",
    "dropzone": "^4.3.0",
    "font-awesome": "^4.7.0",
    "highlightjs": "^9.10.0",
    "jquery": "^3.1.1",
    "jquery-tabby": "^0.13.1",
    "laravel-mix": "0.*",
    "lodash": "^4.17.4",
    "marked": "^0.3.6",
    "select2": "^4.0.3",
    "select2-bootstrap-css": "^1.4.6",
    "vue": "^1.0.26",
    "vue-resource": "^0.9.3"
  }
}

webpack.mix.js 파일을 수정합니다.

const { mix } = require('laravel-mix');

mix.sass('resources/assets/sass/app.scss', 'public/css');

mix
  .scripts('node_modules/highlightjs/highlight.pack.js', 'public/js/temp.js')
  .js('resources/assets/js/app.js', 'public/js')
  .scripts([
    'node_modules/highlightjs/highlight.pack.js',
    'public/js/app.js',
    'node_modules/select2/dist/js/select2.js',
    'node_modules/dropzone/dist/dropzone.js',
    'node_modules/marked/lib/marked.js',
    'node_modules/jquery-tabby/jquery.textarea.js',
    'node_modules/autosize/dist/autosize.js',
    'resources/assets/js/forum.js'
  ], 'public/js/app.js');

mix.copy('node_modules/font-awesome/fonts', 'public/fonts');

mix.version() API를 이용한 캐시 버스팅을 이용하지 않으므로, 마스터 레이아웃은 다음과 같은 모양이어야 합니다.

resources/views/layouts/app.blade.php 파일을 수정합니다.

-<link href="{{ elixir('css/app.css') }}" rel="stylesheet">
+<link href="/css/app.css" rel="stylesheet">

-<div class="container">
+<div class="container" id="app"> 
<!--//...--></div>

-<script src="{{ elixir('js/app.js') }}"></script>
+<script src="/js/app.js"></script>

resources/assets/js/app.js 파일을 수정합니다.

require('./bootstrap');
window.Vue = require('vue');

// Vue.component('example', require('./components/Example.vue'));

const app = new Vue({
  el: '#app',

  ready() {
    hljs.initHighlightingOnLoad();
    this.removeFlashMessages();
    this.setJqueryAjaxHeaders();
    this.initBackToTopButton();
  },

  methods: {
    removeFlashMessages() {
      if ($('.alert')) {
        $('.alert').delay(5000).fadeOut();
      }
    },

    setJqueryAjaxHeaders() {
      $.ajaxSetup({
        headers: {
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
      });
    },

    initBackToTopButton() {
      $('#back-to-top').on('click', function () {
        $('body,html').animate({
          scrollTop: 0
        }, 800);

        return false;
      });

      $(window).on('scroll', function () {
        var scrollPos = $(window).scrollTop();

        if (scrollPos > 50) {
          $('#back-to-top').fadeIn();
        } else {
          $('#back-to-top').fadeOut();
        }
      });
    }
  }
});

resources/assets/sass/app.scss 파일을 수정합니다.

// Fonts
@import url(https://fonts.googleapis.com/css?family=Raleway:300,400,600);

// Variables
@import "variables";

// Bootstrap
@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

// FontAwesome
@import "node_modules/font-awesome/scss/font-awesome";

// Select2
@import 'node_modules/select2/src/scss/core';

.select2-dropdown,
.select2-container--default .select2-selection--multiple,
.select2-container--default.select2-container--focus .select2-selection--multiple {
  border: 1px solid $input-border;
  border-radius: 4px;
}

.select2-container,
.select2-container--default .select2-selection--multiple {
  font-size: $font-size-base;
}

// Dropzone
@import 'node_modules/dropzone/src/dropzone';

.dropzone {
  border: 1px solid $input-border;
  border-radius: 4px;
}

.dropzone {
  display: none;
}

label[for=my-dropzone]>small {
  cursor: pointer;
}

.preview__content {
  display: none;
  margin-top: $font-size-base * 1.6;
  height: auto;
  @extend .form-control;
  box-shadow: none;
}

// Application Layouts
.container__article{
  padding: 1em 0;
}

.action__article {
  margin-top: 1em;
}

.footer__master {
  margin-top: 1em;

  a {
    display: inline-block;
    color: $text-color;
    text-decoration: none;
    padding: 0 5px;
  }

  ul {
    li {
      padding: 0;

      &:first-child {
        margin-right: 5px;
      }
    }

    li:not(:first-child) {
      a:hover,
      a:active,
      a:focus {
        border-radius: 3px;
        background-color: darken($body-bg, 5%);
        transition: all 0.3s ease;
      }

      &.active > a {
        border-radius: 3px;
        background-color: $body-bg;
      }
    }
  }
}

.back-to-top {
  cursor: pointer;
  position: fixed;
  bottom: 5px;
  right: 5px;
  display: none;
  z-index: 9998;
  transition: all 0.5s ease-in-out;
  padding: 8px 10px;
}

// Sidebar
.sidebar__article,
.tags__article,
.attachments__article {
  a {
    color: $text-color;
    text-decoration: none;
  }
}

.sidebar__article {
  ul {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  li {
    a {
      padding: 0.5rem;
      display: block;
    }

    a:hover,
    a:active,
    a:focus {
      border-radius: 3px;
      background-color: darken($body-bg, 5%);
      transition: all 0.3s ease;
    }

    &.active>a {
      border-radius: 3px;
      background-color: darken($body-bg, 10%);
    }
  }

  .badge {
    float: right;
    margin-right: 1rem;
  }

  form {
    margin-bottom: 30px;
  }
}

// Article
.content__article {
  margin: 2em;
  img {
    display: block;
    height: auto;
    max-width: 100%;
    margin: 0 auto;
    transition: all .2s ease-in-out
  }
}

// Tags Line, Attachments Line
.tags__article,
.attachments__article {
  list-style: none;
  margin: 0;
  padding: 0;
  font-weight: 100;
  font-size: $font-size-base * 0.8;

  li {
    display: inline-block;
  }

  li:first-child {
    margin-right: 10px;
  }

  li:not(:first-child) {
    padding: 4px 8px;
    background-color: darken($body-bg, 5%);
    border-radius: 3px;

    &:hover {
      background-color: darken($body-bg, 10%);
    }
  }
}

// Comments
.link__login__comment {
  padding: 1em;
  margin-bottom: 1em;
  border-radius: 3px;
  border: 1px solid $input-border;
  width: 100%;
}

.item__comment.top {
  padding: 1rem;
  border-radius: 4px;
  position: relative;
  overflow: visible;
  float: right;
  width: 100%;
  border: 1px solid $input-border;
}

.media__edit__comment,
.media__create__comment.sub {
  display: none;
}

.form__new__comment,
.list__comment {
  .form-group {
    width: 100%;
    margin: auto;
  }

  div.text-right {
    margin: 10px auto;
  }
}

.content__comment {
  p {
    margin: 0;
  }
}

.action__comment {
  button, span {
    font-size: $font-size-base * 0.8;
    font-weight: 400;
    text-decoration: none;
  }

  button {
    border: none;
    background: none;
    margin: 0;
    padding: 0;
  }

  button:hover,
  button:active,
  button:focus {
    transition: all .2s ease-in-out
  }

  &>span {
    margin: 0 5px;
  }
}

// Form
.form-control {
  box-shadow: none;
}

.form__auth {
  max-width: 400px;
  width: 100%;
  padding: 15px;
  margin: 0 auto;

  .checkbox {
    margin-bottom: 1rem;
  }

  .checkbox {
    font-weight: normal;
  }

  .form-control {
    position: relative;
    height: auto;
    box-sizing: border-box;
    padding: 0.8rem;
  }

  .form-control:focus {
    z-index: 2;
    border-color: $input-border;
    box-shadow: none;
  }

  input {
    margin-bottom: 10px;
  }

  .login-or {
    position: relative;
    margin-top: 20px;
    margin-bottom: 20px;
    padding-top: 15px;
    padding-bottom: 15px;
  }

  .span-or {
    display: block;
    position: absolute;
    left: 50%;
    top: -1px;
    margin-left: -25px;
    background-color: $body-bg;
    width: 50px;
    text-align: center;
  }

  .hr-or {
    margin-top: 0px !important;
    margin-bottom: 0px !important;
  }

  .fa-github {
    margin-right: 10px;
  }
}

span.form-error {
  margin-top: 5px;
  display: block;
  font-size: 0.8em;
  color: $brand_danger;
  font-style: italic;
  font-weight: 100
}

// Alert, Flash Messages
.alert {
  display: inline-block;
  position: fixed;
  bottom: 50px;
  right: 15px;
  max-width: 450px;
  opacity: .8;
  z-index: 999;
}

// Markdown Viewer
.docs__sidebar {
  margin-top: 20px;
}

#app-layout {
  pre {
    background: #000000;
    border-radius: 0;
  }

  // 이하 데일 리즈의 칼라 스킴에서 복사한 스타일시트

  .hljs {
    display: block;
    padding: 0.5em;
    background: #000000;
    color: #BABABA;
  }

  .hljs-comment,
  .hljs-template_comment,
  .hljs-javadoc {
    color: #494B4D;
  }

  .hljs-keyword,
  .ruby .hljs-function .hljs-keyword,
  .hljs-request,
  .hljs-status,
  .nginx .hljs-title {
    color: #F08D24;
  }

  .hljs-function .hljs-keyword,
  .hljs-sub .hljs-keyword,
  .method,
  .hljs-list .hljs-title {
    color: #68C244;
  }

  .hljs-string,
  .hljs-tag .hljs-value,
  .hljs-cdata,
  .hljs-filter .hljs-argument,
  .hljs-attr_selector,
  .apache .hljs-cbracket,
  .hljs-date,
  .tex .hljs-command,
  .coffeescript .hljs-attribute {
    color: #F2D42C;
  }

  .hljs-subst {
    color: #DAEFA3;
  }

  .hljs-regexp {
    color: #E9C062;
  }

  .hljs-title,
  .hljs-sub .hljs-identifier,
  .hljs-pi,
  .hljs-tag,
  .hljs-tag .hljs-keyword,
  .hljs-decorator,
  .hljs-shebang,
  .hljs-prompt {
    color: #E8341C;
  }

  .hljs-symbol,
  .ruby .hljs-symbol .hljs-string,
  .hljs-number {
    color: #8E69C9;
  }

  .hljs-params,
  .hljs-variable,
  .clojure .hljs-attribute {
    color: #1CC3E8;
  }

  .css .hljs-tag,
  .hljs-rules .hljs-property,
  .hljs-pseudo,
  .tex .hljs-special {
    color: #E8341C;
  }

  .css .hljs-class {
    color: #1CC3E8;
  }

  .hljs-rules .hljs-keyword {
    color: #1CC3E8;
  }

  .hljs-rules .hljs-value {
    color: #E8341C;
  }

  .css .hljs-id {
    color: #8B98AB;
  }

  .hljs-annotation,
  .apache .hljs-sqbracket,
  .nginx .hljs-built_in {
    color: #9B859D;
  }

  .hljs-preprocessor,
  .hljs-pragma {
    color: #8996A8;
  }

  .hljs-hexcolor,
  .css .hljs-value .hljs-number {
    color: #DD7B3B;
  }

  .css .hljs-function {
    color: #DAD085;
  }

  .diff .hljs-header,
  .hljs-chunk,
  .tex .hljs-formula {
    background-color: #0E2231;
    color: #F8F8F8;
    font-style: italic;
  }

  .diff .hljs-change {
    background-color: #4A410D;
    color: #F8F8F8;
  }

  .hljs-addition {
    background-color: #253B22;
    color: #F8F8F8;
  }

  .hljs-deletion {
    background-color: #420E09;
    color: #F8F8F8;
  }

  .coffeescript .javascript,
  .javascript .xml,
  .tex .hljs-formula,
  .xml .javascript,
  .xml .vbscript,
  .xml .css,
  .xml .hljs-cdata {
    opacity: 0.5;
  }

  // 이상 데일 리즈의 칼라 스킴에서 복사한 스타일시트
}

// 미디어 쿼리
@media screen and (max-width: 991px) {
  .action__article {
    margin-bottom: 1em;
  }

  .sidebar__article {
    margin-bottom: 2em;
  }

  .item__comment {
    &>a.pull-left {
      display: none;
    }
  }
}

@media screen and (max-width: 767px) {

}

@media screen and (max-width: 479px) {

}

resources/assets/js/forum.js 파일을 다운로드 합니다.

~/laravel-mix-test $ wget https://raw.githubusercontent.com/appkr/l5code/master/resources/assets/js/forum.js -O resources/assets/js/forum.js

에셋 빌드를 수행합니다.

~/laravel-mix-test $ npm run dev 

laravel-mix

mix

@devaxid

This comment has been minimized.

Copy link

commented Jun 12, 2018

Vue 1 버전 기준이네요. Vue 2버전을 사용하시는분이라면 vue 공식문서에서 라이프사이클 다이어그램을 잘보고 resources/assets/js/app.js 파일의

ready() { ... },
위의 코드를
mounted: function (){ ... }
처럼 바꿔야합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.