こんにちは、AIサービス開発部の今枝と申します。
前回もTech BlogでVue.jsに関連した記事を書きましたが、今回もVue.jsに関連する内容です。
前回の記事
やりたいこと
Vuetifyのライブラリに依存しているVueコンポーネントをnpmパッケージとして共有することが目的です。(Vuetifyを使う関係上 Vue 2系(v2.6.11)での内容になります。)
加えて、公開したnpmパッケージのコンポーネントがVuetifyのSASS/SCSS 変数を上書きしてスタイルが変更されることも確認します。
今回、npmパッケージの公開方法などは詳しく扱いません。お好みのnpmレジストリを使用してパッケージ公開してください。
調査の背景
社内の共通の資産としてUIコンポーネントnpmパッケージを作成する場合、UIフレームワーク(Vuetify)に依存したVueコンポーネントが適切にnpmパッケージとして公開できるかを調査しました。
環境
- Vue.js v2.6.12
- vue-cli-plugin-vuetify: 2.3.1
- node: 14.16.1
- yarn: v1.22.5
- @vue/cli 4.5.12
npmパッケージとして公開する方法
環境構築
VueCLIを用いて簡単に環境を構築します。 はじめに、Vueのセットアップをおこないます。
vue create tech-blog-demo Vue CLI v4.5.12 ? Please pick a preset: Manually select features ? Check the features needed for your project: Choose Vue version, Babel, TS, Linter ? Choose a version of Vue.js that you want to start the project with 2.x ? Use class-style component syntax? No ? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes ? Pick a linter / formatter config: Prettier ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, ESLint, etc.? In dedicate d config files ? Save this as a preset for future projects? No
次に Vuetify を導入します。
cd tech-blog-demo vue add vuetify
src/plugins/vuetify.ts が下記のように記載されていることを確認します。 異なっている場合は、下記のように修正してください。
import Vue from "vue"; import Vuetify from "vuetify/lib"; Vue.use(Vuetify); export default new Vuetify({});
コンポーネント・ライブラリ作成用のファイルの追加
src/components/DemoDialog.vue に確認用のコンポーネントを配置します。
<template> <v-dialog v-model="dialog"> <template v-slot:activator="{ on }"> <v-btn v-on="on" color="primary"> Demo Dialog </v-btn> </template> <v-card> <v-card-title>Demo Dialog</v-card-title> <v-card-text> デモ用のダイアログです。 </v-card-text> <v-card-actions> <v-btn @click="dialog = false" color="primary">Close</v-btn> </v-card-actions> </v-card> </v-dialog> </template> <script> export default { name: "DemoDialog", data: () => ({ dialog: false, }), }; </script>
src/build/build.lib.js にライブラリ作成用のファイルの追加します。
参考: Vue コンポーネントを npm パッケージ化する — Vue.js
// Vue.use() によって実行される install 関数を定義 const install = function (Vue) { if (install.installed) return; install.installed = true; // For each matching file name... requireComponent.keys().forEach((fileName) => { const componentConfig = requireComponent(fileName); const componentName = fileName .split("/") .pop() .replace(/\.\w+$/, ""); Vue.component(componentName, componentConfig.default || componentConfig); }); return; }; // Vue.use() のためのモジュール定義を作成 // Create module definition for Vue.use() const plugin = { install, }; // vue が見つかった場合に自動インストールする (ブラウザで <script> タグを用いた場合等) let GlobalVue = null; if (typeof window !== "undefined") { GlobalVue = window.Vue; } else if (typeof global !== "undefined") { GlobalVue = global.Vue; } if (GlobalVue) { GlobalVue.use(plugin); } const requireComponent = require.context( // コンポーネントフォルダの相対パス "../components", // サブフォルダ内を調べるかどうか false, // 基底コンポーネントのファイル名に一致させるのに使う正規表現 /[\w-]+\.vue$/ ); export default plugin;
公開用スクリプトの追加
例としてgithub package の機能を利用してnpmパッケージを公開します。
今回、npm パッケージの公開方法に関しては説明しません。
社内npmレジストリや、GitLab Package Registryにデプロイする際は、適宜修正して利用してください。
package.jsonのScriptに下記のように修正します。
{ "name": "[@github UserName]/tech-blog-demo", "version": "0.1.0", "license": "MIT", "main": "./dist/tech-blog-demo.common.js", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", "build:package": "vue-cli-service build --target lib --name tech-blog-demo src/build/build.lib.js" }, "files": [ "dist" ], "repository": { "type": "git", "url": "https://github.com/[@github UserName]/tech-blog-demo.git" }, ...省略 }
VuetifyのTheme変更のAPIと、VuetifyのSASS/SCSS 変数変更が適応されていることを確認します。
npm パッケージの公開
yarn build:package npm publish
上記のコマンドを入力することで公開完了です。 次にパッケージを読み込む場合の処理を行います。
公開したnpmパッケージの確認
公開したnpm パッケージの動作確認のために、VueCLIで新規にプロジェクトを作成して動作を確認します。
main.js or main.ts で下記のように読み込むことで公開したパッケージのコンポーネントを利用できるようになります。
import Vue from 'vue' import App from './App.vue' import vuetify from './plugins/vuetify'; import TechBlogDemo from '[@github UserName]/tech-blog-demo' Vue.use(TechBlogDemo) Vue.config.productionTip = false new Vue({ vuetify, render: h => h(App) }).$mount('#app')
早速、アプリ内でコンポーネントを表示してみます。
<template> <v-app> <v-main> <v-container fill-height fluid> <v-row align="center" justify="center"> <v-col class="text-center"><DemoDialog/></v-col> </v-row> </v-container> </v-main> </v-app> </template> <script> export default { name: 'App', }; </script>
DevServerで正常にコンポーネント読み込めていることができました!
最後に、VuetifyのAPIが公開パッケージで使用できることを確認します。
Vuetify Themeの変更
Vuetifyには、ThemeプロパティをVuetifyコンストラクタに渡すことで、コンポーネントの色などを簡単に変更可能です。
Theme プロパティを Vuetify コンストラクタに渡して公開したパッケージのコンポーネントの挙動を確認します。
src/plugins/vuetify.js を下記のように修正します。
import Vue from 'vue'; import Vuetify from 'vuetify/lib'; Vue.use(Vuetify); import colors from 'vuetify/lib/util/colors' export default new Vuetify({ theme: { themes: { light: { primary: colors.purple, }, }, }, });
公開したパッケージで使用しているv-btnの色が変更されていることを確認できます。
Vuetify Sass変数の変更
VuetifyではSASS/SCSSカスタム変数を渡すことで、コンポーネントに設定されているデフォルトのSASS/SCSSを上書きすることができます。
SASS/SCSSカスタム変数を変更して公開したパッケージのコンポーネントの挙動を確認します。
src/scss/variables.scss を作成し、下記のように記載します。
// v-btn $btn-font-sizes: ( 'x-small': 40px, 'small': 40px, 'default': 40px, 'large': 40px, 'x-large': 40px );
公開したパッケージで使用しているv-btnのフォントの大きさが変更されていることを確認できます。
おわりに
今回は、Vuetifyに依存したVueコンポーネントをnpmパッケージとして共有する方法について扱いました。社内でUIライブラリとして公開する際は、インターフェイスの設計、保守方法に関して導入前に議論しておく必要があると思います。 npmパッケージを公開して逆に開発工数が増加しないように注意して、ライブラリ化について議論したいと思います。
OPTiMでは、ものづくりが大好きなエンジニアのみなさんを募集しています!