2
1

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 1 year has passed since last update.

GoogleAppScriptでVue.jsの単一ファイルコンポーネントをつかう

Last updated at Posted at 2022-04-24

GoogleAppScriptでVue.jsが使えると知ったので使ってみた。
しかし、そのままではVue.jsの単一ファイルコンポーネント(single-file component)は使えず、一つのhtml内にすべて記述する必要がある。
Vue.jsを使っておきながら単一ファイルコンポーネントが使えないとなると少しもったいない。そこで、なんとかgasで単一ファイルコンポーネントが使えるよう模索したのでここに示す。

※ ある程度のgasとvueの知識が必要

プロジェクト構成

gasプロジェクトは以下の構成とする

.
├── main.gs
├── index.html
└── app.vue

htmlを取得できるようにする

ページにアクセスできるようにdoGetメソッドを作る。
今回はデモなので細かい設定は省略しindex.htmlをそのまま返すようにする。

main.gs
function doGet() {
  return htmlOutput = HtmlService.createTemplateFromFile("index").evaluate();
}

AppScriptエディタ右上の"デプロイ"から、ウェブアプリとしてデプロイしておく。
ここまでは普通の gas + html

GoogleAppScriptにVue.jsを導入する

index.htmlにvue導入処理を記載する。
cdn版Vue.jsは一行で導入できる!すごい!

index.html
<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <h1>{{message}}</h1>
    </div>
  </body>
  <script>
    new Vue({
      el: '#app',
      data () { return { message: 'Hello GAS + Vue.js' } }
    });
  </script>
</html>

この状態でデプロイ先リンクを開くと"Hello GAS + Vue.js"と出力される。

ここまでは普通の gas + vue

単一ファイルコンポーネントを読み込む

さて本題の単一ファイルコンポーネントの読み込みだ。

事前にapp.vue.htmlを単一ファイルコンポーネントの形式にしておく。
ここでは引数messageを受け取って表示するだけのコンポーネントとする。

app.vue.html
<template>
  <h1>
    {{message}}
  </h1>
</template>
<script>
module.exports = {
  props: ['message']
}
</script>

index.htmlから単一ファイルコンポーネントを読み込むためにhttp-vue-loaderを導入する。
http-vue-loaderは単一ファイルコンポーネントのURIを受け取ってコンポーネントを生成するため、これを使って別ファイルに書き出したコンポーネントを読み込む。

index.html
<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script src="https://unpkg.com/http-vue-loader"></script> <!-- 追加 -->
  </head>
  <body>
    <div id="app">
      <App :message = "message"></App>
    </div>
  </body>
  <script>
    // 追加
    const App = httpVueLoader(
      'data:text/plain,' + 
      '<?!= encodeURIComponent(HtmlService.createTemplateFromFile('app.vue').evaluate().getContent()).replace(/[\'']/g,"\\'") ?>'
      );
    new Vue({
      el: '#app',
      data () { return { message: 'Hello GAS + Vue.js + single-file component' } },
      components:{ // 追加
        App
      }
    });
  </script>
</html>

ミソは以下の部分

const App = httpVueLoader(
  'data:text/plain' + 
  '<?!= encodeURIComponent(HtmlService.createTemplateFromFile('app.vue').evaluate().getContent()).replace(/[\'']/g,"\\'") ?>'
      );

app.vue.htmlの中身を文字列として取得

HtmlService.createTemplateFromFile('app.vue').evaluate().getContent()

取得した文字列をURIにエンコード

encodeURIComponent(...)

エンコードした文字列の中のシングルクオートをエスケープ

....replace(/[\'']/g,"\\'")

<?!= ~ ?>の中の文字列はgasのスクリプトとして処理されたのち埋め込まれるため、

const App = httpVueLoader('data:text/plain,{app.vue.htmlの中身}')

のようになり、URIをhttpVueLoaderで読み込んでコンポーネントオブジェクトが生成できる。

読み込んだコンポーネントはvueのコンポーネントとして普通に使うことができる。

この状態でデプロイページにアクセスすると、"Hello GAS + Vue.js + single-file component"と表示されるはずだ。
これで、単一ファイルコンポーネントをgasで扱うことができるようになった。

Gasに変換処理を任せる

const SomeComponent = httpVueLoader(
  'data:text/plain' + 
  '<?!= encodeURIComponent(HtmlService.createTemplateFromFile('some_component.vue').evaluate().getContent()).replace(/[\'']/g,"\\'") ?>'
      );

単一ファイルコンポーネントが利用できるようになったのはいいが、コンポーネントを読み込むたびにこんな長文を書いてられないので、Gas側でできるところまでメソッド化する。

main.gs
function doGet() {
  return htmlOutput = HtmlService.createTemplateFromFile("index").evaluate();
}

// 追加
/** @type { (name:string) => string } */
function getVueURI(name) {
  return "'data:text/plain," + encodeURIComponent(HtmlService.createTemplateFromFile(name).evaluate().getContent()).replace(/[\'']/g,"\\'") + "'"
}

ファイル名からURIを構成して返却するメソッドgetVueURIを作る。やっていることは先ほどと同じ。
それに合わせてindex.htmlを書き換えると以下のようになる。
httpVueLoaderだけはクライアント側で実行しないといけないため、このような構成となった。

index.html
<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
    <script src="https://unpkg.com/http-vue-loader"></script>
  </head>
  <body>
    <div id="app">
      <App :message = "message"></App>
    </div>
  </body>
  <script>
    // 変更
    const App = httpVueLoader(<?!=getVueURI('app.vue')?>)
    new Vue({
      el: '#app',
      data () { return { message: 'Hello GAS + Vue.js' } },
      components:{
        App
      }
    });
  </script>
</html>

おわりに

これでGoogleAppScriptでvueの単一ファイルコンポーネントが使えるようになった。
あとはvuexでもvuetifyでも使って好きに開発できる!

追記:著者はgas/vueともにあまり詳しくはないので、ミスやほかの方法があればコメントにて教えてください。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?