樹脂が固まる前に

WebフロントエンドとAndroidを主にいじっている人のメモ

Laravelでプロジェクト作って,VueでHMRするまで

背景

バイト先で自分はReactを書いていたんだけど,これからはVue使うことになったらしい

ハンズオンしてほしいって頼まれたけど,Vueほぼやったことなかったので,基本的な使い方とかWebpackとの連携とかを半日ぐらい勉強した

よし資料作るかってなったら,そういえばバイト先PHP使ってること思い出して,これはLaravelとLaravel-Mix使うやつやんと気付く

ハンズオンで学んだ内容でそのままスムーズに移行できるように,Laravelを立ち上げて触ってみることにしたけど,何回か躓いたので備忘録

環境

Laravelでプロジェクト作成

PHPとComposerを入れる

各々,公式サイトから落としてくる(てか入ってなかったんか...)

パスを通しておく

Laravel入れる

composer global require "laravel/installer=~1.1"でグローバルにLaravelいれる

これでLaravelコマンドが使えるようになった

プロジェクトを作って依存パッケージを入れる

laravel new xxxx でプロジェクトフォルダ(xxxx)作る

xxxx 内で composer install して依存パッケージを入れようとするが,上手くいかない

これは,composer.lockcomposer.json に書かれたパッケージのバージョンが違うためらしい

composer updateでうまく行った

今後はこれを基本的に使えば良さそう

Laravel起動

php artisan serveしてサーバを起動!動いた

localhost:8000にブラウザでアクセスするも,Whoopsって表示されてる...

あ~.envファイルをコピーする必要があるんだった

PowerShellcp .env.example .envした (ちなみにPowerShellだとcp -p .env.example .envは動かなかった)

気を取り直して,php artisan serveしたら動いた🎉

f:id:pvcresin:20190203185142p:plain

今回使うフォルダたち

  • resources/
    • js/: Vueのファイルも入ってる
      • components/
        • ExampleComponent.vue
    • sass/: SCSSファイルが入ってる
    • views/: テンプレートのPHPファイルが入ってる
      • welcome.blade.php
  • public/: 最終的にServeされるファイルが入ってる(出力されてる)
  • routes/: ウェブページやAPIのルーティング周りが書かれている
    • web.php
  • webpack.mix.js

CSRFトーク

コンソールでCSRFトークンの記述ねえぞって怒られてるから,welcome.blade.phpheadタグ内に

<meta name="csrf-token" content="{{ csrf_token() }}">

書いておく

Vue動かす

準備

  • Chrome拡張のVue.js devtools
  • VSCodeの設定でformatOnSavetrueにする
  • VSCode拡張の以下2つを入れる
    • Prettier: いろんな形式のファイルを自動フォーマットする君
    • Vetur: Vueファイルをいい感じに表示したりする君
  • xxxx内でyarnして依存モジュールを入れる

npm-scripts

package.jsonを見ると,主なコマンドは以下の4つ

  • prod: 1回productionビルド
  • dev: 1回developmentビルド
  • watch: ファイルが更新されるたびにdevelopmentビルド(ブラウザリロード必要)
  • hot: HMR.ファイルが更新されるたびにdevビルド(ブラウザリロード不要)

Routingを変えてみる

viewsindex.blade.phpを作成

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Laravel</title>
    <meta name="csrf-token" content="{{ csrf_token() }}" />
  </head>
  <body>
    <div id="app">
      <example-component></example-component>
    </div>
    <script src="{{ mix('js/app.js') }}"></script>
  </body>
</html>

routes/web.php内に,ブラウザで/にアクセスした時,welcomeのテンプレートを返すことが書かれてるので,indexに変更する

Route::get('/', function () {
    return view('index');
});

もう一度サーバを起動してアクセスし直すとindex.blade.phpの内容が表示されてる

開発してみる

とりあえずyarn watchしてみる

resources/js/components/ExampleComponent.vueを編集すると,自動でビルドされる

ブラウザをリロードするとコンポーネントが更新されている

f:id:pvcresin:20190203185520p:plain

これで開発はできそう

HMR(Hot Module Replacement) する

yarn hotしてみたけど,.vueファイル変更保存しても反映されない!

調べたら,なんかIssueたってた

LaravelとVueを連携するためにLaravel-Mix(Webpackのラッパー)で通信してるけど,そこの連携がうまく行ってないっぽい

webpack.mix.jsに以下を追記

Mix.listen('configReady', webpackConfig => {
    if (Mix.isUsing('hmr')) {
        // Remove leading '/' from entry keys
        webpackConfig.entry = Object.keys(webpackConfig.entry).reduce(
            (entries, entry) => {
                entries[entry.replace(/^\//, '')] = webpackConfig.entry[entry]
                return entries
            },
            {}
        )

        // Remove leading '/' from ExtractTextPlugin instances
        webpackConfig.plugins.forEach(plugin => {
            if (plugin.constructor.name === 'ExtractTextPlugin') {
                plugin.filename = plugin.filename.replace(/^\//, '')
            }
        })
    }
})

もう一回yarn hotしてブラウザで開いたらコンソールでHMRが有効化されていることが確認できた

.vueファイルを変更して保存すると,ブラウザのリロード無しで反映されるようになった🎉

とりあえず最低限は動いてるかな

HMRが動いたので今日はここまで

Kotlin Fest 2018 に行ってきた

8月末にKotlin Fest 2018に行ってきた。

そもそも記事書かないつもりだったから遅れてしまったけど、初めて大きめのカンファレンスに行ったし、やっぱり記念に書いとこ。

Kotlin Fest とは

「Kotlinを愛でる」ためのカンファレンス。

今年初めて開催。場所は品川。

参加者は400人弱と結構多い。

スポンサーも全部で17社あって、そのうちの8社は当日にブースも出してた。

参加まで

JKUG(日本Kotlinユーザグループ)のConnpassで開催がアナウンスされてたので気になってた。

チケットは以下の4種類

  • 一般(懇親会 有)8000円 先着200名
  • 一般(懇親会 無)5000円 先着150名
  • LT登壇(懇親会 有)5000円 先着8名
  • 学生(懇親会 有)無料 先着10名

カンファレンスって結構するのな…と思ってたけど、友達にあとから聞いたら安くね?って言われた笑

とにかくお金がない学生なので、全国で先着10名の学生枠を争うことに。

ブラウザのタブをリロードしまくったら、学生枠3人目をゲット!

懇親会もついてくるし最高~~

開会前

当日の品川は快晴!

看板イケてる

JKUGのかわいいトートバッグもらえた(レッド・ブラック・ネイビー)

水やお茶もあった

コーヒやワインとかも

数種類のスイーツ的な何かが無制限に出てきた(スポンサーの力?)

無料で食べ飲み放題で最高!

写真撮ってないけど、スポンサーブースはクイズをやってたり、グッズのプレゼントがあったりとお祭りって感じが満載だった。

当日の自分のハイライト

講演

はじまり

「Kotlinを愛でる」とは?から始まって熱い講義だった。

最近のKotlinやコミュニティの動き、各社の導入事例などてんこ盛りな内容だった。

ここからは2会場でパラレルに講演を聞ける。

聞いたのは以下の講演

  • 「Kotlinもう一歩」
    • タイプやジェネリクス、変位の話は知らないことも多く、ためになった。
  • 「Kotlinアプリのリファクタリングポイント」
  • 「Kotlin linter」
    • 各リンターの違いや使い方、カスタマイズ方法の話はちょうど今使っていて参考になった。
  • 「Kotlin コルーチンを理解しよう」
    • コルーチンの内部実装の話が面白かった。
  • 「公募によるLT大会」
    • シーケンスやDSL、コルーチンやKontributeなど様々な話を一人3分で詰め込んで話すのはスピード感があってよかった。

懇親会

人がいっぱい

シェフがローストビーフ切ってくれる

懇親会ではパックマンルール(人が入りやすいように輪の一部をあけておくルール)が定められていたので、とても良かった。

Kotlinにまつわる会は初めてじゃなかったので、知ってる人が結構いた。

まとめ

Kotlinを愛でたいので来年も開催してほしいし、参加したい。

多くの講演でKotlinの言語仕様や実装を絡めて話してくれたので、かなり参考になるところが多かったと思う。

サーバサイドもだいぶ増えてきたっぽくてKotlinが広まっていくのは嬉しい。

(Kotlin.jsの話がないぞ…?)

あと食べ飲み放題だったので、最高だった。

学生枠で懇親会も参加できて、有意義な時間だったなぁ。

Kotlinかわいい!

Kotlin/Native v0.3がWin対応したので触ってみた

はじめに

全ての道はKotlinに通ず

つい先日,Kotlin/Nativeがv0.3になってwindowsで動くようになったらしい. blog.jetbrains.com 触るしか無い…!

はじめに結果を言っとくと,サンプルを動かしてウィンドウが出せたよ f:id:pvcresin:20170624012016p:plain

準備

環境はwindows10 64bit.
上のリンクからx86-64 Windows用のzipを落としてきて解凍する.
中はこんな感じ
f:id:pvcresin:20170624011856p:plain
このbinにPATHを通す.(再起動も忘れずに)

何となくコマンドプロンプト(以下cmd)でkotlincと打つと,
Downloading native dependencies (LLVM, sysroot etc). This is a one-time action performed only on the first run of the compiler.
なるほど.はじめは何か落としてくるのか.350MBだったので,まぁまぁ待った.
色々落としてきてる様子がコンソールに流れて,終わったと思ったら最後に
error: you have not specified any compilation arguments. No output has been produced.
怒られた.まぁそうだよね.kotlinc のあとファイル指定してないし.

よしこれで準備OK!

README.mdとか読みながら動かしていくぞ

exeを書き出してみる

hello.ktを作成

fun main(args: Array<String>) {
  for (i in 0 until 10000) {
    println("hello kotlin native :$i")
  }
}

cmdでコンパイルタイム!
README.md によるとkotlinc hello.kt -o helloって書いてあったけど,
これだと怒られるので,kotlinc-native hello.kt -o helloってやったらhello.exeとhello.kt.bcが出来た.
exeをクリックして実行すると文字が流れる.OK!

win32APIを使ってウィンドウを生成する

これが本番.同封されているサンプルにwin32というのがあるのでこれを動かす
サンプルからコードをコピってくる

hello.kt

import win32.*

fun main(args: Array<String>) {
    MessageBoxW(null, "Konan говорит:\nЗДРАВСТВУЙ МИР!\n",
            "Заголовок окна", MB_YESNOCANCEL or MB_ICONQUESTION)
}

キリル文字が並んでる~と思ったら,あ~JetBrainsはロシアだっけか(チェコでした)。

サンプルからwin32.defもコピってきて,コマンドを打つ
cinterop -def win32.def -o win32
数分かかったが,win32-buildというフォルダとwin32.klibができた. これでライブラリの準備が出来たっぽい
ちなみにklibはv0.3から出来たライブラリのフォーマットらしい.

kotlinc-native hello.kt -library win32 -o hello
コンパイルして,出来たhello.exeをクリックすると~

f:id:pvcresin:20170624012016p:plain

すごい.どことなくウイルスみたいに見えるけど,サンプル動いた.おわり!

おわりに

ここからは独り言なんだけど,Kotlinすごい(自分の周りで騒いでる人いなくて悲しいんだけど)

JVMで実行できて,JSへの変換も公式になって,Nativeにも書き出せて,Android開発の公式言語になった
コミュニティのロゴとかも出来たね
Cとかの代わりになるってことでいいのかな?この流れで行くとWebAssemblyまで手を出しそうだ.というか出すんじゃないかな

あと,今回のv0.3でAndroidのnative activitiesに対応したらしい
こっちは試してないけど,C++とか書いてJavaやKotlinから呼び出すみたいな今までの開発をしなくても,KotlinでNativeになる時代が本当に来たのか~と思うと目から汁が出る

KotlinでDSL作って,HTMLとかJSとか全部Kotlinで書くみたいなプロジェクトが確かあったと思うけど,ホントにKotlinでなんでもかける時代が来るのかもしれない
Kotlin/Nativeが出たときに組み込みとかiOSアプリとかも作れるようにしたいって言ってたけど,もしかしたらKotlinでAndroidiOSの両方開発みたいなReactNativeとかXamarinみたいなのもできるようになるのか(胸熱)
まぁでもKotlinでJS書くの結構,頭切り替えなきゃいけないし,そこら辺の差をなくすのはまだまだ無理だろうな

こんなにいろんなことが出来るよって裾野広げて,開発チームは大丈夫なのかといらぬ心配をしてしまう
とにかくKotlinの今後にますます注目~

Mode Template for Processing 3.x を作った

前にMode Template for Processing 2.xを使ってProcessing 3.0.2で使えるMode作ったけど,なぜか動かなくなってたのでこの際だから3.x用作った
基本は2.xのまま借りてきている
少し直したのと,前はEclipseで作ってたけどIntelliJが好きだから,移行してIntelliJでつくった
ここからメンテナンスするかと言われればたぶんしない

github.com

String.prepend, String.append, String.minusの話

小ネタだけど,String関係で便利なやつ第2弾
解説すると,String.prepend(String)で前に追加,String.append(String)で後に追加
String - IntでInt文字数分削除

下の例だと,文字”STRING”にprepend("pre")で"preSTRING"
そのあとappend("app")で"preSTRINGapp"
最後にs - 1で最後の1文字を削除して"preSTRINGap"

operator fun String.minus(num: Int) = this.substring(0, this.length - num)

fun String.prepend(s: String) = this.javaClass.getDeclaredField("value").let {
    it.isAccessible = true
    it.set(this, s.toCharArray() + this.toCharArray())
    this
}

fun String.append(s: String) = this.javaClass.getDeclaredField("value").let {
    it.isAccessible = true
    it.set(this, this.toCharArray() + s.toCharArray())
    this
}

fun main(args: Array<String>) {
    val s = "STRING"
    s.prepend("pre").append("app")
    println(s - 1)  // ->  preSTRINGap
}

Stringに掛け算の演算子オーバーロードしたら捗った

最近Kotlinのoperatorとかinfix触っててよかった話をひとつ.

Stringで+を使うと結合になるわけだけど,なぜか*がない
なのでString.timesを作った
String * Int, String *= Intって感じ
これでいちいちfor回したりがなくなるので結構便利
デフォルトに組み込んでほしい^~

fun main(args: Array<String>) {
    operator fun String.times(num: Int): String {
        var s = ""
        for (i in 0..num) s += this
        return s
    }
    println("hell, " * 2 + "hell)//hell, hell, hell
}

ProcessingのTemplate Modeでビルドするときにスケッチ名とコードを取得する

続き: pvcresin.hatenablog.com

JavaModeを継承しているTemplateModeでhandleLaunchメソッドをOverrideする

メインのコードはhandleLaunchメソッドの中で,こんな感じ

String sketchName = sketch.getName();
System.out.println("handleLaunch: " + sketchName);
        
Editor editor = base.getActiveEditor();
String s = "";
for (int i = 0; i < editor.getLineCount(); i++){
    s += editor.getLineText(i);
}
System.out.println(s);

TemplateMode全体

package com.mydomain.mymode;

import java.io.File;
import processing.app.*;
import processing.app.ui.*;
import processing.mode.java.*;
import processing.mode.java.runner.Runner;

public class TemplateMode extends JavaMode {
    
    public TemplateMode(Base base, File folder) {
        super(base, folder);
    }

    /**
     * Return the pretty/printable/menu name for this mode. This is separate
     * from the single word name of the folder that contains this mode. It could
     * even have spaces, though that might result in sheer madness or total
     * mayhem.
     */
    @Override
    public String getTitle() {
        return "Template";
    }
    
    // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
   
    // Create a new editor associated with this mode.
//    @Override
//    public Editor createEditor(Base base, String path, EditorState state) {
//         return null;
//    }

    // Returns the default extension for this editor setup.
//    @Override
//    public String getDefaultExtension() {
//        return null;
//    }

    // Returns a String[] array of proper extensions.    
//    @Override
//    public String[] getExtensions() {
//        return null;
//    }

    // Get array of file/directory names that needn't be copied during "Save As".    
//    @Override
//    public String[] getIgnorable() {
//        return null;
//    }
    
    /**
     * Retrieve the ClassLoader for JavaMode. This is used by Compiler to load
     * ECJ classes. Thanks to Ben Fry.
     * @return the class loader from java mode
     */
//    @Override
//    public ClassLoader getClassLoader() {
//        for (Mode m : base.getModeList()) {
//            if (m.getClass() == JavaMode.class) {
//                JavaMode jMode = (JavaMode) m;
//                return jMode.getClassLoader();
//            }
//        }
//        return null;  // badness
//    }
    
    /** Handles the standard Java "Run" or "Present" */
    @Override
    public Runner handleLaunch(Sketch sketch, RunnerListener listener,
            final boolean present) throws SketchException {

        String sketchName = sketch.getName();
        System.out.println("handleLaunch: " + sketchName);
        
        Editor editor = base.getActiveEditor();
        String s = "";
        for (int i = 0; i < editor.getLineCount(); i++){
            s += editor.getLineText(i);
        }
        System.out.println(s);
        
      JavaBuild build = new JavaBuild(sketch);
      String appletClassName = build.build(true);
      
      if (appletClassName != null) {
        final Runner runtime = new Runner(build, listener);
        
        new Thread(new Runnable() {
          public void run() {   // these block until finished
            if (present) runtime.present(null);
            else runtime.launch(null);
          }
        }).start();
        
        return runtime;
      }
      return null;
    }    
  
}