7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AtomAdvent Calendar 2017

Day 25

モダンなAtomパッケージのテンプレート(2017年版)

Last updated at Posted at 2017-12-24

この記事はAtomアドベントカレンダーの25日目の記事です。

2017年のAtomアドベントカレンダーもいよいよラストになってしまいました。
トリということで、2017年におけるパッケージのテンプレート(自分調べ)を紹介いたします。

完成版のリポジトリはこちらです
https://github.com/Kesin11/MyAtomPackageTemplate/tree/v2

ES2015

AtomはかつてCoffeeScriptで作られたことにより話題になったエディタです。当然、拡張機能であるパッケージもCoffeeScriptで書かれていました。
しかし現在ではCoffeeScriptはその役目を果たし終えました。現在ではjsでもパッケージを書くことが可能であり、Atom本体周辺も積極的に過去のCoffeeScriptベースのコードを書き直しています。
リリースノートを見ていただくとコアパッケージでもデカフェイン(カフェインを抜く=js化)やconvert to jsという文字を新しいバージョンが出るたびに見かけます。

自分のパッケージをjs化するにはjsでコードを書き、ファイルの先頭に'use babel'と付けるだけです。
これでclassやPromiseといったES2015の機能を使うことができ、async/awaitも使うことが可能です。

GUI

AtomパッケージのGUIはHTMLとCSSで作ることができます。jsからDOMを操作することさらにリッチなGUIを作ることも可能であり、etchというライブラリを使うことでReactと同じようにJSXでDOMを構築することも可能です。

etchについての詳しい内容はこちらの記事を参照してください。
AtomパッケージでGUIを作る(etchの紹介)

テスト

Atomパッケージは最初にGenerate Packageでひな形を作成したときからテストを実行できる環境が用意されています。
しかし最初から用意されているテストランナーは古いJasmineにAtomが独自に拡張を加えたものであり、現代では古い環境となってしまいました。

現在ではatom-mocha-test-runnerを使うことでこの古いテストランナーをmochaに差し替えることが可能です。
詳しい内容は今年のアドベントカレンダーに投稿した以下の記事を参照してください。

Lint

Atomが提供しているわけではありませんが、自分でESLintをインストールすればlintをかけることも可能です。
自分の場合はこのような.eslintrcを使用しています。

{
    "parserOptions": {
      "ecmaVersion": 2017,
      "sourceType": "module",
      "ecmaFeatures": {
        "jsx": true
      }
    },
    "plugins": [
      "mocha"
    ],
    "env": {
      "node": true,
      "es6": true,
      "mocha": true,
    },
    "extends": [
      # Select your base rules
      "eslint:recommended",
    ],
    "rules": {
      # Add your rule config
      semi: ["error", "never"],
    },
    "globals": {
        "atom": false,
    }
}

ベース部分はasync/await + import + JSXを有効にする設定で、テストコード用にpluginsでmochaを追加しています。
自分はrulesに最低限のチェックとしてeslint:recommendedを使用していますが、好みでairbnbなどメジャーなものに差し替えてもいいでしょう。
少し注意が必要なのは最後のglobalsです。パッケージを作成するにあたって当然atomを使う必要があるのですが、これはグローバル変数として定義されているのでglobalsに追加してlintを無視させる必要があります。

CI

多くのAtomパッケージはCIサービスを使用してテストを実行させています。
CIに乗せる方法はそれほど難しくなく、atom/ciに著名なCIの設定ファイルが置かれているので、それをコピーして各CIでリポジトリの登録をするだけです。個人的にはTravisCIがオススメです。

オススメの理由は、atom/ciの.tarvis.ymlを使うだけでLinux/Mac × stable/betaの4パターンでテストを実行してくれるためです。
CIでのテストではAtomのバージョンは固定されておらず、その時点でのstable, betaバージョンを自動的にダウンロードしてその上でパッケージのテストを実行してくれます。そのためAtomの次のバージョンでAPIに変更が入ってパッケージが壊れてしまう場合には事前に検知することが可能というわけです。当然テストがちゃんと書かれている必要はありますが。

さらにTravisCIではコミットやプルリクのトリガー以外に、定期的にビルドを実行してくれる機能(Cron Jobs)があります。
これは前述のstable, betaをダウンロードしてテストする手法と相性が良く、自分でAtomの更新を逐一チェックしなくても自動的に最新バージョンでパッケージが壊れないかテストし続けてくれます。
Atomはだいたい1ヶ月に1回ペースでバージョンが上がっているので、自分が公開しているパッケージではmasterブランチをRuns weeklyでビルドが走るように設定しています。

↓こんな感じです
travisci_cron_job.png

クラス化

前述のES2015の項で紹介したようにclass構文が使用可能ですが、package.jsonのmainで指定しているパッケージのエントリポイントはオブジェクトがexportされている前提となっているため、パッケージ本体をクラスで書くことはできません。
という制約はあるものの、ようはAtom本体から自分のパッケージが読み込まれたときにクラスではなくてオブジェクトを返せればOKなのでこういう構成に変更してしまいます。

package.json
{
  "name": "my-atom-package-template",
  "main": "./lib/main",
  // 関係ない部分は省略
}
main.js
'use babel'

import MyAtomPackageTemplate from './my-atom-package-template'

export default new MyAtomPackageTemplate()
my-atom-package-template.js
'use babel'

export default class MyAtomPackageTemplate {

  constructor () {
  }

  activate() {
  }

  deactivate() {
  }
}

エントリポイントとしてダミーのmain.jsを設定して、その中でインスタンスを作成してexportしてやります。
これでactivate()やdeactivate()を置くパッケージ本体もクラスとして書くことができます :tada:

まとめ

以上のテクニックを全て詰め込んだリポジトリがこちらです
https://github.com/Kesin11/MyAtomPackageTemplate/tree/v2

今現在パッケージをメンテしている方、これからパッケージを作る方の参考になれば幸いです。
それでは2018年のAtomの発展を期待しつつよいお年を!

7
7
0

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
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?