11
11

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 3 years have passed since last update.

kintoneカスタマイズ開発におけるTypeScript導入の流れ

Last updated at Posted at 2019-05-27

kintoneのカスタマイズ開発もモダン化傾向を感じる今日この頃ですが、ちょっと前に「TypeScriptでkintoneカスタマイズ開発をしてみよう」といった記事が掲載されました。この記事の中で言及されているeslintprettierの導入と@kintone/customize-uploaderを利用したカスタマイズのデプロイまでを含めた開発の準備をまとめてみました。

準備

TypeScript関連パッケージのインストール

まずは、記事を参考にTypeScriptに関するパッケージをインストールします。

npm install -D @kintone/dts-gen \
               @babel/core @babel/plugin-proposal-class-properties \
               @babel/preset-env \
               @babel/preset-typescript \
               babel-loader \
               fork-ts-checker-webpack-plugin \
               typescript \
               webpack \
               webpack-cli
npm install -S @babel/polyfill # https://babeljs.io/docs/en/usage#polyfill

ESLint、Prettier関連パッケージのインストール

続けて、eslintprettier周辺のパッケージをインストールします。

npm install -D eslint @typescript-eslint/eslint-plugin \
               prettier eslint-config-prettier eslint-plugin-prettier
npm install -D @cybozu/eslint-config

.eslintrc.jsonは次のように準備します。この辺(1, 2)の内容ベースですが、eslint:@cybozu/eslint-config部分を修正したりしています。Prettierルールとの衝突等考慮点がありますが、まだ試行錯誤中です。

.eslintrc.json
{
  "extends": [
    "@cybozu/eslint-config",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "plugins": [
    "@typescript-eslint"
  ],
  "parser": "@typescript-eslint/parser",
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "parserOptions": {
    "sourceType": "module"
  },
  "globals": {
    "kintone": false
  },
  "rules": {
    "indent": ["error", 2]
  }
}

インデント2で使いたいのでrulesにそれだけ指定しつつ、.editorconfigも生成しておきます。

.editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

TypeScript、Webpack関連の設定ファイルの準備

この辺で、対象のkintoneアプリに合わせたTypeScriptの型定義を生成します。生成されたfields.d.tsはソースを整理するsrcを作成して移動しておきます。

npx kintone-dts-gen --host https://xxx.cybozu.com \
                    -u user \
                    -p password \
                    --app-id 596
mkdir src; mv fields.d.ts src 

記事の通り、tsconfig.jsonbabel.config.jsも準備します。

tsconfig.json
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "esModuleInterop": true,
    "noUnusedLocals": true,
    "noImplicitAny": true,
    "declarationDir": "dist/types",
    "declaration": true,
    "target": "es5",
    "module": "es2015",
    "strict": true
  },
  "files" : [
    "./node_modules/@kintone/dts-gen/kintone.d.ts",
    "./src/fields.d.ts"
  ],
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "dist",
    "dest",
    "node_modules"
  ]
}
babel.config.js
module.exports = function (api) {
    api.cache(true);
    const presets = [
        [
            "@babel/preset-env",
            {
              "useBuiltIns": "usage"
            }
        ],
        "@babel/typescript"
    ];
    const plugins = [
        [
            "@babel/proposal-class-properties"
        ]
    ];
    return {
        presets,
        plugins,
    }
}

webpack.config.jsは次のように整えておきます。

webpack.config.js
const path = require('path');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
  mode: "development",

  entry: {
    "customize" : "./src/customize.ts"
  },

  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist'),
  },

  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.json']
  },

  module: {
    rules: [{ test: /\.(ts|js)x?$/, loader: 'babel-loader', exclude: /node_modules/ }],
  },

  plugins: [
    new ForkTsCheckerWebpackPlugin(),
  ]
};

@kintone/customize-uploaderの設定

そして、@kintone/customize-uploaderのインストールと初期設定を行います。

npm install -D @kintone/customize-uploader
$(npm bin)/kintone-customize-uploader init
dest/customize-manifest.json
{
    "app": "596",
    "scope": "ALL",
    "desktop": {
        "js": [
            "dist/customize.js"
        ],
        "css": []
    },
    "mobile": {
        "js": [
            "dist/customize.js"
        ]
    }
}

npm-run-allを利用したwatchの設定

TypeScript等を含めたビルドを担うwebpackのwatchと、その出力をアップロードするための@kintone/customize-uploaderのwatchを共存するために、@kintone/create-pluginと同様にnpm-run-allを導入しscripts/npm-start.jsを準備します。

npm i -D npm-run-all
scripts/npm-start.js
"use strict";
const runAll = require("npm-run-all");

runAll(["develop", "upload"], {
  parallel: true,
  stdout: process.stdout,
  stdin: process.stdin
}).catch(({results}) => {
  results
    .filter(({code}) => code)
    .forEach(({name}) => {
      console.log(`"npm run ${name}" was failed`);
    })
  ;
});

package.jsonとフォルダ構成を確認

最後にpackage.jsonscriptsに後々の作業を楽にできるように幾つか足して、次のようにしておきます。update:fieldsはパスワード埋め込みになるので、ちょっと悩ましいところです。startではtsファイルの変更で、webpackのバンドルからjsファイルのデプロイまで行えるようになります。

package.json
{
  "name": "kintone-customize-bolierplate-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "update:fields": "npx kintone-dts-gen --host https://xxx.cybozu.com -u user -p passowrd --app-id 596; mv fields.d.ts src",
    "start": "node scripts/npm-start.js",
    "upload": "kintone-customize-uploader --watch dest/customize-manifest.json",
    "develop": "npm run build -- --watch",
    "build": "webpack",
    "build:prod": "webpack --mode production",
    "lint": "eslint src/*"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.4.4",
    "@babel/plugin-proposal-class-properties": "^7.4.4",
    "@babel/preset-env": "^7.4.4",
    "@babel/preset-typescript": "^7.3.3",
    "@cybozu/eslint-config": "^4.0.1",
    "@kintone/customize-uploader": "^1.5.3",
    "@kintone/dts-gen": "^1.0.2",
    "@typescript-eslint/eslint-plugin": "^1.9.0",
    "babel-loader": "^8.0.6",
    "eslint": "^5.16.0",
    "eslint-config-prettier": "^4.3.0",
    "eslint-plugin-prettier": "^3.1.0",
    "fork-ts-checker-webpack-plugin": "^1.3.3",
    "npm-run-all": "^4.1.5",
    "prettier": "^1.17.1",
    "typescript": "^3.4.5",
    "webpack": "^4.31.0",
    "webpack-cli": "^3.3.2"
  }
}
❯ tree -L 1 -a
.
├── .editorconfig
├── .eslintrc.json
├── .git
├── .gitignore
├── babel.config.js
├── dest
├── dist
├── node_modules
├── package-lock.json
├── package.json
├── scripts/npm-start.js
├── src
├── tsconfig.json
└── webpack.config.js

以上で設定は終了です。

kintoneカスタマイズコーディング

準備が整ったら、記事にあるように次のようにコーディングを進めましょう。

src/customize.ts
const HANDLE_EVENT = "app.record.create.show";
interface KintoneEvent {
    record: kintone.types.SavedFields;
}
kintone.events.on(HANDLE_EVENT, (event: KintoneEvent) => {
    event.record.単価.value = "1";
    event.record.ユーザー選択.value = [{name: "名前", code: "コード"}];
    return event;
});

所感

  • kintoneの型が収められているkintone.d.tsが便利です!
    • kintone.d.tstsconfig.jsonを見るとfilesfields.d.tsと共に./node_modules/@kintone/dts-gen/kintone.d.tsとして指定されています
    • これだけreferenceタグで読み込んで使うというのも便利です
  • kintoneでよくある複数のアプリを対象にしたカスタマイズでは、kintone-dts-genする際に--namespacefields.d.tsを作り分けて対応すると良さそうです(ドキュメントより)
  • kintoneのカスタマイズ開発でもコード量が多くなることが見込まれるケースには、TypeScriptの利用は有効かと思いました。TypeScriptでの一般的なメリットをkintoneカスタマイズ開発でも享受できます
    • 逆に、コード量が増える見込みがないケースでは無理して使う必要もなさそうかなぁと思いました(ただ、kintone.d.tsの利用は幸せになれると思います)
    • 同様に、kintoneカスタマイズ初学者の方はTypeScript自体の導入・学習コストが高く感じられると思いますし、いきなりコード量が多いカスタマイズに挑むケースは考えづらいとすれば、従来のJavaScriptのカスタマイズに慣れてきて、Webpackを利用する開発が必要になったり、そのメリットが見えてくるケースに遭遇するようになったらTypeScript導入を検討頂くと良いのかなと思いました
  • ESLint、Prettierの設定が良い感じなのかが自信なく、試行錯誤を続けたいと思います

参考にした情報

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?