kamulog

xamarin.formsのネタなど

なるべく最小の Vue.js 単一ファイルコンポーネント 環境構築メモ

vue-cliを使わず極力最小の構成でのVue.js単一ファイルコンポーネントの環境を作るためのメモです。

リポジトリ

https://github.com/muak/VueSingleFileComponentMinimum

完成したもの

hogeクリックで増殖するだけです。

フォルダ構成

  • project root
    • dist
      • js
        • index.bundle.js
      • css
      • images
      • index.html
    • src
      • components
      • stylus
        • site.styl
      • index.js
    • project.json
    • webpack.config.js

手順

  • project初期化
    • npm init
    • 全部enterで問題なし
    • licenseだけはちょっと気をつける
    • package.jsonが生成される
  • 開発専用パッケージインストール
    • npm i -D webpack webpack-cli webpack-dev-server vue-loader vue-template-compiler css-loader npm-run-all
  • AltCssのパッケージインストール(ここではstylus利用)
    • npm i -D stylus stylus-loader autoprefixer-stylus
  • 依存パッケージインストール
    • npm i -S vue ress
  • webpack.config.jsを作成
  • package.jsonスクリプトを追加
  • いくつかの適当なソースを用意する
    • html(index.html)
    • stylus(site.styl)
    • 単一ファイルコンポーネントhoge.vue)
    • エントリポイントのjs(index.js)

パッケージ1行メモ

  • webpack
  • webpack-cli
    • webpack v4から必須。
  • webpack-dev-server
    • 開発用Webサーバー。なくても良いけど便利なのであった方が良い。
  • vue-loader
    • webpackにvueを読み込むもの。
  • vue-template-compiler
  • css-loader
  • stylus
    • AltCssのStylus。
  • stylus-loader
    • webpackでstylusを読み込むもの。
  • autoprefixer-stylus
    • stylusのプラグインでベンダープレフィックスを付けてくれる。
  • vue
    • Vue.js本体。
  • ress
    • リセットcss。別になんでも良い。
  • npm-run-all
    • npmスクリプトを並列処理したり直列処理したりするもの。

webpack.config.js

const Path = require('path');

module.exports = {  
  entry: {
    index: './src/index.js',
  },

  output: {
    filename: 'js/[name].bundle.js', // 出力ファイル名(パスも含めてOK) [name]でentryの名前が入る
    path: Path.resolve(__dirname, 'dist'), // 出力パス 要絶対パスなのでpathモジュールを使用
  },

  // 開発中はsourcemapを出力
  devtool: process.env.NODE_ENV === 'production' ? false : 'source-map',

  module: {
    rules: [
      {
        // .vueファイルを読み込めるようにする
        test: /\.vue$/,
        loader: 'vue-loader',
      },
    ]
  },

  resolve: {
    extensions: ['.js', '.vue'],
    alias: {
      vue$: 'vue/dist/vue.esm.js', //webpack使う場合はこっちを指定する https://jp.vuejs.org/v2/guide/installation.html#%E7%94%A8%E8%AA%9E
    },
  },

  devServer: {
    //webpack-dev-server document root設定
    contentBase: './dist',
  },
}

package.json スクリプト

"scripts": {
    "dev:css": "stylus -w --include-css src/stylus/site.styl -o dist/css -u autoprefixer-stylus",
    "dev:js": "webpack-dev-server --hot --inline --mode development",
    "devAll": "run-p dev:*",
    "build:css": "stylus -c --include-css src/stylus/site.styl -o dist/css -u autoprefixer-stylus",
    "build:js": "NODE_ENV=production webpack --mode production",
    "buildAll": "run-s build:*"
  },

スクリプトの意味

  • dev:css
    • site.stylを監視(-w)して生cssをimport可能に(--include-css)してdist/cssに出力し(-o)、その際autoprefixerを使う(-u)ようにしてstylusを実行。
  • build:css
    • dev:cssに加えてcssを圧縮(-c)するようにする。監視はしない。
  • dev:js
    • webpack-dev-serverを変更即反映(--hot)するようにしてinlineで開発モード(--mode development)で起動する
  • build:js
    • production環境変数を渡しつつwebpackを本番モード(--mode production)で実行する
  • devAll
  • buildAll

※ --modeで本番・開発用のビルドを切り替えられるが、configの中でprocess.env.NODE_ENVがセットされないので、configで使う場合はscriptで明示的に指定する必要がある。

いくつかの適当なソースを用意する

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="/css/site.css" />
  <title>Vue.js 単一ファイルコンポーネント サンプル</title>
</head>

<body>
  <div id="app">
    <header id="header">Vue.js 単一ファイルコンポーネント サンプル</header>
    <div id="main">
        <p>メインですよ</p>
        <hoge></hoge>
    </div>
    <footer id="footer">&copy; 2018 hoge</footer>
  </div>
  <script src="/js/index.bundle.js"></script>
</body>

</html>

bodyはvueの要素にできないので注意。

site.styl

@import "../../node_modules/ress/dist/ress.min.css"
@import "_pccs"
#header
  background-color: $ltg14
  height: 50px
  width: 100%
  padding: 8px
  color: $W
#main
  margin: 0 auto
  padding: 1em
  color: $Gy40
#footer
  background-color: $Gy80
  width: 100%
  padding: 1em
  text-align: center
  color: $Bk

※ _pccsはPCCSカラーシステムの変数を定義したファイル

hoge.vue

<template>
  <div>
    <img src="/images/color_analyzer.svg" alt="" width="30" height="30"><br>
    <button class="hoge_button" @click="onClick()">{{text}}</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      text: 'hoge'
    }
  },
  methods: {
    onClick(){
      this.text += 'hoge';
    }
  }
};
</script>

<style lang="stylus" scoped>
@import '../stylus/_pccs'

.hoge_button
  background-color: $lt6
  border-radius: 3px
  padding: 3px
</style>

外部のcssもインポート可能。

index.js

import Vue from 'vue';
import Hoge from './components/hoge'

new Vue({
  el: '#app',
  components:{'hoge':Hoge},
});

読み込んだコンポーネントhogeタグとして登録する。必ず小文字を指定する。変数名とタグ名は一致する必要はない。

スクリプト実行して開発

npm run devAll

を実行するとwebサーバーを起動しつつstylファイルも監視してコンパイルするようになるので、後はひたすらコードを書いていく。

本番用ビルド

npm run buildAll

これでいろいろ最適化されたものが出力される。

ここまでのpackage.json全体

{
  "name": "vuesample",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev:css": "stylus -w --include-css src/stylus/site.styl -o dist/css -u autoprefixer-stylus",
    "dev:js": "webpack-dev-server --hot --inline --mode development",
    "devAll": "run-p dev:*",
    "build:css": "stylus -c --include-css src/stylus/site.styl -o dist/css -u autoprefixer-stylus",
    "build:js": "NODE_ENV=production webpack --mode production",
    "buildAll": "run-s build:*"
  },
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "autoprefixer-stylus": "^0.14.0",
    "css-loader": "^0.28.11",
    "npm-run-all": "^4.1.2",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.2",
    "vue-loader": "^14.2.1",
    "vue-template-compiler": "^2.5.16",
    "webpack": "^4.1.1",
    "webpack-cli": "^2.0.12",
    "webpack-dev-server": "^3.1.1"
  },
  "dependencies": {
    "ress": "^1.2.2",
    "vue": "^2.5.16"
  }
}

おわりに

ただこれだけの構成をおおまかに理解するまでかなりの時間がかかってしまいました。webpackの設定はまだ理解してないことが多いです。けどひとつひとつ地道に調べて進めていって、何がどういう理由で必要になっているかというのが最低限理解できたように思うので結果良かったかなと思います。

この構成でfirefox chrome safari edgeを使う限りはbabelは不要でした。当然最新の構文を使う場合は必要になってくると思いますが。あとwebpack v4になってから設定ファイルの記述が減ってかなりシンプルになりました。css-loaderの設定もこの構成で使う限りは不要のようでした。

参考サイト

関連ワードで検索したぺージを片っ端から参考にしたので省略させてください。