LoginSignup
6
6

More than 3 years have passed since last update.

Nuxt.js + TypeScript のプロジェクトに CoreUI を手動クリーンインストール【前編】

Last updated at Posted at 2020-03-03

この記事では npx create-nuxt-app で作成してTypeScript環境を導入したNuxt.jsプロジェクトにCoreUIを組み込む。

なお、Nuxt.jsにCoreUIを組み込んだ非公式のテンプレートが存在するけれど、今回この非公式テンプレートも参考にしながらすべて手動でCoreUIを組み込みこんだ結果わかったのは、この非公式テンプレのどこにCoreUIの要素があるのか全然わからんということだった。非公式テンプレのことは最後にまたすこし書く。

公式テンプレート

https://github.com/coreui/coreui-free-vue-admin-template
↑このリポジトリから取得できるものを、以下、公式テンプレートと呼ぶことにする。基本的にはこれを参考にしながら、同じことをNuxtプロジェクトで実現するにはどうすればよいかを考えていく。

とりあえずインストール

まずは次の2つのモジュールをインストールする。

npm i @coreui/vue @coreui/coreui

これらをインストールしろという指示は、coreui-vueのREADMEにある。ついでに、公式テンプレートのpackage.jsonを覗いて依存関係を見てみると、次のような感じ。

"dependencies": {
  "@coreui/coreui": "~3.0.0",
  "@coreui/icons": "~1.0.1",
  "@coreui/utils": "~1.2.2",
  "@coreui/vue": "~3.0.0",
  "@coreui/vue-chartjs": "~1.0.3",
  "vue": "~2.6.11",
  "vue-router": "~3.1.5",
  "vuex": "~3.1.2"
}

インストール手順に記載のない @coreui/utils@coreui/icons は必須ではなさそう。でもiconsのほうは、名前のとおりCoreUIの独自アイコンが収められており、それらを利用するためにこの記事のあとの方でまたすこし触れる。

CoreUIコンポーネントを使ってみる

CoreUIのコンポーネントをひとつ使ってみよう。公式テンプレートの src/views/base/Cards.vue を参考に、自分のプロジェクトの pages/index.vue に次のような要素を加えてみた。

<div>
  <CCard>
    <CCardHeader>
      カードのタイトル
      <div class="card-header-actions">
        <a
          href="https://coreui.io/vue/docs/components/card-components"
          class="card-header-action"
          rel="noreferrer noopener"
          target="_blank">
          <small class="text-muted">docs</small>
        </a>
      </div>
    </CCardHeader>
    <CCardBody>
      カードの内容
    </CCardBody>
  </CCard>
</div>

でも、CCardというコンポーネントがVueに登録されるような処理をどこにも書いていないので、このままでは当然エラーがでる。

[Vue warn]: Unknown custom element: <CCard> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

これを解決するには、CoreUIをVueにプラグインとして登録すればよい。以下では、それをNuxt.jsプラグインとして実現する。

次の内容で plugins/coreui.ts というファイルを作成し、

import Vue from 'vue'
import CoreUI from '@coreui/vue'

Vue.use(CoreUI)

この(Nuxt.jsとしての)プラグインを読み込むよう nuxt.config.ts を編集。

export default {
  // ...
  plugins: [
    '~/plugins/coreui'
  ],
  // ...
}

これで、コンポーネントが見つからないというエラーは消えるけど、まだスタイルが適用されていない。公式テンプレートでは src/assets/scss 下に共通のスタイル定義 style.scss, _custom.scss, _variables.scss が置かれているので、これらを自分のプロジェクトの assets/scss 下にコピーし、グローバルなスタイル定義として nuxt.config.ts に記載しておく。

export default {
  // ...
  css: [
    '~/assets/scss/style.scss'
  ],
  // ...
}

これでカードがきれいに表示されるようになるはず。

アイコンを使う

アイコン表示につかうコンポーネント CIcon@coreui/icons-vue で定義されているが、これは @coreui/vue から依存されているので、すでにインストールされている。

$ npm ls
my-project@1.0.0 /Users/user/my-project
├── @coreui/coreui@3.0.0
├─┬ @coreui/vue@3.0.0
│ ├── @coreui/icons@1.0.1
│ ├─┬ @coreui/icons-vue@1.3.0
│ │ └── vue@2.6.11 deduped

たとえば pages/index.vue に先ほど追加したカードのヘッダにアイコンを表示するなら、次のように書けばよいようだけど、いまのまま CIcon コンポーネントを使っても、エラーは出ないけれどアイコンは表示されない。

<CCardHeader>
  カードのタイトル
  <div class="card-header-actions">
    <a
      href="https://coreui.io/vue/docs/components/card-components"
      class="card-header-action"
      rel="noreferrer noopener"
      target="_blank"
    >
      <CIcon name="cil-envelope-open" />    <!-- これを追加した! -->
      <small class="text-muted">docs</small>
    </a>
  </div>
</CCardHeader>

CIcon コンポーネントがどのようにアイコンを参照しているかというと、公式テンプレートの src/main.js にある次の記述。この中でインポートされている icons.js は、 @coreui/icons モジュールで定義されているアイコンやプロジェクト固有のアイコン(テンプレではサンプルとしてロゴを読み込んでいる)をexportしており、それをルートコンポーネントのオプションとして設定している。ちなみに、 icons.js がエクスポートする各アイコンはアイコンサイズと表示用のHTMLタグを文字列で保持する長さ2のstring配列データ。

// src/main.js
import { iconsSet as icons } from './assets/icons/icons.js'

new Vue({
  el: '#app',
  router,
  store,
  icons,
  template: '<App/>',
  components: {
    App
  }
})

Nuxt.jsプロジェクトでこの main.js と同じことをやるには、ルートとなっているコンポーネントの生成箇所を、ハックするか、生成直後に次のようなことができればよいのだろうけど、いくら調べてもそれができる適切な方法を見つけることができなかった。誰か教えてほしい。

import { iconsSet as icons } from 'myicons.ts'
$root.$options.icons = icons

仕方がないので、ルートの直下に配置されるレイアウト用コンポーネントの作成タイミングにこのロジックを挿入することにしてみた。以下、その手順。

プロジェクトをTypeScript化しているので、まずは型定義を追加する。 @types/coreui-icons.d.ts ファイルを次の内容で作成し、それを型定義ファイルとして tsconfig.json に追加。

// @types/coreui-icons.d.ts
import Vue from 'vue'

type IconsSet = { string: string[] }

declare module 'vue/types/options' {
  interface ComponentOptions<V extends Vue> {
    icons?: IconsSet
  }
}
// tsconfig.json
"types": [
  "@types/node",
  "@nuxt/types",
  "./@types/coreui-icons" // <- これ
]

つぎに公式テンプレートの src/assets/icons ディレクトリ下のファイル icons.jslogo.js を、プロジェクトの assets/icons ディレクトリにコピーする。TypeScript化するので、 icons.js 改め icons.ts がエクスポートしてるiconsSetに型指定しておく。

// assets/icons.ts
import { IconsSet } from '~/@types/coreui-icons'

export const iconsSet: IconsSet = Object.assign( // ...略

ちなみに、公式テンプレートの icons.js@coreui/icons が提供しているすべてのアイコンをインポートしているわけではないので、必要なアイコンがあればあとで足していけばよいと思う。

最後に layouts/default.vue にコンポーネントを定義して created メソッドを実装する。

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { iconsSet as icons } from '~/assets/icons/icons'

@Component
export default class DefaultLayout extends Vue {
  created() {
    this.$root.$options.icons = icons
  }
}
</script>

これでアイコンが表示されるようになったはず。 icons.ts をうまく組めば CIcon コンポーネントでfont-awesomeなどサードパーティのアイコンも表示できると思う。

レイアウト

次に、公式テンプレートと同じように、コンテンツのまわりにヘッダー・サイドメニュー・フッターを配置するレイアウトを作る。そこまでできればCoreUIを利用する準備が整ったと言えそう。けど、疲れたので続きは改めて。

CoreUIはサイドメニューの開閉ステータス管理にVuexを使っているので、レイアウトと合わせてVuexまわりの設定についても触れる。vue-routerまわりについては特に問題なくサイドメニューなどを作成できる。ただしCoreUIは当然 <nuxt-link> を使ってはいないので、そこにこだわる場合ツラいことになりそう。

→ 書いた。 Nuxt.js + TypeScript のプロジェクトに CoreUI を手動クリーンインストール【後編】

非公式テンプレートについて

リンク再掲。
https://github.com/muhibbudins/nuxt-coreui

非公式テンプレートのpackage.jsonは次のとおりで、Nuxt関連のはさておくとして、bootstrap-vue 以下、公式テンプレートの依存関係に存在しないライブラリを用いている。一方、CoreUI関連モジュールへの依存はない(え?)。

"dependencies": {
  "cross-env": "^5.2.0",
  "nuxt": "^2.0.0",
  "express": "^4.16.3",
  "@nuxtjs/axios": "^5.0.0",
  "@nuxtjs/style-resources": "^0.1.1",
  "bootstrap-vue": "^2.0.0-rc.1",
  "chart.js": "^2.7.1",
  "flag-icon-css": "^2.9.0",
  "font-awesome": "^4.7.0",
  "simple-line-icons": "^2.4.1",
  "vue-chartjs": "^3.1.1"
},

非公式テンプレートが実際に何のコンポーネントを使ってデモサイトを作っているかというと、 bootstrap-vueっぽい。アイコンも依存関係にあるとおり、CoreUIとは関係のない製品を組み合わせている様子。

こんな記事を書いてるけれど別にCoreUI推しというわけではないので、Nuxt.jsにUIフレームワークとしてbootstrap-vueなどを組み合わせたテンプレートとして、これはこれでいいと思うのだけど、なぜこれをNuxt + CoreUI projectと称しているのかが理解できず、頭にハテナが付いてる状態。

6
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6