備忘録

何かあったとき用に

React をさくっと使う (with parcel)

この記事は TUT Advent Calendar 2019 1 日目の記事です.
初日から遅刻しかけてるの大丈夫か?

やりたいこと

create-react-app だと色々機能が多いので, さくっとかつすぐ React を触れるような構成を作る.
React プロジェクトに parcel を使用して bundle するだけ.
package 導入には yarn 使ってます. npm の方は適宜読み替えてください.

環境

  • Node.js: v12.13.1
  • yarn: 1.19.2
  • react/react-dom: 16.12.0
  • parcel-bundler: 1.12.4

手順

必要な package を追加

$ yarn init

とかでプロジェクト初期化する. 次に以下を実行して, プロジェクトに必要な package を入れる.

$ yarn add react react-dom
$ yarn add --dev parcel-bundler

作成

ソースコードは普通に長い (というか貼り付けるのが面倒な) ので GitHub に上げているから参照してください.
コンポーネントにはモダンな Functional Component, 昔ながらの Class Component どちらとも利用している. (やっていることは同じだが)

ちなみに, このプロジェクトでは node_modules/ 除いて以下のような構成になっている:

./
├── package.json
├── src
│   ├── component.js
│   ├── index.css
│   ├── index.html
│   └── index.jsx
└── yarn.lock

実行

package.json に以下を追記:

"scripts": {
    "start": "parcel src/index.html",
    "build": "parcel build src/index.html"
  }

これで, yarn startでテストサーバを起動でき, yarn build でビルドができる.

f:id:KashEight:20191201183553p:plain

Chrome 上でこのように表示されて, それぞれのボタンが反映されればおそらく大丈夫なはず.

注意

React で Class Component を使う際, メソッドを呼び出すときに, this を bind する必要があり, 煩わしくて class property*1 使うかもしれないけど, そもそもまだそれは ECMAScript で標準化されていない実装なので, 使うときは babel を用いてトランスパイルする必要があるから気をつけてほしい.

余談

実は parcel は CSS もモジュールとして読み込んで bundle してくれるので HTML に直書きしなくてもやってくれる.
なので, js 内で import "./index.css" しても別に問題ない. (なんなら parcel のホームページもそんな使い方の例を示してるし)
あと Sass とか, TypeScript とかも自動的に読み込んでくれるので本格的なものを作る必要ないなら parcel で十分な気がする. webpack だと設定面倒だし.

最後に, 最近忙しいのマジでどうにかしてくれ…実際にこれ遅刻しかけてるし…

*1:クラス直下の宣言 (コンストラクタ経由をしない宣言), これにはアロー関数も含まれる. つまり, クラス内のアロー関数宣言はメソッドではなくプロパティ扱い

人生

皆さんも人生楽しみましょう.

楽しいインターネット 楽しい Twitter そして人間に感謝































人生, インターネット, Twitter 全て最高!

信念

凍結解除のお話

以前こんなこと言ってましたけどなんやかんやあって凍結解除されたのでそのお話

何があったのか

5 月 14 日の朝 4 時ぐらい*1に凍結かロック, または両方の判定食らったらしくアカウントがお陀仏になりました.
ちぃたんや神楽めあなどのアカウントが一斉凍結*2されたのでそれに巻き込まれた形ですね.
"凍結かロック, または両方の判定" と書いたのは Twitter を開いた後 "ロック画面の表示 → ロック解除 → 数秒後に凍結表示" となったのでロック解除されてから凍結されたのか, 同時に行われたのかがわからなかったのでそう表記しました (おそらく後者の可能性が高いと思います, 個人的な感想ですが…).

解除までの経緯

凍結されたあと, すぐに異議申し立てフォームから異議申し立てしました. Twitter の日本支社は悪い噂しか聞かないのと個人的な恨みがあったので, 英語フォームから本社に直接異議申し立てしました. まあ, それが今回解除が長引いた原因なんですけどね…
異議内容は忘れましたが確か "なんで凍結されたか知らんが教えろ" みたいな内容だったような気がします. それで, 返信はこれです

f:id:KashEight:20190803235915p:plain

読んだらわかるかと思いますが, この方法はいわゆるロック解除の方法で凍結異議とは別のものです. 件名は "Appealing an account suspension" なのにね.
一応, これは返信すると返ってくるタイプのメールなので返信してます.
そのときの回答はこちらです

f:id:KashEight:20190804002815p:plain

そのまま読むと, "ルールの複数回違反による凍結" です. もちろん, これだけでは納得しないので再度異議を送り直しました.
そのときの回答

f:id:KashEight:20190804005408p:plain

まあいわゆる "永久凍結されてるのに別のアカウント持ってるやろお前" みたいな感じで凍結されたようです.
ならばと, "永久凍結した最初のアカウントで異議申し立てして解除されればいけるのでは?" という浅はかな考えで今回凍結したアカウントと違うアカウントで異議申し立てしました. もちろん, 結果はダメでしたけど.
で, ある時 "日本語フォームで異議申し立てしてみよう" と考えになって異議申し立てを行いました. それと同時に "それならば, 今回のアカウントも日本語フォームから送ってみよう" と思い, こちらの方でも異議申し立てを行いました.
前者の方は 1 日ほどで返ってきて内容は "無理です" ということ (過去に何度も蹴られてるので当たり前だが). 後者の方は 9 日かかって返ってきました. そのときの内容がこちらです

f:id:KashEight:20190804011549p:plain

いやいやいや…

8, 9 割ぐらい諦めてたのでこれ見た瞬間めっちゃびっくりしました. 21 時ぐらいにこれ送られてきてその時は寝てたんですが, 携帯の通知がきて見たらこれだったので一瞬で目が覚めました.

そういうわけでアカウントが無事復活しました. 素直に日本語フォームから異議申し立てを送れば 2 ヶ月もかからず解除はできたと思いますが, まあ結果的に解除はできたので良しとしましょう.

結論

Twitter の利用環境が日本ならためわらず日本語フォームで異議申し立てしましょう. 日本支社と本社で回答が違うところを見ると, どっちとも状況を同じく把握しているわけではないっぽいので.

あと, ネタで相手を通報するのはやめようね!てか, 相手がクソ嫌いなやつで凍結させたくてしょうがない人はともかく, 面白半分のネタで通報するのはやめてくれ, マジで面倒だから, いやほんとに.

*1:凍結されても凍結される直前の TL は表示されるので TL 上に残ってた最後のツイート時間から判別しました. ちなみにその時間は丁度 Discord も落ちてたみたいです (そのときの最終ツイートが Discord が落ちた報告でした, 不名誉).

*2:ソース: Twitterでアカウント凍結祭りか ちぃたん☆や仮面女子、Vtuberなども凍結(2019年5月14日)|BIGLOBEニュース

今後のこと

Twitter 凍結解除の目処はないのと作り直すのも面倒なのでそのままフェードアウトします.
Discord にはいるのでなんかあったらそこで教えてください, 気分で返答します.

それでは.

後日談 → http://kasheight.hatenablog.jp/entry/2019/08/04/015731

家具作った

計5時間ぐらい (片付け含めると6時間ちょい) かかったので昼飯は16時ぐらいに食べた. (作業開始が10時くらいなので)

以上.

Nuxt2 + TypeScriptの環境構築

この記事はKaigen Discord Advent Calendar 2018 13日目の記事です。

前置き

Nuxt.jsでTypeScriptを導入した環境を構築するのにかなり苦労したので同じことをしようと思う人と自分に向けてまとめておく。
最終的なテンプレートはGitHubにあげていますのでご参考に。

環境

  • Node.js: 10.14.1
  • Nuxt: 2.3.4

構築過程

プロジェクト作成

まず

$ yarn create nuxt-app

でNuxtプロジェクトを作る。構成は以下の画像のようにした。

f:id:KashEight:20181206205904p:plain

今回は環境構築だけなのでサーバサイドフレームワークやUIフレームワークは使わず, また, APIをいじいじするわけでもないのでAxiosも入れない。Universalアプリケーション作るわけでもないのでSPA。lintはかけたいのでeslintやprettierは今回のプロジェクトで導入した。

プロジェクトを作成したらとりあえず

$ yarn run dev

で動かしてみる。
Nuxt v2.3.4ではこのような画面が出たら成功。

f:id:KashEight:20181206213350p:plain

TypeScriptの導入

TypeScriptとWebpack用のloaderとnodeの型宣言ファイルを導入する

$ yarn add -D typescript ts-loader @types/node

Nuxt(というよりかはVueファイル)で使用するパッケージを導入

$ yarn add vue-class-component vue-property-decorator vuex-class

vue-class-componentやvue-property-decoratorをベースとしたnuxt-class-componentnuxt-property-decoratorがnuxt-communityで公開されているがどちらともメンテナンスが滞ってる(nuxt-property-decoratorは最近メンテナンスが再開された?)し, どちらともベースとなるもので事足りるのとそっちの方が機能が多いので別に導入しなくていいと思う。

TypeScriptをビルドできるようにする

TypeScriptをビルドできるようにWebpackの設定をいじってみる。
Nuxtではnuxt.config.jsのbuildプロパティ*1でWebpackの設定をいじるほか, モジュール*2という形でもWebpackの設定をいじることができる。
前者の方法では軽く設定を変える程度で複数プロジェクトで同じようなことをしない場合, そうではない場合は後者の方法を用いるのがいいでしょう。
今回のような場合は後者の方法で実装したほうがよさそう。
幸いにもNuxt2ではないがTypeScriptのテンプレートがあったのでそれを参考にNuxt2用に実装してみる。
まず, modules/typescript.jsとmodulesフォルダとjsファイルを作り以下のコードを記入する。(一応, tsxにも対応できるようにした)

module.exports = function() {
    // Nuxtで.ts/.tsxファイルを解決させる
    this.nuxt.options.extensions.push('ts', 'tsx')
    // Webpackの設定
    this.extendBuild(config => {
        // .ts/.tsxをビルドできるようにts-loaderを追加する。
        config.module.rules.push({
            test: /\.tsx?$/,
            exclude: /(node_modules)/,
            loader: 'ts-loader',
            options: {
                appendTsSuffixTo: [/\.vue$/]
            }
        })
        // Webpackのextensionsに.tsが入っていない場合解決できるようにする
        if (!config.resolve.extensions.includes('.ts')) {
            config.resolve.extensions.push('.ts')
        }
        // Webpackのextensionsに.tsxが入っていない場合解決できるようにする
        if (!config.resolve.extensions.includes('.tsx')) {
            config.resolve.extensions.push('.tsx')
        }
    })
}

次にモジュールを読み込めるようにnuxt.config.jsに以下を追記する。

modules: ['~modules/typescript.js']

tsconfig.jsonは以下のようにした。

{
    "compilerOptions": {
        "target": "es5",
        "lib": ["dom", "es2015", "es2016", "es2017"],
        "module": "es2015",
        "moduleResolution": "node",
        "alwaysStrict": true,
        "experimentalDecorators": true,
        "noImplicitAny": false,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "sourceMap": true,
        "removeComments": true,
        "suppressImplicitAnyIndexErrors": true,
        "allowSyntheticDefaultImports": true,
        "allowJs": true,
        "baseUrl": ".",
        "paths": {
            "~/*": ["./*"],
            "@/*": ["./*"]
        },
        "typeRoots": [
            "node_modules/@types",
            "types"
        ]
    },
    "exclude": [
        "node_modules"
    ]
}

vscodeだと以下のようなファイルエラーが出ますが無視して構いません。(理由はよくわからないです…分かる人は教えてくれれば幸いです。)

[ts] 入力ファイルを上書きすることになるため、ファイル <rootPath>/modules/typescript.js' を書き込めません。

2/20追記: コメントにて

tsconfing.jsonのcompilerOptionsにoutdirかoutFileを指定するとエラーがなくなるようです。
変換しない場合は、"outFile": "" とするかまたは存在しないデタラメなフォルダを指定すればいいようです。

という指摘をいただきました。
確認はまだしていないのですがこれでそのvscodeのエラーは回避できるようです。
7ccさんありがとうございます!

最後に, VueでTypeScriptが使用できるように型宣言ファイルをtypes/index.d.tsのように作成して以下を記入する。

declare module '*.vue' {
    import Vue from 'vue'
    export default Vue
}

TypeScriptを使用する

pages/index.vueでTypeScriptを使用してみる。ソースは以下のようにした。

<template>
  <section class="container">
    <div>
      <logo/>
      <h1 class="title">
        {{ title }}
      </h1>
      <h2 class="subtitle">
        {{ fuwa }}
      </h2>
      <div class="links">
        <a
          href="https://nuxtjs.org/"
          target="_blank"
          class="button--green">Documentation</a>
        <a
          href="https://github.com/nuxt/nuxt.js"
          target="_blank"
          class="button--grey">GitHub</a>
      </div>
    </div>
  </section>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import Logo from '~/components/Logo.vue'

@Component({
    components: {
        Logo
    }
})
export default class extends Vue {
    title = 'hoge'
    desc = 'fuwa'
}
</script>

<style>
.container {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
}

.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}

.links {
  padding-top: 15px;
}
</style>

ビルドしてみる

一度, yarn run lint --fixyarn run devをしてビルドしてみよう。
localhost:3000に接続してみて以下の画像のようになったら成功。

f:id:KashEight:20181207011810p:plain

これでTypeScriptの導入は終了した。

TypeScriptにlintをかける

TypeScriptを導入したはいいけれども.ts/.tsxファイルや.vueファイル内のscript部分にはlintはかからない。
そこでtslintやtypescript-eslint-parserを導入してlintをかけようと思う。今回はeslintを導入しているのとtslintとvueの相性が悪いのでtypescript-eslint-parserを使ってlintをかける。
まず必要となるパッケージを追加する。

$ yarn add -D typescript-eslint-parser eslint-plugin-typescript

nuxt.config.js

config.module.rules.push({
    enforce: 'pre',
    test: /\.(js|vue)$/,
    loader: 'eslint-loader',
    exclude: /(node_modules)/
})

を以下のように変更

config.module.rules.push({
     enforce: 'pre',
     test: /\.(js|ts|vue)$/,
     loader: 'eslint-loader',
     exclude: /(node_modules)/
})

.eslintrc.jsに以下を追記

overrides: [
    {
        files: ["*.ts", "*.vue"],
        parserOptions: {
            parser: "typescript-eslint-parser"
        },
        plugins: ['vue', 'prettier', 'typescript']
    }
]

これでTypeScriptにlintがかかるようになった。

余談

この記事を作るきっかけとしてyarn create nuxt-appでeslintとprettierを導入して初期の状態でビルドするとエラーを吐いて導入できなかったのがあった。
原因は.vueファイル内のscriptの言語がTypeScriptだと初期のeslintのパーサであるbabel-eslintで解析してしまうためそれを回避するために記事中に書いたTypeScriptにlintをかけるような方法を取らなければいけなかった。
この記事を書いてる最中にNuxtのバージョンが上がったため新しいバージョンで試したところ, エラーを吐かずにすんなりビルドを通した。
今までの苦労はなんだったんだろう…。

脚注