Photoruction工事中!

Photoructionの開発ブログです!

Vueのシングルファイルコンポーネント(SFC)を生Javascriptアプリで使おう!

株式会社フォトラクション WEBチーム所属 ジョンです!
Photoruction Advent Calendar 2021の7日目の記事です。

Vueのシングル・ファイル・コンポーネントをSPAではないプロジェクトに使える方法を紹介したいと思います。

目次



フォトラクションでは、アプリケーションの改善を常に行っています。それの一つの計画としては今のアプリケーション内に古く書かれているBackbone.jsとjQueryを最もモダンなフレームワーク、Vue.jsに書き直すことです。

だが一つ問題があり、レガシーコードを書き直しながら新しい機能を増やすことも大事で私たちのリソースをコードの書き直しだけに無駄に使うのがふさわしくない。そのため、Backbone.jsやjQueryで書かれているコードにも新しい機能を追加することもよくあるのです。ソースコードをすべてVue.jsに書き直すついでにBackbone.jsやjQueryをこれ以上増やしたくないので、新しい機能もVueで開発したかったです。

なお、Vueにはいろいろ書き方があります。その一つはSFCを使わずに直接Vueのインスタンスを作ることです。もちろんこのような書き方にしても問題ないですが、VueのSFCのメリットを得られなくなる上に管理もしにくくなります。

<!DOCTYPE html>
<html>
    <head>
        <title>俺のものすごいアプリ</title>
    </head>
    <body>
        <div>
            <!-- 既存コード -->
        </div>
        <div id="my-vue-component">
            <other-component />
        </div>

        
        <script
            src="https://code.jquery.com/jquery-3.6.0.min.js"
            integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
            crossorigin="anonymous"
        ></script>
        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
        <script>
            $(document).ready(() => {
                ...既存コード
            });

            Vue.component('other-component', {
                data() { ... },
                template: '...'
            });
    
            new Vue({
                el: '#my-vue-component',
                template: '...',
                data() { ... },
                methods; { ... }
            });
        </script>
    </body>
</html>


では、早速始めましょう!

前提条件

Node.js - npmからVueやwebpackなどをダウンロードするため、Vueのシングル・ファイル・コンポーネントはそのままJavaScriptに使うことができないため、コンパイルする必要があります。

シングル・ファイル・コンポーネント(Single-File Component)

<template>
    <button>
        <other-component />
        <slot />
    </button>
</templaet>

<script>
import OtherComponent from './OtherComponent.vue';

export default {
    component: {
        OtherComponent
    },
    data() {
        return { ... };
    },
    methods: { ... }
};
</script>

<style scoped>
button {
    padding: 1rem 2rem;
}
</style>

Vueのシングル・ファイル・コンポーネントは基本的に.vueという拡張子が付いています。この.vueファイルにはHTML、JavaScriptCSSをまとめてバンドルすることができます。Vueでシングル・ページ・アプリケーション(SPA)を作ったことがある人には見慣れたコードになると思います。このファイルはSPAを作るときの.vueファイルと全く同じのため、他のコンポーネントやライブラリーをインポートすることはできますし、JavaScriptの代わりにTypeScriptを使うこともできますし、SASSなどを使うこともできます。

ローダーのスクリプト

先ほど作ったSFCを使えるために、ローダースクリプトを作ります。ローダースクリプトはVueコンポネントをアプリケーションにマウントさせるためのスクリプトになります。これがないとSFCを使用できません。

import Vue from "vue"; 
import MyComponent from "../components/MyComponent.vue";

const el = document.querySelector('#some-element'); 
new Vue(MyComponent).$mount(el);

VueでSPAを開発したことがある方は.vueファイルのようにこれも見慣れたコードになっていると思います。Vueのシングル・ページ・アプリケーションのindex.jsに書かれているものと同じです。ここで何をやっているのかというと、まずVueとプロジェクトに使いたいコンポーネントをインポートします。そして、new Vue(MyComponent)で新しいVueのインスタンスを作り、コンポーネントをパラメータとして渡します。それから、.$mount(el)でアプリケーション内の好きな場所にマウントします。

コンパイル

コンポーネントとローダースクリプトを完成したら、コンパイルする必要があります。コンパイルするためにはNode.jsが必要です。Node.jsはまだインストールしていない方には先にインストールしてください。Node.jsをインストールした後次へ進んでください。

Nodeで既に開発している場合

もしNodeですでに開発をしている場合はnpmから必要なパッケージのみインストールしてください。自分のプロジェクトにすでにインストールされているパッケージはインストールしなくていいです。プロジェクトにインストール済みのパッケージはpackage.jsonに確認できます。


まずは、vuevue-loadervue-template-compilerをインストールします。

npm install -D vue vue-loader vue-template-compiler


次はwebpackをインストールします。

npm install -D webpack webpack-cli


最後は.vueの中にあるCSSなどのためのローダーをインストールします。

npm install -D @babel/core babel-loader css-loader vue-style-loader

今回はシンプルにしたいため、SASSなどを使わないですが、もしSASSが必要であればsass-loaderなどをインストールする必要があります。


次は、webpack.config.jsを修正します。


webpackが使われていないプロジェクトにはこのファイルが存在していない可能性あります。であれば、プロジェクトのrootwebpack.config.jsのファイルを作成してください。

const { dirname } = require("path");
const VueLoaderPlugin = require("vue-loader/lib/plugin");

module.exports = {
  entry: {
    "favorite-cat": "./vue/loaders/favoriteCatLoader.js",
  },
  output: {
    filename: "bundle.js",
    path: __dirname,
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
      {
        test: /\.js$/,
        loader: "babel-loader",
      },
      {
        test: /\.css$/,
        use: ["vue-style-loader", "css-loader"],
      },
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
  ],
};

webpack.config.js確認

  1. webpack.config.jsはすでにあるプロジェクトには上記の内容が自分のwebpackコンフィグに存在しているかどうか確認してください。
  2. module.exportsmodule.ruleの順番が大事なので、webpack.config.jsを修正するときに注意をしてください。


新しいコンポーネントやローダースクリプトを追加するときに、module.exportsentryに追加しなければなりません。

module.exports = {
  entry: {
    "comp1": "./loaders/ComponentLoader1.js", 
    "comp2": "./loaders/ComponentLoader2.js",
    "comp3": "./loaders/ComponentLoader3.js",
  },
 ...
}

プロジェクトのrootpackage.jsonを開いて、下記を追加してください。

"scripts": {
    "build": "webpack --config webpack.config.js --mode development"
},


プロジェクトに初めてNodeを使った場合にはwebpack.config.jsみたいにpackage.jsonも存在していない可能性があります。その場合は、下記を実行し、プロジェクト情報を入力してください。

npm init

そのあとは上記のpackage.jsonファイルの編集を行ってください。


最後にはビルドをします。

npm run build


上記のコマンドを実行したら、プロジェクトのrootbundle.jsが生成されます。そのbundle.jsをHTMLの中にインクルードします。

<html>
    <body>
        ...
        <script src="bundle.js" defer></script>
    </body>
</html>


そのあと、HTMLにコンポーネントのマウント先を作ります。
ロードスクリプト#some-elementコンポーネントをマウントしようとしているため、<div id="some-element"></div>を追加すれば、Vueコンポーネントはこのdivの中にマウントされます。

まとめ

自分のプロジェクトはVueのシングル・ページ・アプリケーションではなくてもVueのシングル・ファイル・コンポーネントを使えます。上記でいろいろやりましたが結局3つのステップで済むことができます。

1. Vueコンポーネントを作成
2. ローダースクリプトを作成
3. ビルド

今までのスパゲッティコードを何とかしたいけど、今のプロジェクトをSPAに書き換えることができない人は是非やってみてください!


株式会社フォトラクションでは一緒に働く仲間を募集しています
corporate.photoruction.com
www.wantedly.com