Help us understand the problem. What is going on with this article?

Figma PluginをVue.js + TypeScript + Sass + Bulmaで開発する

About

Figma Pluginに未来を感じています。

公式ドキュメントには、UIをReactで構築する流れ(Building React)が紹介されています。
しかし、個人的に(会社的に)はVueに慣れていることもあり、以下の環境で構築してみようと試みました。

  • Vue.js
  • TypeScript
  • Sass
  • Bulma

注: Figma Pluginはあまり関係なく、ほぼWebpackの設定の問題ですw

結論

GitHubにコードを置いておきました。

https://github.com/hosopy/figma-plugin-vue-sample

解説: ビルド環境

まず、公式ドキュメントのBundling with Webpackを参考に、Webpackベースのコードベースを構築しました。
公式GitHubにサンプルがあります。

以下は、Bundling with Webpackのコードベースからの差分に関する解説です。

package.json

Vue.js, Sass, Bulmaを使うために必要なパッケージを追加しました。

$ npm install --save vue vue-class-component vue-property-decorator bulma
$ npm install --save-dev node-sass sass-loader vue-loader vue-template-compiler

tsconfig.json

Vue.jsのTypeScript推奨構成に変更しました。

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "strict": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "module": "es2015"
  }
}

webpack.config.js

主な変更点

  • rules
    • vue-loaderの設定を追加
    • ts-loaderのオプションにappendTsSuffixTo: [/\.vue$/]を追加
    • sass-loaderの設定を追加
  • resolve
    • .vueに関する設定を追加
  • plugins
    • VueLoaderPluginを追加
...

const VueLoaderPlugin = require('vue-loader/lib/plugin')

...

module.exports = (env, argv) => ({
  ...

  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            'scss': 'vue-style-loader!css-loader!sass-loader',
            'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
          }
        }
      },
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          appendTsSuffixTo: [/\.vue$/]
        }
      },
      ...
      {
        test: /\.scss$/,
        loader: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          { loader: 'sass-loader' }
        ]
      },
      ...
    ],
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.vue'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },

  plugins: [
    ...
    new VueLoaderPlugin()
  ]
})

解説: UIの実装

Reactのサンプルと同じく、指定した数の正方形を描画するRectangle CreatorをVueで実装してみました。

まず、UIのエントリポイントsrc/ui.htmlsrc/ui.tsです。

src/ui.html
<div id="app"></div>
src/ui.ts
import Vue from 'Vue'
import RectangleCreator from './RectangleCreator'
import './ui.scss'

new Vue({
  el: '#app',
  render (h) {
    return h('rectangle-creator')
  },
  components: {
    RectangleCreator
  }
})

src/ui.scssでは、Bulmaを読み込んで変数の設定などを行います。

src/ui.scss
@charset "utf-8";

@import "~bulma/sass/utilities/initial-variables";
@import "~bulma/sass/utilities/functions";

$brand: #18A0FB;
$primary: $brand;

@import "~bulma/bulma";

最後に、BulmaのCSSを使ってRectangle Creatorを書き換えてみます。

src/RectangleCreator.vue
<template>
  <div class="container">
    <h2 class="title is-4">Rectangle Creator</h2>

    <div class="field">
      <label class="label">Count</label>
      <p class="control">
        <input class="input is-small" type="number" v-model="count">
      </p>
    </div>

    <div class="field is-grouped is-grouped-centered">
      <p class="control">
        <button class="button is-primary is-small" @click="create">
          Create
        </button>
      </p>
      <p class="control">
        <button class="button is-small" @click="cancel">
          Cancel
        </button>
      </p>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

@Component({
  name: 'RectangleCreator'
})
export default class RectangleCreator extends Vue {
  count: number = 5

  create () {
    parent.postMessage({ pluginMessage: { type: 'create-rectangles', count: this.count } }, '*')
  }

  cancel () {
    parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*')
  }
}
</script>

<style lang="scss">
.container {
  padding: 0.75rem;
}
</style>

実行するとこんな感じ

スクリーンショット 2019-08-22 17.05.17.png

参考: 途中ハマったこと

初期提供のfigma.d.tsが古い問題

Figma Desktop Appでプラグインの初期生成したときに提供されるfigma.d.tsは古い?もので問題があり、コンパイルエラーが発生しました。
(2019/08/22現在)

具体的には、LineHeightのインタフェース定義でエラーになります。

interface LineHeight {
  readonly value: number
  readonly unit: "PIXELS" | "PERCENT"
} | {
  readonly unit: "AUTO"
}

GitHubのサンプルのfigma.d.tsを参考に、型エイリアスに書き換えることで解決しました。

type LineHeight = {
  readonly value: number
  readonly unit: "PIXELS" | "PERCENT"
} | {
  readonly unit: "AUTO"
}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away