ぬまのそこ

namazuのゆるいエンジニアブログ

Vue.jsでcomputed以外のプロパティでcomputedっぽいことをする

標題のとおりです。

したいこと

export default {
    name: 'hoge-component',
    computed: {
        hoge ( ) {
          return 'xxx';
        }
    },
    meta: { // これがcomputedのように動いて欲しい
       reactiveComputed ( ) { // => 'xxx'
          return this.hoge;
       }
    }
}

普段はcomputed内だけに定義できる算出ゲッターをmeta内に定義できるようにします。

動的に変わりまくるtitleやpageContext的なものを扱うためにcomputedではないレイヤーにcomputedがほしかった。

やりかた

  1. globalMixinを使い,createdでmetaが入ってきたコンポーネントが作られたことを検出します。
  2. metaのそれぞれの関数にコンポーネントをbindして作った関数で別のVueインスタンスを作ります
  3. 新しく作るVueインスタンスのcomputedに登録してWatcherで追跡してもらいます
watcher = undefined;
Vue.mixin({
  created() {
    if (this.$options.meta) {
      const self = this;
      const meta = this.$options.meta;
      const computed = Object.entries(meta).reduce((acc, current) => {
        if (typeof current[1] === "function") {
          acc[current[0]] = current[1].bind(self);
        }
        return acc;
      }, {});
      watcher = new Vue({
        computed,
        watch: {
          hoge(to, from) {
            console.log(to);
          }
        }
      });
    }
  },
  beforeDestroy () {
    if (watcher) {
      watcher.$destroy();
    }
  }
});

これでok. リアクティブな値を好きなスコープに作るのはVue.util.defineReactiveで作れますが, computedを作るにはWatcherをnewするひつようがあるので別のVueインスタンスを作るしかなさげかなと。 Vue.prototype._initをいじればcomputedにmetaの中身をマージできますが, そうすると同名でcomputedに置けなくなってしまう。

こうすればインスタンスが増えてしまうけれどcomputedを作れます。

コード

Vue Template - CodeSandbox

さらに

computedと同時に同名のwatchを定義して, 別につくったVueインスタンスのdataを置き換えるようにします。 そうすると散らばったコンポーネントのmetaが一箇所にまとまります.

このVueインスタンスのdataを元に色々と処理をします。  そうすると各ページコンポーネントにmetaってプロパティで定義した算出ゲッターが返す値をdocument.titleに設定できるようになります。

べんり!

vue.js: functional componentとscoped css

最近はFF14をしたり、某社でフロントやphpを書いたりしています。 Vueをメインに書いていますが、その中でちょっとハマった点があったのでまとめがてら記載します。

vue (2.5.17) にはvueloaderのscoped cssをfunctional componentでうまく扱えない挙動があります。 その対策をメモ的に書いておきます。

現象

vueにはインスタンスを持たない軽量なコンポーネントとしてfunctionalというコンポーネントを作ることができるようなりました。 これは画期的で、大量に使うようなbaseコンポーネントを負荷を恐れず簡単に分離し大量に用いることができます。

そこで私はいろいろと共通化できる処理を細かい単位でfunctional-componentとして分離して共通化していっているのですが、その過程でちょっと困ったことになりました。 functionalでない普通のコンポーネントからfunctionalなコンポーネントを利用するとscoped cssやクラスがうまく付きませんでした。

まとめると、

です。

コードにすれば、

<template functional>
  <span v-bind="data.attrs">{{ props.text }}</span>
</template>

<script>
export default {
  name: 'functional-component',
  props: {
    text: String
  }
}
</script>

のようなfunctilnal componentに対して

<template>
  <div>
     <functilnal-component text='hoge' class='red'/>
  </div>
<template>

<style scoped>
   .hoge {
       color: red;
   }
</style>

をしたとき文字が赤色にならないということです。

原因

  1. 静的なクラスとして与えたhogeはfunctional-componentでは通常コンポーネントで行われるクラスのマージが行われないため,functional-componentのルート要素spanに付与されません。

  2. vueのscoped cssdata-v-xxxxのような属性をrender時に全ての要素に付与し, cssを属性セレクタ付きに書き換えることで実現していますが, 上記のように利用した場合 functional-component側でv属性はマージされず, functional-component側だけのv属性がDOMに付与されるため, cssセレクタに一致せずスタイルが適用されません。

これはclassや属性をマージする一般的なhowtoである、functionalコンポーネント側でv-bind=data.attrsのようなことをしても解決しません。

対策

  1. functionalコンポーネントでは(というよりvnodeでは)静的なクラスとして付与された文字列はdata.staticClassで参照可能ですそのためv-bind:class="data.staticClass"とすることで普通に渡したクラスをfunctionalコンポーネント側の要素に付与することができます。

  2. これは厄介ですがvue-template-loaderによって実現されるscopedCssに使うscopeId (data-v-xxx)はvueインスタンス$options._scope_idで取得することができます。 つまりこれをバインドしてやればfunctional-compnent側でdata-v-xxxな値をマージすることができます。

これらを合わせると上記の問題を解決するfunctional-componentのtemplateは以下になります。

<template functional>
  <span
    v-bind="(() => { const res = data.attrs; /* scopeIdをマージする */ res[`${parent.$options._scopeId}`] = ''; return res; })()"
    :class="data.staticClass"
  >{{ props.text }}</span>
</template>

このようにv-bindとclassbindingを書いておくと, functional-componentを自然に普通のコンポーネントから利用できるようになります。

v-bindの中が黒魔術

他にはcss-moduleを利用するなどのscopedcssに頼らない根本的な解決策がありますが、私はscoped-cssがシンプルでvueらしく好きなので一旦これで進むことにしました。

日記記事を別ブログで書くようにしました

日記記事を別のブログで書くようにしました

実は昨日、記事の投稿ボタンを押すのが数分遅れて、このブログ の連続投稿が途切れてしまいました

それにしても、ここ最近、毎日書くブログにアウトプットと日記が混在していることをもどかしく感じていました。 純粋な技術エントリと全くそうじゃないエントリが混ざっているのはなんだかなーと。  日記も書きにくくなるし、技術エントリも書きにくくなる。 良くないなぁって思っていました。

そこで連続投稿が途切れたのを切っ掛けに、日記ブログを新しく作り、そこで日記を書くことにしました。 Wordpressでやろうかと思ったのですが、Wordpressを上げられるサーバがない。 個人でAWSにいくつかサーバは持っているのですが自分のWordpress用にはあまり使いたくないなという状況でした。

結局はてなブログでささっと別のブログを開設しました。 今年中にあるタイミングでWordpressに移して自鯖運用にしたいなぁと考えています。 新しい日記ブログは

namazu-diary.hatenablog.com

こちらになります。 これまでこのブログにあった全ての記事を移行させました。

また、このブログから、日記記事に偏っているなという記事は全て削除しました。 

今後はなにか共有できそうな成果を出したらこのブログに書いていくというスタイルにしたいと思います。

最近のWineはエロゲ動くの?

wineでエロゲ動かす

私のノートPCは以前Windowsだったのだが、開発に使うには嫌気がさしてLinuxにしてしまった。 開発効率が上昇してとても良い感じだが、一点問題が。エロゲができない。

そもそも開発用のノートPCでやるなよという話なのだが、ノートPCしか手元にない状態で過ごしていると、なんとなくやりたくなったときにできなくてつらい。

家のメインPCにRDPしてやってもいいのだが、メインのデスクトップを常時付けていると電気代もアレなので大抵切ってしまっている。

この前実家に帰省したときにノートPCしかなくて辛くなって、なんとかしてLinuxノートでエロゲ動かそうと頑張ってみた。

Linuxwindowsアプリを動かすならwine。 昔に使ったときは、使い物にならなかったような記憶があるが、いまはどうなんだろうって。

環境

  • VAIO Z(VJZ13A1)
  • ArchLinux

wineインストール

Wine - ArchWiki

偉大なるArchWikiに沿ってやっていく。 適当に推奨されたものを突っ込んでいった。 実際に動かす上で足りない物もでてきたので、それらは随時いれた。

足りない奴は実行時にsoがないよーってログが吐かれるので、そこから推察してインストールすれば上手くいく。

私はサウンド関係を入れ忘れてて、音がでなかった。 必要パッケージをpacmanから放り込んだらすんなりいった。 (wikiにリスト載ってるんだからちゃんといれとけと言う話だが。。。)

動かしてみた

とりあえず試してみたのは『feng: 妹のセイイキ』 OPが好き。 三部作のなかでは一番好きですね。 イカもいいんだけど。 

ISOをノートPCにマウントして、wineコマンドでexeを起動。 インストーラはさらっと立ち上がって、普通にインストールできた。

起動したら、普通に画面出た。 普通に動くし問題なさそう!

f:id:kituneko-510:20180303230815p:plain

一つ動いたくらいだと偶然っぽいので、もうひとつやってみた。

ユニゾンシフト: 』 癒やしゲー。

こちらはインストールして起動したら、画面が出てこなかった。 おそらくDirectXとかあのあたりではないだろうかだろうと予想。 winetricsを入れて、DirectX周りのコンポーネント入れたらちゃんと立ち上がってくれた。 

f:id:kituneko-510:20180303231038p:plain

いいかんじ。

結論

二作品しか試していないけど、Linuxでもエロゲはなんだかんだ動くんじゃないでしょうか。 

どうしてもノートPCでエロゲがしたいときはなんとかできる。

どうでもいいはなし

きょうはみみのひで、みみけっとでした。 ぼーっと歩いてたらなんか色々買っていて、財布が空になってた。 こわい。

涼屋のうすい本、キャラが可愛くてなんとなーく欲しかったのですが、25分で全部完売しててゲットならずでした。  みみけの涼屋ってあんなんだったけ。。。 

昼は品川のラーメンを食べてきて家に戻ったのですが、書類がどっかいったことに気づき、家中探し回り、大学にまで探しに行った、大学で無事見つけられたのだが、その後また小川流でラーメン食べて返ってきた。 1日に二回もラーメンを食べてしまった。。。

エロゲと美少女ゲームの定義って結構差があるよね。

 

Nginxのauth_requestがPOST時にTimeoutする

Nginxのauth_request

Module ngx_http_auth_request_module

これをつかってSSO認証を制御していた。

上手いこと動いていた感じだったのだが、この認証下にある WordpressのログインがTimeoutするという問題が発生。 

調査していくと、wordpressへのPOST時のauth_requestでタイムアウトが発生していることがわかった。 認証サーバ側のNginxのログは見ると408を返していた。

解決策

auth_requestをProxyに流すときには、

  • Content-Length を空にして
  • proxy_request_body を off にすること。
 proxy_pass_request_body off;
 proxy_set_header Content-Length "";

公式にちゃんと書いてある()

行きつくまで

認証サーバ自体はRailsでできたちょっとしたものなので処理の中でタイムアウトが起きるはずはなかった。 またRailsには一切ログが吐き出されていなかった。

Railsのログに記載されないというのはどういうこと???ってなった。 低レイヤでどうなってるのか調べようと、unicornにstraceを掛けたり、tcpdumpしたり色々していた。 その過程でそこそこしょうもない知識を得た。

結局、nginxがGETを受けたまま、そのまま固まっているのでは?感がnginx-workerプロセスのstraceから見えてきた。 ヘッダを全部見返していったら、大本の設定でContent-Lengthが抜けてたことに気づいた。

他のauth_requestの設定をしてある場所はちゃんと公式の見本通りにヘッダがセットしてあったのに、ここだけ抜けていたのはなんでなんだろう。。。 Gitのログ曰く、最近テンプレートを書き直したときに、このヘッダだけ削っていたっぽい。 ふぇぇって感じ。

どうでもいいはなし

Nginxのことも含めて、

とか絶賛しょうもない日だった。

タスクが山積みなのでなんとかしないと。。。 明日大学に行って進捗を出すかなぁ。。。 

 

Linuxのパーミッションで4桁のときの最初の0

今日したこと

  • windows10のVagrantVirtualBox)が上手く動かなくなっててBIOSが開けなかったり、設定項目にたどり着けなくておこになった。
  • なんかつかれたのでお風呂に行ってた。
  • vagrantで沢山VM上げてプロビジョニングして楽しんだ

Linuxパーミッションの数字表記

chmod 0644 ... とか よく書くじゃないですか。 この最初の0について。 気になったので調べてたら、これのことだったのねってなったのでメモ。

この最初の桁は0,1,2,4が使えて、それぞれ以下の意味になる

  • 0 とくになにもなし
  • 1 スティッキービット: 所有者以外消せないけど誰でも書き込めるって奴。 /tmpとかのディレクトリに初期設定されてる。ファイルに付与したら何も起きない。
  • 2 SGID: 付けた場合、そのファイルの所属グループの権限で動くようになる。
  • 4 SUID: 付けた場合、そのファイルの所有者の権限で動くようになる。

詳細は

qiita.com

このへん。

RackとかRailsでリダイレクトとかがhttpsにならないとき

今日したこと

  • いろいろ

短文技術エントリは手抜き。

nginx => railsとかでhttpsをraislに飛ばすときに解く

よくある構成だとおもう。 フロントのWebサーバまではHTTPSで飛ばして、最後のRailsにはHTTPでReverseProxyするってやつ。

そのときにHTTPヘッダをちゃんとNginxで設定しないとRails側がHTTPSで来た通信だということを認識しなくてうまく動かないのはよく知られた話。 X_Forwared_Proto htttps; とかはちゃんと書こうなって記事に引っかかる。

で。 これで引っかかった。 ちゃんと書いていたのにHTTPSと認識されなかったのは謎。

今回の問題は、 GoogleOmniauthのリダイレクトURLが何故かHTTPになってしまうということ。

コードを漁っていったら、Rackのschemeからhttpsかhttpかを取得していた。

このschemeの部分を見ていたらRails(Rack)がHTTPSできた通信かHTTP出来た通信か調べてるのがわかった。

def scheme
        if get_header(HTTPS) == 'on'
          'https'
        elsif get_header(HTTP_X_FORWARDED_SSL) == 'on'
          'https'
        elsif get_header(HTTP_X_FORWARDED_SCHEME)
          get_header(HTTP_X_FORWARDED_SCHEME)
        elsif get_header(HTTP_X_FORWARDED_PROTO)
          get_header(HTTP_X_FORWARDED_PROTO).split(',')[0]
        else
          get_header(RACK_URL_SCHEME)
        end
end

Rack schmeのここの部分だった。 これでhttpsか判断してるっぽい。 X_FORWARDED_PROTOなどなんかうまくいかなかったので、このコードにしたがって、Nginxで。。。

proxy_add_header X_FORWARDED_SSL on;

みたいにやったら、HTTPSと認識してくれて良しなに動いた。

どうでもいいはなし

  • 某所の電源がぶつぶつ切れる問題。 接続しているUPSのバッテリー切れが原因っぽかった。 対応したのでこれでいけるといいにゃぁ。
  • ストロングゼロ2本だと飛べないのでつらいね。