Vue CLI
でセットアップしたプロジェクトで kintone CLI
を利用したカスタマイズ環境を作る目論見です。
どうにかこうにか形になりました。
ざっくり書いていますので読みづらいかも知れません。
こちらは TypeScript 編です。
JavaScript 編は以下をご覧ください。
Vue CLI と kintone CLI の共存を探る(JavaScript 編)
目的
Vue CLI
で作られるプロジェクトの整然さと kintone CLI
で行えるカスタマイズの開発やデプロイの簡易性を両立させる。
TypeScript
での開発を可能とし、@kintone/rest-api-client
を利用する。
kintone UI Component
は諦める。(React
でしか動かないので)
場合により Vuetify
の利用を検討する。
フォーマッティング・lint に関しては以下の方針。
Vetur
はフォーマットを実行させず、シンタックスハイライトなどの役割に専念。
eslint
は静的解析のみ担当。コードフォーマットはしない。
コードフォーマットは Prettier
が実行。
前提
Vue CLI
および kintone CLI
がグローバルインストールされている事。
npm install -g @vue/cli
npm install -g git://github.com/kintone/kintone-cli.git
プロジェクト作成手順
Vue.js プロジェクトをセットアップする
Vue CLI
でプロジェクトを開始する。
vue create vue-cli-kintone-cli-ts
以下の選択肢で進める。
? Check the features needed for your project:
- Babel
- TypeScript
- Vuex
- CSS Pre-processors
- Linter / Formatter
- Unit Testing
? Use class-style component synytax?
Yes
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?
Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
Sass/SCSS (with dart-sass)
? Pick a linter / formatter config:
ESLint + Prettier
? Pick additional lint features:
Lint on save
? Pick a unit testing solution:
Jest
? Where do you prefer placing config for Babel, ESLint, etc.?
In dedicated config files
kintone CLI でアプリを作成する
作成されたプロジェクトを VS Code で開き、ターミナルを起動する。
kintone CLI
でアプリをセットアップする。
kintone-cli create-template
? What type of app you want to create ?
Customization
? Do you want to set authentication credentials ?
Yes
? What is your kintone domain ?
(サブドメイン).cybozu.com
? What is your kintone username ?
(ユーザー名)
? What is your kintone password ?
(パスワード)
? Do you use proxy ?
No
? Do you want to use React ?
No
? Do you want to use TypeScript ?
Yes
? Do you want to use webpack ?
Yes
? What is the entry for webpack ?
main.ts
? What is the app name ?
app
? Do you want to use @cybozu/eslint-config for syntax checking ?
No
? What is the app ID ?
(アプリ ID)
? What is the scope of customization ?
ALL
app
ディレクトリの下にソースが作成される。
開発サーバーをインストールする
この手順だとローカルプレビュー用の local-web-server
がインストールされないため、手動で追加する。
現時点(2020 年 6 月)での最新版は 4.2
だが、このバージョンでは正しく動作しない模様。
kintone-cli
でインストールされるものと同じバージョンの 2.6.1
をインストールする。
yarn add -D local-web-server@2.6.1
その他の関連ツールをインストールする
core-js
が二重に入っている。
いったんアンインストールして最新版を追加。
yarn remove core-js
yarn add core-js
@kintone/rest-api-client
, @kintone/dts-gen
をインストールする。
yarn add @kintone/rest-api-client
yarn add -D @kintone/dts-gen
ESLint・Prettier の設定
以下を参考にする。
続・VSCode 上で vue ファイルに対して ESLint と Prettier が快適に動作する設定
VS Code で ESLint × Prettier のベストかも知れないプラクティス
yarn add -D eslint-config-prettier
プロジェクトルート直下の .eslintrc.js
を修正
module.exports = {
extends: [
// --- 省略
"prettier",
],
};
プロジェクトルート直下に .eslintignore
ファイルを作成。
dist
フォルダを追跡から除外する。
**/dist
標準のフォーマッティングを無効化し、Prettier
が全て担当するようにする。
.vscode/settings.json
に設定を加える。
{
"javascript.format.enable": false,
"typescript.format.enable": false,
"vetur.format.enable": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
.prettierrc
を作る。
設定はお好みで。
{
"semi": false,
"singleQuote": true
}
ディレクトリ構成
プロジェクトルート直下の src
以下のファイルを app/source
に移動。
app/tests/unit
フォルダを作成。
残った src
と public
、tests
は不要なので削除。
app/source/main.ts
をとりあえず以下のようにする
import Vue from "vue";
import App from "./App.vue";
import store from "./store";
Vue.config.productionTip = false;
kintone.events.on("app.record.index.show", (event) => {
console.log("Hello from kintone CLI");
const elem: Element = kintone.app.getHeaderSpaceElement() as Element;
new Vue({
store,
render: (h) => h(App),
}).$mount(elem);
return event;
});
tsconfig.json の設定
プロジェクトルート直下と app
の下に存在する。
プロジェクトルート直下の設定に寄せる。
app
の下にある記述をプロジェクトルート直下の tsconfig.json
にマージする。
この際 include
や paths
、typeRoots
のパスを調整する。
最終的には以下の通りとなる。
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"typeRoots": ["node_modules/@types", "**/source/*.d.ts"],
"types": ["webpack-env", "jest"],
"paths": {
"@/*": ["~/*"]
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
"include": [
"**/source/**/*.ts",
"**/source/**/*.tsx",
"**/source/**/*.vue",
"**/tests/**/*.ts",
"**/tests/**/*.tsx"
],
"exclude": ["node_modules"]
}
app
下の tsconfig.json
は削除ないしリネーム。
babel の設定
ビルドするために @babel/plugin-proposal-decorators
のインストールが必要。
yarn add -D @babel/plugin-proposal-decorators
プロジェクトルート直下に babel.config.js
が、 app
の下に .babelrc
が存在する。
プロジェクトルート直下の babel.config.js
に app/.babelrc
の内容をマージする。
以下のようになる。
module.exports = {
plugins: [
[
"@babel/plugin-proposal-decorators",
{
legacy: true,
},
],
[
"@babel/plugin-proposal-class-properties",
{
loose: true,
},
],
"@babel/plugin-syntax-dynamic-import",
],
presets: [
"@vue/cli-plugin-babel/preset",
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: {
version: 3,
proposals: true,
},
},
],
],
};
その後 app/.babelrc
は削除ないしリネーム。
Webpack の設定
.vue
ファイルをビルドするために vue-loader
, vue-template-compiler
, ts-loader
, url-loader
, file-loader
をインストールする。
また webpack
の設定は開発ビルドとプロダクションビルドで設定を変えたいので、webpack-merge
もインストールする。
加えて、プロダクションビルドではミニファイも行うので、 terser-webpack-plugin
もインストールする。
yarn add -D vue-loader vue-template-compiler ts-loader url-loader file-loader webpack-merge terser-webpack-plugin
webpack
の設定は app
以下のものを使用する。
app/webpack.config.js
を app/webpack.common.js
にリネームし、内容を以下のようにする。
const path = require("path");
const VueLoaderPlugin = require("vue-loader/lib/plugin");
module.exports = {
entry: path.resolve(__dirname, "./source/main.ts"),
resolve: {
extensions: [".ts", ".tsx", ".vue", ".js"],
},
output: {
path: path.resolve(__dirname, "./dist"),
filename: `${path.basename(__dirname)}.min.js`,
},
module: {
rules: [
{
test: /\.vue$/,
use: {
loader: "vue-loader",
options: {
loaders: {
js: {
loader: "babel-loader",
},
},
},
},
},
{
test: /.ts?$/,
exclude: /node_modules/,
use: {
loader: "ts-loader",
options: {
transpileOnly: true,
appendTsSuffixTo: ["\\.vue$"],
happyPackMode: false,
},
},
},
{
test: /.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(jpe?g|png|gif|svg|ico)(\?.+)?$/,
use: {
loader: "url-loader",
options: {
esModule: false,
limit: 10000,
fallback: {
loader: "file-loader",
options: {
name: "img/[name].[ext]",
},
},
},
},
},
],
},
performance: {
maxEntrypointSize: 10000000,
maxAssetSize: 10000000,
},
plugins: [new VueLoaderPlugin()],
};
開発ビルドの設定 app/webpack.dev.js
は以下の通りにする。
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
});
プロダクションビルドの設定 app/webpack.prod.js
は以下の通りにする。
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = merge(common, {
mode: "production",
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: { compress: { drop_console: true } },
}),
],
},
});
新たに app/webpack.config.js
を作り、以下のようにする。
このファイルでビルドターゲットを判定して、適切なファイルをロードするようにする。
module.exports = (env, argv) => {
const mode = argv.mode.includes("development") ? "dev" : "prod";
return require(`./webpack.${mode}.js`);
};
Jest の設定
特にない。
必要に応じてプロジェクトルート直下の jest.config.js
を編集すればよい。
package.json の設定
コマンドの入力を簡略化するため scripts
を以下のようにする。
webpack の設定ファイルもここでコントロールする。
"scripts": {
"dev": "ws --port ****",
"serve-app": "kintone-cli dev --app-name app --watch --localhost",
"devel-app": "webpack --mode development --config app/webpack.config.js",
"build-app": "webpack --mode production --config app/webpack.config.js",
"deploy-app": "kintone-cli deploy --app-name app",
"test:unit": "jest"
},
ws --port ****
は任意のポート番号。
以下の記事で解説している。
kintone CLI をざっくり試す
.gitignore の設定
これまでの流れで app/auth.json
は含まれているはず。
app/dist
も弾くようにする。
その上で、今後仮に app
が増えても大丈夫なようにする。
以下の通り修正。
*/auth.json
*/dist
.vscode/settings.json
は共有したいので、.vscode
の行は削除する。
ここまでで開発準備は終了。
あとはひたすらに開発に注力する。
開発フェーズ
開発・テスト
実際の開発は app/source/
以下のファイルに対して行っていく事になる。
開発モード(ローカルサーバ)で起動
yarn serve-app
ローカルサーバへの参照が kintone アプリに適用され、テストが行えるようになる。
単体テストは以下のように実行。
yarn test:unit
テストファイルは app/tests/unit/
以下に **.spec.ts
のファイル名パターンで記述する。
ビルド
yarn build-app
app
フォルダの下に dist
フォルダが作成されファイルがビルドされる。
ビルドしたファイルを手動で運用環境に適用したい場合に使う。
webpack.prod.js
では TerserPlugin
によりミニファイと console
の除去が行われる。
デプロイ
yarn deploy-app
ビルドとデプロイを同時に実行するコマンド。
ビルドが実行され、終了後に運用環境にデプロイされる。
2 つめ以降のアプリのカスタマイズを作る場合
プロジェクトが複数のアプリカスタマイズで構成される場合、いくつかアプローチがある。
kintone-cli create-template を使う
kintone CLI
的には王道パターンではある。
kintone-cli create-template --app-name (新しいアプリ名)
と実行し、カスタマイズを新規で作成する。
作成されたフォルダに、既存のアプリカスタマイズのファイルをかぶせてやる。(要微修正)
この方法だと改めて依存モジュール類を再取得しに行く動作をするため、時間が掛かる上にせっかく整えた package.json
がまた汚れてしまう。
(core-js
が二重になってしまうなど)
従って、決して良いやり方ではないと思われるが、以下の方法の方が簡単。
既存のアプリをコピーする
既に作成済みのアプリカスタマイズの構成ファイルをコピーして整えていくパターン。
以下、作成済みのアプリカスタマイズを app
、 新しいアプリカスタマイズを second-app
として説明する。
フォルダ・ファイル構成
プロジェクトルート直下に新しいフォルダ second-app
を作成する。
その下に、source
フォルダ、 tests
フォルダを作成する。
second-app/source/
以下に必要に応じて下記フォルダを作る。
- assets
- components
- css
- js
- store
app/
の以下のファイルを second-app/
フォルダにコピーする。
- auth.json
- config.json
- webpack.common.js
- webpack.config.js
- webpack.dev.js
- webpack.prod.js
app/source/
の以下のファイルを second-app/source/
フォルダにコピーする。
- global.d.ts
- shims-vue.d.ts
- shims-tsx.d.ts
認証情報
新しいアプリカスタマイズの認証情報が異なる場合は second-app/auth.json
を編集する。
アプリカスタマイズ情報
second-app/config.json
を開き、以下の部分を編集する。
{
"appID": **, // カスタマイズを適用するアプリID
"appName": "second-app",
"type": "Customization",
"scope": "ALL",
"uploadConfig": {
"desktop": {
"js": ["second-app/dist/second-app.min.js"],
"css": []
},
"mobile": {
"js": ["second-app/dist/second-app.min.js"]
}
}
}
基本的には編集前に app
となっていたものを second-app
に置き換えれば良い。
package.json の修正
package.json
の scripts
にコマンドを追加する。
作成済みの serve-app
, devel-app
,build-app
,deploy-app
をコピーし、app
の部分を second-app
に変えてやる。
合わせると以下の通りになる。
"scripts": {
"dev": "ws --port 8800",
"serve-app": "kintone-cli dev --app-name app --watch --localhost",
"devel-app": "webpack --mode development --config app/webpack.config.js",
"build-app": "webpack --mode production --config app/webpack.config.js",
"deploy-app": "kintone-cli deploy --app-name app",
"serve-second-app": "kintone-cli dev --app-name second-app --watch --localhost",
"devel-second-app": "webpack --mode development --config second-app/webpack.config.js",
"build-second-app": "webpack --mode production --config second-app/webpack.config.js",
"deploy-second-app": "kintone-cli deploy --app-name second-app",
"test:unit": "jest"
},
あとは元のアプリカスタマイズを参考に main.ts
、App.vue
、components/**.vue
等を作り込んでいく。
それなりに作業が多くオペミスが起こりやすいので注意が必要。
Vuetify を利用する場合
Vue CLI
でインストールし、その成果を app
以下に移してやると言う流れ。
※この流れでは IE11 で正しく動作しない。IE11 が要件に入らない場合のみ採用できる。
vue add vuetify
インストールが始まる。
道中でプリセットの選択を求められる。
デフォルトで良い。
? Choose a preset:
Deafult (recommended)
public/index.html
が存在していないと最後にエラーが出るが、インストール自体は正常に行われているので問題ない。
プロジェクトルート直下の src
以下にファイルが作成される。
src/App.vue
を app/source/App.vue
に上書き。
src/components/HelloWorld.vue
を app/source/components/HelloWorld.vue
に上書き。
src/assets/Logo.svg
を app/source/assets/
に移動。
src/plugins
フォルダを app/source/
に移動。
src
フォルダは不要なので削除。
app/plugins/vuetify.ts
を以下のように修正。
import "@mdi/font/css/materialdesignicons.css";
import Vue from "vue";
import Vuetify from "vuetify/lib";
Vue.use(Vuetify);
export default new Vuetify({
icons: {
iconfont: "mdi",
},
});
app/source/main.ts
を以下のように修正する。
import Vue from "vue";
import App from "./App.vue";
import store from "./store";
import vuetify from "./plugins/vuetify";
Vue.config.productionTip = false;
kintone.events.on("app.record.index.show", (event) => {
console.log("Hello from kintone CLI");
const elem: Element = kintone.app.getHeaderSpaceElement() as Element;
new Vue({
store,
vuetify,
render: (h) => h(App),
}).$mount(elem);
return event;
});
app/webpack.coomon.js
に以下の記述を追加。
const VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin");
module.exports = {
// 省略
module: {
rules: [
// 省略
// CSS に対するルールの次に記述する
{
test: /\.s(c|a)ss$/,
use: [
'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sassOptions: {
fiber: require('fibers'),
indentedSyntax: true // optional
}
}
}
]
},
// 省略
// いちばん下に追加する
{
test: /\.(woff|woff2|eot|ttf)(\?.+)?$/,
use: {
loader: 'url-loader',
options: {
esModule: false,
limit: 1000000
}
}
}
]
}
plugins: [
new VueLoaderPlugin(), // 既に記述済み
new VuetifyLoaderPlugin(),
],
};
追加のライブラリをインストールする。
yarn add -D vue-style-loader fibers deepmerge @mdi/font
これで Vuetify
が表示できるようになる。
雑感
Vue CLI
と kintone CLI
を良い感じに共存させようと言う考えから始めたが、あとでライブラリを追加したり多くの設定ファイルに手を入れたりファイルを移動させたりと、結局のところ両者の良さを良い感じに活かすと言うよりはどうにかこうにか妥協点を見出したと言う形になったように思う。
とは言え、Vue.js
の環境をゼロから(Vue CLI
を使わずに)作成するのは今となってはもう面倒この上ないし、kintone CLI
のコマンド一発でデプロイできる便利さは開発工数の削減に効果があるのは間違いなく、無理っくり感が否めない構成とは言えテンプレート化できたのは十分なメリットをもたらすのではなかろうか。
※今回の成果は近日中に GitHub にアップする予定です。
参考
VS Code に Prettier・ESLint・Stylelint を導入してファイル保存時にコードを自動整形させる方法
続・VSCode 上で vue ファイルに対して ESLint と Prettier が快適に動作する設定
VS Code で ESLint × Prettier のベストかも知れないプラクティス
kintone CLI をざっくり試す