Ikkyu's Tech Blog

技術系に関するブログです。

WordPressをはじめてみる

WordPressを勉強することになったので、調べたことをまとめます。

WordPressとは?

PHPMySQLに基づいて無料でオープンソースなContent Management System(CMS)です。

CMSとは?

wikipediaより

ウェブコンテンツを構成するテキストや画像などのデジタルコンテンツを統合・体系的に管理し、配信など必要な処理を行うシステムの総称

システム構成

Webサーバ

Apache, Nginx + PHP-FPM

DB

MySQL, MariaDB

phpの実行環境については、こちらのサイトが非常にわかりやすかったです。

qiita.com

勉強で使用する環境

こちらのサイトを参考にしました。 keruuweb.com

その他の構成で構築したい方はこちらを参考してください。

MacでIEやEdgeを使用する方法

こんな便利なものがあったなんて!!と衝撃受けたので記事にしようと思いました。

たぶん有名だと思いますが...笑

これです。

developer.microsoft.com

なにが衝撃受けたかって、無料なんです。

これ知るまで、本気で検証用でwindowsを買おうとしていました...😇

フロントエンドの人は是非これを使ってみるといいと思います!

【CSS】NuxtでProductionとDevelopmentのBuildの違い

Nuxtで開発していたら、buildによってcssの読み込みに違いがありましたので、簡単にまとめます。

検証環境

  • Mac: 10.15.5
  • Node: v12.12.0
  • Nuxt: v2.12.2

この違いによって何が起こったのか

Production Buildしたら子コンポーネントにstyleを上書きされた

説明

コンポーネント(以下、子)と親コンポーネント(以下、親)があったとします。

<template>
  <button class="button">Button</button>
</template>
<style scoped>
.button {
  font-size: 14px;
}
</style>

<template>
<Button class="alert-button"/>
</template>

<script>
import Button from '~/components/Button.vue'

export default {
  components: {
    Button
  }
}
</script>

<style scoped>
.alert-button {
  background-color: red;
  font-size: 20px;
}
</style>

styleに注目してほしいのですが、 font-sizeが同じ詳細度になっています。

DevelopmentでBuildした場合、子で指定したスタイルを親が上書きするのでfont-size20pxになります。

f:id:Ikkyu:20200529001932p:plain
Development Build

しかし、ProductionでBuildした場合、親で指定したスタイルを子が上書きするのでfont-size14pxになります。
これは読み込まれるスタイルの順番がDevelopmentと逆になるためのようです。

f:id:Ikkyu:20200529002228p:plain
Production Build

原因は今のところ不明です。 対応策としては親の詳細度上げることしか思いつきませんでした🤔

ちなみにvue-cliでつくったプロジェクトで同じ検証を行いましたが、 nuxtのような違いは発生せず、DevelopmentでBuildした時と同じ挙動となりました。

今回検証したコードを、githubで公開しています。 github.com

[追記] そもそもこのような設計ってどうなの?って考えに行き着きました。 やっぱりCSSの設計は難しい...😇

Dockerの日本語化

rails consoleを使用する時に、日本語が消えてしまう問題が起こったので、やったことをメモします。

Dockerfileに以下を追加

RUN apt update && apt install -y locales locales-all

ENV LC_ALL ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP.UTF-8

参考 - ubuntu - Unable to locate package language-pack-en - Stack Overflow

Rails TutorialでHerokuにデプロイする時に、サブディレクトリを指定する方法

以前さわっていたRails...2年前ぐらいだったので、Rails再入門しようと思って
Rails Tutorialをやりはじめました。

TutorialではHerokuへのデプロイがあります。

Docker使ってTutorialやろうと思っていたので、
ディレクトリは以下のような構成になっています。

.
├── README.md
├── docker
├── tools
└── tutorial
    └── environment
        └── hello_app

Turorialは、この構成ではないので、

$ git push heroku master

を実行するとデプロイに失敗します。

やりたいことは、

tutorial/environment/hello_appをHerokuにデプロイしたいです。

そこで、git subtree push使って、サブディレクトリをHerokuへpushします。

git subtreeが気になる方は以下を参照してください。 github.com

今回の私のケースですと

$ git subtree push --prefix tutorial/environment/hello_app/ heroku master 

で、hello_appがHerokuにデプロイできました!!

git便利じゃん!ーって思ったけど、知らないこといっぱいだな...

また一つ勉強になりました。

subtree pushする時にエラーが発生する場合

push時に以下のエラーが発生する場合があります。

hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

その場合は、以下のようにすればデプロイできす。

git push heroku `git subtree split --prefix [path name] master`:master --force

参考記事
Herokuでサブディレクトリをデプロイできるらしいのでメモ | Qrunch(クランチ)
[Heroku] サブディレクトリだけを deploy する | CodeNote
Git subtree で push できないときの対処法 - Qiita
Why can't I push this up-to-date Git subtree? - Stack Overflow

Nuxt.js(TypeScript) × Vuetify × Storybookを使用して開発環境を再構築してみる

以前、Nuxtの開発環境構築の記事を書きました。

ikkyu.hateblo.jp

その後、Nuxt.jsやStorybookのバージョンが上がり設定方法が変わったので、改めて開発環境を記事にしてみようと思いました。

動作環境 - maxOS 10.15.4 - VSCode(Veturをインストール済み) - yarnインストール済み

構成は以下の通りです。(変更はありません)

  • Nuxt.js
  • TypeScript
  • Vuetify
  • ESLint
  • Prettier
  • Jest
  • Storybook

今回はnpxでなくyarnを使います。

プロジェクトを作成

yarn create nuxt-app <アプリケーション名>

対話形式で答えていきます。 このようにしました。

$ yarn create nuxt-app nuxt-typesciprt-starter
yarn create v1.21.1
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Installed "create-nuxt-app@2.15.0" with binaries:
      - create-nuxt-app

create-nuxt-app v2.15.0
✨  Generating Nuxt.js project in .
? Project name nuxt-typesciprt-starter
? Project description My world-class Nuxt.js project
? Author name ikkyu-3
? Choose programming language TypeScript
? Choose the package manager Yarn
? Choose UI framework Vuetify.js
? Choose custom server framework None (Recommended)
? Choose the runtime for TypeScript @nuxt/typescript-runtime
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)ESLint, Prettier, Lint staged files, St
yleLint
? Choose test framework Jest
? Choose rendering mode Universal (SSR)
? Choose development tools jsconfig.json (Recommended for VS Code)

プロジェクトが作成されたら一度起動してみます。

$ cd nuxt-typescript-starter
$ yarn dev

http://localhost:3000/にアクセスしてページが表示されるか確認します。

f:id:Ikkyu:20200403003859p:plain
アクセスしたページ

簡単ですね🎉

TypeScript導入

プロジェクト作成時に使用言語をTypeScriptにしましたが、開発に必要なライブラリや設定を行います。

vue-property-decoratorを使用します。

$ yarn add vue-property-decorator

TypeScriptでvueファイルを読み込めるように設定

プロジェクトのrootディレクトリにshims-vue.d.tsを作成します。

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

vueファイルを変更

components/Logo.vueにscriptタグを追加します。

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class Logo extends Vue {}
</script>

次にcomponents/VuetifyLogo.vueにscriptタグを追加します。

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class VuetifyLogo extends Vue {}
</script>

次にpages/index.vueのscriptタグを変更します。

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import Logo from '~/components/Logo.vue'
import VuetifyLogo from '~/components/VuetifyLogo.vue'

@Component({
  components: {
    Logo,
    VuetifyLogo
  }
})
export default class Index extends Vue {}
</script>

package.jsonを変更

scriptsのlintとlint-stagedを変更します。

{
  "scripts": {
    "lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .", // tsファイルを対象に追加します
    ...
  },
  ...
  "lint-staged": {
    "*.{ts,js,vue}": "yarn lint", // tsファイルを対象に追加します
    ...
  }
}

JestにTypeScriptを導入

yarn add -D @types/jest

次にtsconfig.jsonを変更します。

{
  ...,
  "allowJs": true, // 削除
  ...,
  "types": [
    ...,
    "@types/jest"
  ]
}

allowJs1がtrueだとCannot write file ... because it would overwrite input file.とエラーとなりテストが失敗するため削除します。

test/Logo.spec.jstest/Logo.spec.tsに変更し、テストを実行してみます。

$ yarn test
yarn run v1.21.1
$ jest
ts-jest[versions] (WARN) Version 24.9.0 of jest installed has not been tested with 
ts-jest. If you're experiencing issues, consider using a supported version (>=25.0.
0 <26.0.0). Please do not report issues in ts-jest if you are using unsupported versions.
 PASS  test/Logo.spec.ts
  Logo
    ✓ is a Vue instance (8ms)

------------------|----------|----------|----------|----------|-------------------|
File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------------|----------|----------|----------|----------|-------------------|
All files         |    23.08 |      100 |       25 |       25 |                   |
 components       |       50 |      100 |       50 |       50 |                   |
  Logo.vue        |      100 |      100 |      100 |      100 |                   |
  VuetifyLogo.vue |        0 |      100 |        0 |        0 |             1,6,9 |
 pages            |        0 |      100 |        0 |        0 |                   |
  index.vue       |        0 |      100 |        0 |        0 |     1,66,67,68,76 |
  inspire.vue     |        0 |      100 |        0 |        0 |                 1 |
------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.034s
Ran all test suites.
✨  Done in 3.98s.

テストが通りました✌️

Vuetifyのコンポーネントを使用したvueファイルをテストする場合の設定

jestでTypeScriptを使用できるようになりましたが、vuetifyのコンポーネントをjestで使用できるようにユニットテスト — Vuetify.jsをみながら設定します。

test/setup.jsを作成します。

import Vue from 'vue'
import Vuetify from 'vuetify'

Vue.use(Vuetify)

次に、jest.config.jsに設定を追加します。

module.exports = {
  setupFilesAfterEnv: ['./test/setup.js'], // 追加
  ...
}

試しにtest/index.spec.tsを作成します。

import Vuetify from 'vuetify'
import { mount, createLocalVue, RouterLinkStub } from '@vue/test-utils'
import Index from '@/pages/index.vue'

const localVue = createLocalVue()

describe('Index', () => {
  let vuetify: typeof Vuetify

  beforeEach(() => {
    vuetify = new Vuetify()
  })

  test('is a Vue instance', () => {
    const wrapper = mount(Index, {
      vuetify,
      localVue,
      stubs: {
        NuxtLink: RouterLinkStub
      }
    })
    expect(wrapper.isVueInstance()).toBeTruthy()
  })
})

テストを実行してみます。

$ yarn test
yarn run v1.21.1
$ jest
ts-jest[versions] (WARN) Version 24.9.0 of jest installed has not been tested with 
ts-jest. If you're experiencing issues, consider using a supported version (>=25.0.
0 <26.0.0). Please do not report issues in ts-jest if you are using unsupported ver
sions.
ts-jest[versions] (WARN) Version 24.9.0 of jest installed has not been tested with 
ts-jest. If you're experiencing issues, consider using a supported version (>=25.0.
0 <26.0.0). Please do not report issues in ts-jest if you are using unsupported ver
sions.
 PASS  test/Logo.spec.ts
 PASS  test/index.spec.ts
------------------|----------|----------|----------|----------|-------------------|
File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------------|----------|----------|----------|----------|-------------------|
All files         |    92.31 |      100 |       75 |    91.67 |                   |
 components       |      100 |      100 |      100 |      100 |                   |
  Logo.vue        |      100 |      100 |      100 |      100 |                   |
  VuetifyLogo.vue |      100 |      100 |      100 |      100 |                   |
 pages            |    85.71 |      100 |       50 |    83.33 |                   |
  index.vue       |      100 |      100 |      100 |      100 |                   |
  inspire.vue     |        0 |      100 |        0 |        0 |                 1 |
------------------|----------|----------|----------|----------|-------------------|

Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.503s
Ran all test suites.
✨  Done in 4.47s.

できました👍

Storybookを導入

Storybook for Vueを見ながらStorybookを導入していきます。今回も自動セットアップで行います。

$ npx -p @storybook/cli sb init --type vue

実行すると必要なパッケージがインストールされ、.storybookとstoriesというディレクトリが作成されて、その中にいくつかのファイルが作成されます。

また、package.jsonもstorybook, build-storybookというscriptsが新たに追加されています。
staticディレクトリのファイルを使用できるように、scriptsを以下のように変更します。2

{
  ...
  "scripts": {
    ...
    "storybook": "start-storybook -p 6006 -s ./static",
    ...
  },
  ...
}

一度Storybookを表示してみます。

$ yarn storybook

サーバが起動したらhttp://localhost:6006/にアクセスします。

f:id:Ikkyu:20200403155454p:plain
Storybook

表示できました👍

では次に、StorybookでVuetifyを使用できるようにします。

Vuetify対応

StorybookでVuetifyを使用するため、.storybook/preview.jsを追加します。

import { addDecorator } from '@storybook/vue'
import 'vuetify/dist/vuetify.css'

import Vue from 'vue'
import Vuetify from 'vuetify'

Vue.use(Vuetify)

Vue.component('nuxt-link', {
  props: ['to'],
  methods: {
    log() {
      action('link target')(this.to)
    }
  },
  template: '<a href="#" @click.prevent="log()"><slot>NuxtLink</slot></a>'
})

const vuetifyConfig = new Vuetify({
  icons: { iconfont: 'fa' },
  theme: { dark: false }
})

addDecorator(() => {
  return {
    vuetify: vuetifyConfig,
    template: '<v-app><div><story/></div></v-app>'
  }
})

では次に、JavaScriptで書かれたStorybookをTypeScriptに置き換えます。

TypeScript対応

Storybook用のwebpackをセットアップ

TypeScriptで書かれたstoriesファイルを読み込むために、
.storybook/main.jsを以下のように変更します。3

const path = require('path');

module.exports = {
  stories: ['../**/*.stories.ts'],
  addons: ['@storybook/addon-actions', '@storybook/addon-links'],
  webpackFinal: async config => {
    config.module.rules.push({
      test: /\.ts$/,
      exclude: /node_modules/,
      use: [
        {
          loader: 'ts-loader',
          options: {
            appendTsSuffixTo: [/\.vue$/],
            transpileOnly: true
          }
        }
      ]
    })
    config.resolve.extensions.push('.ts')

    const rootPath = path.resolve(__dirname, '..')
    config.resolve.alias['@'] = rootPath
    config.resolve.alias['~'] = rootPath

    return config
  }
};

これで設定は終わりです。

TypeScriptでStoryを書いてみる

components配下のLogo.vueとVuetifyLogo.vueのStoryをCSF4で書いてみます。

components/index.stories.tsを作成します。
(表示したいコンポーネントと同じディレクトリにStroyを作成するとメンテナンスが簡単になります。5)

※ storiesディレクトリは使用しないので、削除します。

import Logo from './Logo.vue'
import VuetifyLogo from './VuetifyLogo.vue'

export default {
  title: 'Components'
}

export const logo = () => ({
  components: { Logo },
  template: '<logo />'
})

export const vuetifyLogo = () => ({
  components: { VuetifyLogo },
  template: '<vuetify-logo />'
})

yarn storybookでstorybookを起動します。

f:id:Ikkyu:20200403180410p:plain
TypeScriptで書いたStory

できました!

今回作成したプロジェクトファイルはこちらで確認できます。

以上です。

zshでpreztoを使ってみる

以前bashからfishに変えましたが...zshに変えます。

理由は、

  • fishの書き方に慣れなかった(...そもそも覚えようと努力してない😇)
  • macOS Catalinaからデフォルトのログインシェルがzsh

ですね。 ということで、これからはzsh使っていきます!

zshにしたので、「Prezto」を使ってみました。

github.com

とても導入が簡単なので、READMEを見ればできちゃう人がほとんどだと思います。

あくまで自分用のメモです📝

Prezto導入

# 1. zsh起動(デフォルトがzshの場合スキップOK)
zsh

# 2. gitclone
git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"

# 3. 設定ファイルを作成するため以下のコピーしてターミナルに貼り付けて実行  
 (既に .zshrc, .zprofileがある場合はそのファイルを退避しておきます)
setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done

# 4. zshをデフォルトシェルに変更 (デフォルトがzshの場合スキップOK)
chsh -s /bin/zsh

# 5. 新しいウインドウやタブを開きます
# 3で退避したファイルがあれば設定を追加します。

これで導入は終わりです👍

gitモジュールを追加

このままでもいいのですが、gitのブランチ名が表示されてないのでgitモジュールを~/.zpreztorcに追加します。

...
# Set the Prezto modules to load (browse modules).
# The order matters.
zstyle ':prezto:load' pmodule \
   'environment' \
   'terminal' \
   'editor' \
   'history' \
   'directory' \
   'spectrum' \
   'utility' \
   'completion' \
   'prompt' \
   'git' # <- この行を追加!!
...

保存すれば反映されていると思います。

あとはお好みでテーマを変更すれば、とりあえずはって感じでしょうか...😊


[追記]
ディレクトリの色が青色で見にくいので、水色に変更する設定を.zshrcに追加しておいくといいかもです。

# lsコマンドの色を変更
export LSCOLORS=gxfxcxdxbxegedabagacad

設定が楽なのは本当に素晴らしい🎉