Nuxt.jsをVue.jsに解体するTips(JavaScriptコンパイル編)

# 背景

- Nuxt.jsで動いているSPAアプリをVue.jsに解体してほしい的な話があり、部分部分をTipsとして投稿します。
- APIはLaravel(6.x)です。なおLaravelとNuxt.jsは同一リポジトリです(なぜ)
- Nuxt.jsは2.9。Vueは2.6.10
- 今回はJavaScriptコンパイル編です。


## LaravelのディレクトリにNuxtのプロジェクトを移行

- resources/jsにNuxtのプロジェクトをそのまま移行します

下記のようなディレクトリ構造になります。

```
resources/js
├── assets
├── components
├── layouts
├── pages
├── plugin
└── store
```

## webpack.mix.jsにaliasを設定する

- Nuxt.jsのモジュールのパスの指定は相対パスではなくaliasを設定してパスを設定しています。
- webpack.mix.jsにデフォルトではそんな機能はないので設定します。

```webpack.mix.js
const mix = require('laravel-mix');

const path = require('path');
mix.webpackConfig({
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.esm.js',
      '~': path.resolve(__dirname, 'resources/js/'),
    },
  },
})
```

## resources/js/app.jsを作成する

- VueやVue Routerなどの読み込み設定ファイルを作成します。

```resources/js/app.js
import Vue from "vue";
import router from '~/router'
import App from '~/App.vue'

new Vue({
  router: router,
  render: h => h(App),
}).$mount('#app')
```

## resources/js/App.vueを作成する

- レンダリングするVueファイルを作成し、resources/js/layouts/default.vueを読み込みます。

resources/js/layouts/default.vue

```resources/js/App.vue
<template>
  <div id="app">
    <layout />
  </div>
</template>

<script>
import Layout from '~/layouts/default'

export default {
  components: {
    Layout
  }
};
```

## resources/js/layouts/default.vueを編集する

- <nuxt />を<router-view />に変更します。

```resources/js/layouts/default.vue
<template>
  <div>
    <router-view />
  </div>
</template>
```

## resources/js/router.jsを作成する

- ルーティングは自動生成されないので手動で設定します。

```resources/js/router.js
import Vue from 'vue'
import Router from 'vue-router'
import Index from '~/pages/index'

Vue.use(Router)

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Index',
      component: Index,
    },
  ],
});
```

## package.jsonの編集

- Laravel-Mixが使えるようにnpm scriptsを編集します。
- [Laravel-Mix公式ドキュメント](https://laravel-mix.com/docs/4.1/installation#npm-scripts)よりスクリプトを参照しています。

```package.json
  "scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
   },
```

## webpack.mix.jsの編集

- resources/js/app.jsのコンパイルを設定します。

```webpack.mix.js
const mix = require('laravel-mix');

const path = require('path');
mix.webpackConfig({
  resolve: {
    alias: {
      vue$: 'vue/dist/vue.esm.js',
      '~': path.resolve(__dirname, 'resources/js/'),
    },
  },
})

mix.js('resources/js/app.js', 'public/js')
```

## 必要なnpmモジュールをインストール

```console
$ npm install cross-env vue vue-router laravel-mix --save-dev
```

## コンパイル

```
$ npm run dev
```

JavaScriptのコンパイルは通るはずです。（画面確認時にはコンソール上でエラーが出まくると思いますが）
プロジェクトによっては不足しているモジュールがあるかもしれません。随時追加してください。

## 画面で確認したい場合

- Sassのコンパイルは未設定ですので、画面崩れまくりますが、画面確認したい時あるかもしれません。

### Laravelのルーティングを編集

- 全部のルーティングをindex.bladeに集約します。

```routes/web.php
Route::get('{any}', function() {
    return view('index');
})->where('any', '.*');
```

### index.blade.phpの編集

- index.blade.phpでapp.jsを読み込みます。

```resources/views/index.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>~~~~</title>
    </head>
    <body>
      <div id="app">
      </div>
      <script src="{{ mix('/js/app.js') }}"></script>
    </body>
</html>
```

これで画面の確認は可能です。