■目次
概要基本の手順でアプリを作成プロジェクトでアプリを作成ExpressサーバサイドレンダリングVagrant上で実行するAWSのEC2上で実行する
■概要
Nuxt.js - ユニバーサル Vue.js アプリケーション https://ja.nuxtjs.org/ はじめに - NuxtJS https://ja.nuxtjs.org/guide/ 「Vue.js」でWebページを作成できるフレームワーク「Nuxt.js」最初の一歩 (1/3):CodeZine(コードジン) https://codezine.jp/article/detail/11566 分かりやすそう TypeScript と Redux に入門しながら Next.js でサンプルアプリケーションを作ってみた - Qiita https://qiita.com/monzou/items/8ff07258a42042075d7b Next.js ... Reactを使ったフレームワーク Nuxt.js ... Vueを使ったフレームワーク Nuxt.js使ってみた - Qiita https://qiita.com/_takeshi_24/items/224d00e5a026dbb76716 yarnとは - Qiita https://qiita.com/lelouch99v/items/c97ff951ca31298f3f24 npmに代わるものらしい GitHubがnpmの買収を発表、JavaScriptのパッケージ管理サービス。将来的にはGitHubとnpmを統合へ − Publickey https://www.publickey1.jp/blog/20/githubnpmjavascriptgithubnpm.html npmが無くなってyarnになる…ということは無さそう ■メモ 東京都 新型コロナウイルス感染症対策サイト GitHub https://github.com/tokyo-metropolitan-gov/covid19 node.js + yarn + Nuxt.js で作られているみたい 東京都の新型コロナ対策サイトはなぜNuxtJSだったのか? ─ シビックテックのベストプラクティス - エンジニアHub https://employment.en-japan.com/engineerhub/entry/2020/05/19/103000 開発体制などについて触れられている レガシーシステムの大規模リプレイスで分かった「Vue.jsでSPAならNuxt.jsが有力」 - エンジニアHub https://employment.en-japan.com/engineerhub/entry/2018/09/25/110000 大規模リプレイスについて触れられている 記事投稿機能のNuxt化が完了しました Nuxt移行プロジェクト リリースノート (2020年3月)|こんぴゅ|note https://note.com/konpyu/n/n4b6e3ea0bf31 Angular.jsからNuxtへ刷新しているらしい Nuxt.js+Firebaseの認証・認可を実装した雛形プロジェクトを公開しました - Qiita https://qiita.com/Yuta_Fujiwara/items/3c57c99399891ae3ff38
■基本の手順でアプリを作成
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\first\package.json
{ "name": "first-app", "scripts": { "dev": "nuxt" } }
>cd C:\localhost\home\refirio_org\public_html\memos\nuxtjs\first >npm install -save nuxt >npm run dev ───────────────────────────────────────────── │ │ │ Nuxt.js v2.12.2 │ │ Running in development mode (universal) │ │ │ │ Listening on: http://localhost:3000/ │ │ │ ───────────────────────────────────────────── i Preparing project for development 15:18:16 i Initial build may take a while 15:18:16 WARN No pages directory found in C:\localhost\home\refirio_org\public_html\memos\nuxtjs\first. Using the default built-in page. √ Builder initialized 15:18:17 √ Nuxt files generated 15:18:17 √ Client Compiled successfully in 7.99s √ Server Compiled successfully in 6.95s i Waiting for file changes 15:18:26 i Memory usage: 192 MB (RSS: 252 MB) 15:18:26 i Listening on: http://localhost:3000/ 15:18:26 以下にアクセスすると「The Vue.js Framework」というデフォルトページが表示される http://localhost:3000/ ■ページの作成 以下にファイルを作成し、nuxt を停止させてから再度起動する 画面に作成ページの文言が表示される C:\localhost\home\refirio_org\public_html\memos\nuxtjs\first\pages\index.vue
<template> <div> <h1>Hello!</h1> <p>This is Next.js sample page.</p> </div> </template>
■プロジェクトでアプリを作成
>cd C:\localhost\home\refirio_org\public_html\memos\nuxtjs >npx create-nuxt-app test_project create-nuxt-app v2.15.0 Generating Nuxt.js project in test_project Project name test_project Project description My dazzling Nuxt.js project Author name refirio Choose programming language JavaScript Choose the package manager Npm … yarn から Npm に変更した Choose UI framework None Choose custom server framework None (Recommended) Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose test framework None Choose rendering mode Universal (SSR) Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection) >cd test_project >npm run dev ───────────────────────────────────────────── │ │ │ Nuxt.js v2.12.2 │ │ Running in development mode (universal) │ │ │ │ Listening on: http://localhost:3000/ │ │ │ ───────────────────────────────────────────── i Preparing project for development 16:22:24 i Initial build may take a while 16:22:24 √ Builder initialized 16:22:24 √ Nuxt files generated 16:22:24 √ Client Compiled successfully in 8.33s √ Server Compiled successfully in 7.27s i Waiting for file changes 16:22:34 i Memory usage: 196 MB (RSS: 253 MB) 16:22:34 i Listening on: http://localhost:3000/ 16:22:34 以下にアクセスすると「test_project My spectacular Nuxt.js project」というデフォルトページが表示される http://localhost:3000/ ■プロジェクト作成時にエラー 「Choose the package manager」 で「yarn」を「Npm」に変更したが、yarnのままだとプロジェクト作成時に以下のエラーになった 詳細は要調査 - Installing packages with yarnTrace: Error: spawn yarn ENOENT at notFoundError (C:\Users\refirio\AppData\Roaming\npm-cache\_npx\12656\node_modules\create-nuxt-app\node_modules\sao\node_modules\cross-spawn\lib\enoent.js:6:26) at verifyENOENT (C:\Users\refirio\AppData\Roaming\npm-cache\_npx\12656\node_modules\create-nuxt-app\node_modules\sao\node_modules\cross-spawn\lib\enoent.js:40:16) at ChildProcess.cp.emit (C:\Users\refirio\AppData\Roaming\npm-cache\_npx\12656\node_modules\create-nuxt-app\node_modules\sao\node_modules\cross-spawn\lib\enoent.js:27:25) at Process.ChildProcess._handle.onexit (internal/child_process.js:275:12) { code: 'ENOENT', errno: 'ENOENT', syscall: 'spawn yarn', path: 'yarn', spawnargs: [ 'install' ] } at C:\Users\refirio\AppData\Roaming\npm-cache\_npx\12656\node_modules\create-nuxt-app\cli.js:46:17 at processTicksAndRejections (internal/process/task_queues.js:97:5) ■ファイル構成 プログラム作成において重要になるのは以下のフォルダ components layouts pages 見た目を調整する際は以下のフォルダも関係してくる assets static 以下を編集することで、初期ページの内容を変更できる layouts\default.vue pages\index.vue components\Logo.vue ■コンテンツの編集 C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\index.vue
<template> <section class="container"> <h1>{{ title }}</h1> <p>{{ message }}</p> <hr> <pre>{{ now }}</pre> </section> </template> <script> export default { data: function() { return { title: 'Hello', message: 'This is a message', now: 'wait...' }; }, created: function() { setInterval(() => { var d = new Date(); this.now = d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds(); }, 1000) } } </script> <style> .container { padding: 5px 10px; } h1 { color: #345980; } pre { padding: 10px; background-color: #efefef; } hr { margin: 10px 0; } </style>
■他のページを追加 pages内にファイルを作成すると、自動的にページとして認識される C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\index.vue
<router-link to="/other">Go to Other</router-link>
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\other.vue
<template> <section class="container"> <h1>{{ title }}</h1> <p>{{ message }}</p> <hr> <router-link to="/">Go to Top</router-link> </section> </template> <script> export default { data: function() { return { title: 'Hello', message: 'これは別のページです。' }; } } </script> <style> .container { padding: 5px 10px; } h1 { color: #345980; } hr { margin: 10px 0; } </style>
■パラメーターを取得 pages内に階層ありでファイルを作成すると、その名前をもとに値を取得できる C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\index.vue
<router-link to="/test/test1/test2/test3">Go to Other</router-link>
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\test\_x\_y\_z.vue
<template> <section class="container"> <h1>{{ title }}</h1> <p>{{ message }}</p> <hr> <router-link to="/">Go to Top</router-link> </section> </template> <script> export default { data: function() { return { title: 'Hello' }; }, computed: { message: function() { let x = this.$route.params.x; let y = this.$route.params.y; let z = this.$route.params.z; return 'x=' + x + ', y=' + y + ', z=' + z; } } } </script> <style> .container { padding: 5px 10px; } h1 { color: #345980; } hr { margin: 10px 0; } </style>
■Vuexで状態を管理する store内にファイルを作成し、各ページから参照する値を用意できる 読み込んで反映されない場合、サーバの再起動とページの再読み込みを試す C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\store\index.js
import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: function() { return { message: 'これはストアメッセージです。', }; } }) } export default createStore
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\index.vue
<p>{{ $store.state.message }}</p>
■ミューテーションで値を変更する mutationsで命令を定義し、それを呼び出すことでstateの内容を変更できる C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\store\index.js
import Vuex from 'vuex' const createStore = () => { return new Vuex.Store({ state: function() { return { message: '数値をカウントします。', counter: 0, }; }, mutations: { count: function(state) { state.counter++; }, reset: function(state) { state.counter = 0; } } }) } export default createStore
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\index.vue
<template> <section class="container"> <h1>{{ title }}</h1> <p>{{ message }}</p> <p>{{ $store.state.message }}</p> <hr> <div class="counter" @click="$store.commit('count')" @click.ctrl="$store.commit('reset')" > clicked: {{ $store.state.counter }} </div> </section> </template> <script> export default { data: function() { return { title: 'Hello', message: 'This is a message' }; }, } </script> <style> .container { padding: 5px 10px; } h1 { color: #345980; } div.counter { padding: 10px; background-color: #efefef; } hr { margin: 10px 0; } </style>
■外部データを読み込み ※axiosを使うと、非同期で外部データを読み込むことができる ※プロジェクト作成時にaxiosをインストールすることもできる ※requireでaxiosを読み込むと、async function() で定義した関数内で await axios.get() を使ってデータを読み込める >cd C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project >npm install --save axios >npm run dev C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\index.vue
<router-link to="/axios">Go to Axios</router-link>
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\test_project\pages\axios.vue
<template> <section class="container"> <h1>{{ title }}</h1> <p>{{ message }}</p> <pre>{{ result_data }}</pre> <router-link to="/">Go to Top</router-link> </section> </template> <script> const axios = require('axios'); let url = '/README.md'; //let url = 'http://refirio.org/page/about'; export default { data: function() { return { title: 'Hello', message: 'これはデータ取得のテストです。' }; }, asyncData: async function() { let result = await axios.get(url); return { result_data: result.data }; }, } </script> <style> .container { padding: 5px 10px; } h1 { color: #345980; } pre { padding: 10px; background-color: #efefef; } hr { margin: 10px 0; } </style>
■Express
Nuxt.js でバックもフロントもこれ一本 - Qiita https://qiita.com/kawaMk4/items/298f95f751540b96d39b ※Expressを使えば、サーバサイドプログラムもJavaScriptで作成できる ※Ajaxでのデータ取得は必須と言ってもいい機能なので、axiosははじめからインストールしておくと良いかも >cd C:\localhost\home\refirio_org\public_html\memos\nuxtjs >npx create-nuxt-app express create-nuxt-app v2.15.0 Generating Nuxt.js project in express Project name express Project description My astonishing Nuxt.js project Author name refirio Choose programming language JavaScript Choose the package manager Npm … yarn から Npm に変更した Choose UI framework None Choose custom server framework Express … None から Express に変更した Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose test framework None Choose rendering mode Universal (SSR) Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection) >cd express >npm run dev [nodemon] 1.19.4 [nodemon] to restart at any time, enter `rs` [nodemon] watching dir(s): server\**\* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node server/index.js` i Preparing project for development 00:11:05 i Initial build may take a while 00:11:05 √ Builder initialized 00:11:05 √ Nuxt files generated 00:11:05 √ Client Compiled successfully in 7.50s √ Server Compiled successfully in 8.05s i Waiting for file changes 00:11:15 READY Server listening on http://localhost:3000 00:11:15 以下にアクセスすると「express My spectacular Nuxt.js project」というデフォルトページが表示される http://localhost:3000/ ■APIを作成 C:\localhost\home\refirio_org\public_html\memos\nuxtjs\express\server\api.js
const express = require('express') const router = express.Router() router.get('/test', (req, res, next) => { const param = { test: 'success' } res.header('Content-Type', 'application/json; charset=utf-8') res.send(param) }) module.exports = router
C:\localhost\home\refirio_org\public_html\memos\nuxtjs\express\server\index.js
const express = require('express') const consola = require('consola') const { Nuxt, Builder } = require('nuxt') const app = express() const apiRouter = require('./api') … 追加 // Import and Set Nuxt.js options const config = require('../nuxt.config.js') config.dev = process.env.NODE_ENV !== 'production' async function start () { // Set api route app.use('/api', apiRouter) … 追加 // Init Nuxt.js const nuxt = new Nuxt(config)
以下にアクセスすると「{"test":"success"}」というデフォルトページが表示される http://localhost:3000/api/test ■Vue.js(フロント)から上記サーバサイドのAPI(Express)を呼び出し Nuxt.jsとaxiosでエラーTypeError: Cannot read property '$get' of undefined - Qiita https://qiita.com/HorikawaTokiya/items/e24c6aaf173d0237525e axios をインストール >npm install --save @nuxtjs/axios nuxt.config.js の最後に modules と axios のブロックを追加 C:\localhost\home\refirio_org\public_html\memos\nuxtjs\express\nuxt.config.js
}, modules: [ '@nuxtjs/axios', ], axios: { } }
index.vue の template に response の表示場所を追加し、 script に data と mounted のブロックを追加する C:\localhost\home\refirio_org\public_html\memos\nuxtjs\express\pages\index.vue
<h2 class="subtitle"> My astonishing Nuxt.js project </h2> <p>API response: {{ response }}</p> }, data: function() { return { response: null } }, mounted: function() { this.$axios .$get('/api/test') .then(response => { this.response = response.test }) .catch(error => { console.log(error) }) } }
以下で起動すると、APIのレスポンス内容が画面に表示される >npm run dev
■サーバサイドレンダリング
未検証だが、どのような動きになるか確認したい Nuxt.jsを使うときに、SPA・SSR・静的化のどれがいいか迷ったら - Qiita https://qiita.com/nishinoshake/items/f42e2f03663b00b5886d
■Vagrant上で実行する
※VagrantでもDockerでも、Windowsとの共有ディレクトリでnpxコマンドが正しく動作しない symlink が使えないことが原因となっているみたい 共有ディレクトリの外に移動させれば動作するようだが、それはそれで管理の手間が増える ローカルでは素直に、Windowsにインストールしたnode.jsで作業するほうが無難かも ■基本的な環境の構築 ※SELinuxを無効にしておく(nginxから参照できなくなる) ※nginx_mariadbのPlaybookで構築 $ sudo su - # python --version Python 2.7.5 # yum -y install epel-release # yum -y install ansible # ansible --version ansible 2.9.7 # vi /etc/ansible/hosts
[localhost] 127.0.0.1
# exit $ cd /var/www/ansible $ ansible-playbook site.yml --connection=local http://192.168.33.10/ ■Nuxt.jsを実行 ※Windowsとの共有ディレクトリでnpxコマンドが正しく動作しない 今回は、共有ディレクトリ外に移動してプロジェクトを作成している AmazonLinux2へNuxt.js導入手順 - Qiita https://qiita.com/deehii/items/58e6da680f322fce10ff $ curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash - $ sudo yum install -y nodejs $ node --version v12.16.3 $ npm --version 6.14.4 $ sudo npm install -g @vue/cli $ vue --version @vue/cli 4.3.1 $ cd $ npx create-nuxt-app my-project create-nuxt-app v2.15.0 Generating Nuxt.js project in my-project Project name my-project Project description My splendiferous Nuxt.js project Author name Choose programming language JavaScript Choose the package manager Npm Choose UI framework None Choose custom server framework Express Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose test framework None Choose rendering mode Universal (SSR) Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection) $ cd my-project $ npm run dev ■エラー プロジェクト作成時、以下のエラーになることがある npm ERR! code EPROTO npm ERR! syscall symlink npm ERR! path ../@babel/parser/bin/babel-parser.js npm ERR! dest /var/www/my-project/node_modules/.bin/parser npm ERR! errno -71 npm ERR! EPROTO: protocol error, symlink '../@babel/parser/bin/babel-parser.js' -> '/var/www/my-project/node_modules/.bin/parser' Windowsとの同期ディレクトリでは symlink を使用できないため 以下のように、同期ディレクトリの外に移動してプロジェクトを作成する (その後同期ディレクトリに移動させても正しく実行できなかった。要調査) $ cd $ npx create-nuxt-app my-project $ cd my-project $ npm run dev WindowsのDocker環境でnpm install実行時にエラーが出た場合の対処法メモ - Qiita https://qiita.com/Y-Kanoh/items/58815aafb7346930f370 [メモ]vagrantでnpm install中に出たエラーまとめ - Qiita https://qiita.com/yosida001/items/3c21acc79adf977e87c0 また、502エラーになる場合、SELinuxが原因となっている可能性がある nginxで同一ホスト内にリバースプロキシしようとするとエラーが出る - Qiita https://qiita.com/rikudai/items/884b203f4a72cfb62c02
■AWSのEC2上で実行する
※Nuxt.jsのみでも実行できるが、Nginxを併用するのが定番みたい AmazonLinux2へNuxt.js導入手順 - Qiita https://qiita.com/deehii/items/58e6da680f322fce10ff ■EC2の基本設定 # localectl set-locale LANG=ja_JP.UTF-8 # timedatectl set-timezone Asia/Tokyo ■Node.jsやVue.jsをインストール $ curl --silent --location https://rpm.nodesource.com/setup_12.x | sudo bash - $ sudo yum install -y nodejs $ node --version v12.16.3 $ npm --version 6.14.4 $ sudo npm install -g @vue/cli $ vue --version @vue/cli 4.3.1 ■プロジェクトを作成 $ cd $ npx create-nuxt-app my-project create-nuxt-app v2.15.0 Generating Nuxt.js project in my-project Project name my-project Project description My splendiferous Nuxt.js project Author name Choose programming language JavaScript Choose the package manager Npm Choose UI framework None Choose custom server framework Express Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection) Choose test framework None Choose rendering mode Universal (SSR) Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection) プロジェクトの作成が完了すると以下が表示される successfully created project my-project To get started: cd my-project npm run dev To build & start for production: cd my-project npm run build npm run start ■起動 プロジェクト作成時に表示された案内に従って起動できる $ cd my-project $ npm run build $ nohup npm run start & [1] 2900 $ curl http://localhost:3000 案内にあるように「npm run start」だけでも起動できるが、コンソールを終了させても停止しないようにバックグラウンドで起動するといい ログはプロジェクト内の nohup.out に出力される killで終了できる $ kill 2900 プロセス番号が不明な場合、以下で調べる $ ps aux | grep npm Nuxt.jsアプリをSSRモードでさくらVPS(CentOS7)にデプロイする手順メモ|ss_ishii|note https://note.com/ss_ishii/n/ncf6418e1bb68 SSH 接続先でサーバを立ち上げっぱなしにしてログアウトするための Bash の書き方 - Corredor https://neos21.hatenablog.com/entry/2018/09/26/080000 ■標準ログとエラーログ 以下のように起動すると、logs/access.log にアクセスログが、logs/error.log にエラーログが表示される …ようだが、詳細な挙動は要検証 ログ用ディレクトリは、あらかじめ作成しておかないと起動できない $ mkdir logs $ nohup npm run start > logs/access.log 2> logs/error.log & ディレクトリ名は何でもいいと思われるが、.gitignore に「/logs」という記述があるので logs という名前にしておくのが一般的かも ログローテートもしくは日付ごとのファイルに保存できるかなどは検証したい command.txtにある「$ touch `date +%Y%m%d_%H-%M-%S`.txt」の応用で何とかなるか、もしくは他に専用の仕組みがあるか nohup コマンドで任意の場所にログを出力する方法 - 約束の地 https://obel.hatenablog.jp/entry/20180208/1518054980 SSH 接続先でサーバを立ち上げっぱなしにしてログアウトするための Bash の書き方 - Corredor https://neos21.hatenablog.com/entry/2018/09/26/080000 nohupで実行したコマンドの出力をnohup.out以外のファイルに保存する https://kazmax.zpp.jp/linux/nohup_stdout.html ■外部からアクセス プロジェクト作成時点では localhost からのみアクセスできる 外部から3000番ポートを指定してアクセスできるようにするためには、起動時の設定が必要(nginxを使うなら不要かも) $ vi package.json
"config": { "nuxt": { "host": "0.0.0.0", "port": "3000" } }
$ nohup npm run start & 以下のようにアクセスできる。コンソールを終了させてもアクセスできることを確認する http://203.0.113.1:3000/ Nuxt.js yarn start時に外部IPから接続できるように設定する | mebee https://mebee.info/2019/12/02/post-4240/ ■Nginxの導入 AmazonLinux2へNuxt.js導入手順 - Qiita https://qiita.com/deehii/items/58e6da680f322fce10ff nginx をリバースプロキシとして使う - NuxtJS https://ja.nuxtjs.org/faq/nginx-proxy/ Nginxが挟まっていれば、package.json でのhost&port設定が無くてもアクセスできる Webサーバとして高性能なNginxを挟んでおく方が、後々運用しやすいと思われる # amazon-linux-extras install nginx1.12 -y # vi /etc/nginx/nginx.conf
server { listen 80 default_server; listen [::]:80 default_server; server_name _; #root /usr/share/nginx/html; … 公開ディレクトリをコメントアウト # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://localhost:3000; … ブロックに内容を追加 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
# systemctl start nginx # systemctl enable nginx 以下のようにアクセスできる http://203.0.113.1/