vue-cli 3.0で始めるPWAとVue.jsのconfig周り

Vue.js 7月 15, 2018

みなさん、Vue.jsやってますか?僕はバリバリです(?)

最近vue-cliの3系が出て、npmもvue-cliから@vue/cliに変わりましたね。導入からディレクトリ構成も結構変わりました(webpack.configがないとか)。

大きな変更点として、webpack4系の対応と、template形式からplugin形式のカスタマイズに変更になりました。この辺りはこのスライドなどが参考になると思います。

vue-cli 3.0時代のNuxt.js

Nuxt.jsも話題なのですが、今回は、今僕が開発中のプロジェクトの設定を丸々リプレースするための参考に、普通のVue.jsでプロジェクトを作成してみようと思います。

また、設定周りで変わったところも多いので(process.envとかcommon.scssの読み込みとか)、Tipsとして最後の方に載せておきます。

環境

  • node: v10.6.0
  • npm: 6.1.0

ちなみに僕はnodeのバージョン管理にanyenvからのndenvを使用しています。とても使いやすい。

プロジェクト作成

早速いきましょう

-% npm install -g @vue/cli
----------- 中略 -----------
+ @vue/cli@3.0.0-rc.4
added 692 packages from 471 contributors in 30.393s

-% vue -V
3.0.0-rc.4

インストールができました。
それではプロジェクトを作成します。ここで、一番最初の選択肢はDefaultではなくManuallyにすることに気を付けてください。

-% vue create vue-cli-3-pwa-sample
Vue CLI v3.0.0-rc.4
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): SCSS/SASS
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Pick a unit testing solution: Mocha
? Pick a E2E testing solution: Cypress
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? Yes
? Save preset as:
? Pick the package manager to use when installing dependencies: NPM

とまあ、こんな感じで設定していくと良いと思います。2つ目は**「Babel, PWA, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E」**と、TypeScript以外を選択しています。まあ、細かいところはお好みで。

⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project vue-cli-3-pwa-sample.
👉  Get started with the following commands:

 $ cd vue-cli-3-pwa-sample
 $ npm run serve

はい、プロジェクトが作成されました。



起動

早速起動してみましょう。

-% cd vue-cli-3-pwa-sample
-% npm run serve

 INFO  Starting development server...
 98% after emitting CopyPlugin

 DONE  Compiled successfully in 5830ms                                                                                                        7:20:11 PM

  App running at:
  - Local:   http://localhost:8080/
  - Network: http://192.168.20.4:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

起動したので、localhost:8080にChromeでアクセスしてみましょう。

また、もう一つNetwork: http://192.168.20.4:8080/があるため、LAN内からIPでもアクセスできるようです。試しに、僕のAndroid端末でアクセスしてみましょう。

素晴らしい!!これで端末デバッグもやりやすいですね!!



構成

root/
├ node_modules/
├ public/
│ ├ img/icons/
│ ├ favicon.ico
│ ├ index.html      - SPAの起点になるhtmlファイル
│ ├ manifest.json   - PWA用のmanifestファイル
│ └ robots.txt
├ src/
│ ├ assets/
│ ├ components/     - 汎用性の高いvueファイルはここに
│ ├ views/          - ページに相当するvueファイルはここに(パス名=ファイル名にすると良い)
│ ├ App.vue         - SPAの起点になるvueファイル
│ ├ main.js         - Vueの基本設定を記述、App.vueをhtmlに紐付ける
│ ├ registerServiceWorker.js  - サービスワーカーの設定
│ ├ router.js       - ルーティング設定
│ ├ store.js        - Vuexの設定
│ └ robots.txt
├ tests/
│ ├ e2e             - E2Eテスト
│ └ unit            - Unitテスト
├ .browserslistrc   - CSS3のベンダープレフィックスを自動で付与する際の設定
├ .eslintrc.js      - ESLintの設定
├ .gitignore
├ .postcssrc.js     - PostCSSの設定だが、ここではautoprefixerの適用
├ babel.config.js   - Babelの設定
├ cypress.json      - E2Eテストフレームワークの設定
├ package.json
├ package-lock.json
└ README.md

ざっと見るに、publicに静的ファイルを設置し、srcにはコンパイルなどが必要なファイルを置くようだ。

ここでindex.htmlを見ると、<%= BASE_URL %>favicon.icoという記述があるので、BASE_URLpublic直下にアクセスできるみたい。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>vue-cli-3-pwa-sample</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but vue-cli-3-pwa-sample doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>


各種設定

さて、ライブラリや設定周りも少し紹介します。

package.json

VueでWebアプリを作成するにあたり、使用頻度の高いライブラリです。(※)のものは、前述の手順で既にinstallされているものです。

  • vue-route (※): SPAのルーティング
  • vuex (※): プロジェクト全体の共通リソースを管理するのに便利
  • vuex-persistedstate: localStrageを使ったvuexリソースの永続化
  • buefy: BulmaというCSSフレームワークを、Vue向けにコンポーネント化してくれたもの。エフェクトがあるので、Bulmaよりも良さげ
  • ElementUI: 汎用性の高いコンポーネントを提供してくれている(が、ちとサイズがでかい
  • vee-validate: inputバリデーション
  • vue-i18n: 国際化
  • vue-moment: 日付を扱うmoment.jsのvueプラグイン
  • webpack-bundle-analyzer: ライブラリのサイズ関係を一目できるやつ

router.js

特にないが、デフォルトがhashモードなので、historyモードにしておくと良い。

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: About
    }
  ]
})

store.js

永続化したいなら以下のように

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  plugins: [createPersistedState()]
})

process.envどうするの

webpack4からno configを謳っているが、envは書きたい。ので、以下のファイルをルートに設置する。

VUE_APP_API_URL=https://localhost:9000/v1
VUE_APP_DEBUG=true
VUE_APP_API_URL=https://api.hoge.com/v1
VUE_APP_DEBUG=false

ポイントは、VUE_APP_を頭に付けること。これがないとprocess.envに入ってこない。

もちろん取り出すときもprocess.env.VUE_APP_API_URLでアクセスする。

全vueファイルで共通のCSSを読み込みたい

以前のwebpackを使うバージョンでは、webpack.configに以下のような設定を書いていたと思う。

scss: generateLoaders('sass').concat({
  loader: 'sass-resources-loader',
  options: {
    resources: path.resolve(__dirname, '../src/assets/scss/common.scss')
  }
})

さて、本バージョンからはwebpack.configがないため、vue.config.jsというファイルをルートに作成し、以下のように記述すれば良い。

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        data: `@import "@/assets/scss/common.scss";`
      }
    }
  }
}

webpack-bundle-analyzer

vue.config.jsついでに、こいつを使いたい場合は以下のように書けば良い。

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        data: `@import "@/assets/scss/common.scss";`
      }
    }
  },
  configureWebpack: {
    plugins: [new BundleAnalyzerPlugin()]
  }
}


おわりに

設定周りは調べる時間が無駄なので、参考にしていただければと思います。

あれ、PWA...??

slont

金融ベンチャーでWebエンジニア。美と酒とTechで生きてる。Vue.jsが至高。Elixir好き。個人事業とWebアプリ案件もやってます。 アプリ→https://app.cullet.me Android→https://play.google.com/store/apps/details?id=net.maytry.cullet.android

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.