2020年3月30日 更新
【備忘録】Nuxt.jsでJAMstackサイトを作るときのハマりポイント
Nuxt.jsでJAMstackを開発するにあたって筆者自身が躓いたポイントとその解決方法について、備忘録として残しておきます。同じような場面に遭遇した際に解決の糸口になれば幸いです。
nuxt generateしても生成されたHTMLの中身が空なんだけど・・?
nuxt generate(npmの場合はnpm run generate、yarnの場合はyarn generate)のコマンドを実行すると静的化されたindex.htmlが生成されると公式サイトに書いてあります。じゃあ実際にやってみよう!としてコマンドを叩いてみます。
sh-3.2# yarn generate
yarn run v1.22.0
$ nuxt generate
ℹ Production build 14:26:14
✔ Builder initialized 14:26:14
✔ Nuxt files generated 14:26:14
✔ Client
Compiled successfully in 4.14s
Hash: f7ece106df30a97b78db
Version: webpack 4.41.6
Time: 4140ms
Built at: 2020-03-16 14:26:19
Asset Size Chunks Chunk Names
../server/client.manifest.json 8.13 KiB [emitted]
0db2bf4bc93cff6e695c.js 5.77 KiB 3 [emitted] [immutable] pages/index
476bfcc8be385302226d.js 3.15 KiB 2 [emitted] [immutable] pages/contact
98672295aeb35cfbf08f.js 164 KiB 1 [emitted] [immutable] commons.app
LICENSES 389 bytes [emitted]
e1d2b016a29d974242c5.js 4.3 KiB 5 [emitted] [immutable]
e46e6e01d4aa6b3718b6.js 47.9 KiB 0 [emitted] [immutable] app
f2f8341d29ed552b90fe.js 2.35 KiB 4 [emitted] [immutable] runtime
icons/icon_120.5f6a36.png 4.68 KiB [emitted]
icons/icon_144.5f6a36.png 5.8 KiB [emitted]
icons/icon_152.5f6a36.png 6.1 KiB [emitted]
icons/icon_192.5f6a36.png 7.83 KiB [emitted]
icons/icon_384.5f6a36.png 18.1 KiB [emitted]
icons/icon_512.5f6a36.png 20 KiB [emitted]
icons/icon_64.5f6a36.png 2.35 KiB [emitted]
manifest.cb11056c.json 780 bytes [emitted]
+ 1 hidden asset
Entrypoint app = f2f8341d29ed552b90fe.js 98672295aeb35cfbf08f.js e46e6e01d4aa6b3718b6.js
ℹ Generating pages 14:26:19
✔ Generated /contact 14:26:19
✔ Generated / 14:26:19
✨ Done in 5.90s.
できたっぽい!
それでdistディレクトリを見にいくと、
sh-3.2# ls -l
total 80
-rw-r--r-- 1 root admin 0 3 16 14:26 .nojekyll
-rw-r--r-- 1 root admin 3520 3 16 14:26 200.html
-rw-r--r-- 1 root admin 435 3 16 14:26 README.md
drwxr-xr-x 11 root admin 352 3 16 14:26 _nuxt
drwxr-xr-x 4 root admin 128 3 16 14:26 admin
drwxr-xr-x 3 root admin 96 3 16 14:26 contact
-rw-r--r-- 1 root admin 1393 3 16 14:26 favicon.ico
-rw-r--r-- 1 root admin 242 3 16 14:26 form.html
-rw-r--r-- 1 root admin 12699 3 16 14:26 icon.png
drwxr-xr-x 3 root admin 96 3 16 14:26 img
-rw-r--r-- 1 root admin 3520 3 16 14:26 index.html
-rw-r--r-- 1 root admin 995 3 16 14:26 sw.js
いい感じ!index.htmlとかcontact.htmlが出来てますね。
で、中身を確認してみます。
sh-3.2# cat index.html
<!doctype html>
<html lang="en" data-n-head="%7B%22lang%22:%7B%221%22:%22en%22%7D%7D">
<head>
<title>netlify-nuxt</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content="My fantastic Nuxt.js project"><meta data-n-head="1" data-hid="mobile-web-app-capable" name="mobile-web-app-capable" content="yes"><meta data-n-head="1" data-hid="apple-mobile-web-app-title" name="apple-mobile-web-app-title" content="netlify-nuxt"><meta data-n-head="1" data-hid="author" name="author" content="sho-zy"><meta data-n-head="1" data-hid="theme-color" name="theme-color" content="#fff"><meta data-n-head="1" data-hid="og:type" name="og:type" property="og:type" content="website"><meta data-n-head="1" data-hid="og:title" name="og:title" property="og:title" content="netlify-nuxt"><meta data-n-head="1" data-hid="og:site_name" name="og:site_name" property="og:site_name" content="netlify-nuxt"><meta data-n-head="1" data-hid="og:description" name="og:description" property="og:description" content="My fantastic Nuxt.js project"><link data-n-head="1" rel="icon" type="image/x-icon" href="/favicon.ico"><link data-n-head="1" rel="manifest" href="/_nuxt/manifest.cb11056c.json"><link data-n-head="1" rel="shortcut icon" href="/_nuxt/icons/icon_64.5f6a36.png"><link data-n-head="1" rel="apple-touch-icon" href="/_nuxt/icons/icon_512.5f6a36.png" sizes="512x512"><link rel="preload" href="/_nuxt/f2f8341d29ed552b90fe.js" as="script"><link rel="preload" href="/_nuxt/98672295aeb35cfbf08f.js" as="script"><link rel="preload" href="/_nuxt/e46e6e01d4aa6b3718b6.js" as="script">
</head>
<body>
<div id="__nuxt"><style>#nuxt-loading{visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #fff;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style><script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script><div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div></div>
<script type="text/javascript" src="/_nuxt/f2f8341d29ed552b90fe.js"></script><script type="text/javascript" src="/_nuxt/98672295aeb35cfbf08f.js"></script><script type="text/javascript" src="/_nuxt/e46e6e01d4aa6b3718b6.js"></script></body>
</html>
一見上手くいってそうに見えますが、 bodyタグの中身がありませんねぇ・・・
おかしい・・・これは静的化されていないじゃん・・・
という事象がありました。
こんな時はnuxt.config.jsのmodeを確認してみましょう!
「SPA」モードになっていませんか?
実は「Universal」モードで実行しないと正しく静的化されないのです。
実際に変更して再度nuxt generateしてみます。
sh-3.2# yarn generate
yarn run v1.22.0
$ nuxt generate
ℹ Production build 14:38:40
✔ Builder initialized 14:38:40
✔ Nuxt files generated 14:38:40
✔ Client
Compiled successfully in 4.25s
✔ Server
Compiled successfully in 955.57ms
Hash: 7870e0bb8803edb865c7
Version: webpack 4.41.6
Time: 4254ms
Built at: 2020-03-16 14:38:45
Asset Size Chunks Chunk Names
../server/client.manifest.json 8.16 KiB [emitted]
0db2bf4bc93cff6e695c.js 5.77 KiB 3 [emitted] [immutable] pages/index
476bfcc8be385302226d.js 3.15 KiB 2 [emitted] [immutable] pages/contact
7595360bec8e3948b6bf.js 47.9 KiB 0 [emitted] [immutable] app
98672295aeb35cfbf08f.js 164 KiB 1 [emitted] [immutable] commons.app
LICENSES 389 bytes [emitted]
e1d2b016a29d974242c5.js 4.3 KiB 5 [emitted] [immutable]
f2f8341d29ed552b90fe.js 2.35 KiB 4 [emitted] [immutable] runtime
icons/icon_120.5f6a36.png 4.68 KiB [emitted]
icons/icon_144.5f6a36.png 5.8 KiB [emitted]
icons/icon_152.5f6a36.png 6.1 KiB [emitted]
icons/icon_192.5f6a36.png 7.83 KiB [emitted]
icons/icon_384.5f6a36.png 18.1 KiB [emitted]
icons/icon_512.5f6a36.png 20 KiB [emitted]
icons/icon_64.5f6a36.png 2.35 KiB [emitted]
manifest.cb11056c.json 780 bytes [emitted]
+ 2 hidden assets
Entrypoint app = f2f8341d29ed552b90fe.js 98672295aeb35cfbf08f.js 7595360bec8e3948b6bf.js
Hash: 4fa54700dcd0ba67f76f
Version: webpack 4.41.6
Time: 956ms
Built at: 2020-03-16 14:38:46
Asset Size Chunks Chunk Names
43634cd07bbbcddbd278.js 5.55 KiB 2 [emitted] [immutable] pages/index
b9505899fc2e9573d9c5.js 1.93 KiB 1 [emitted] [immutable] pages/contact
server.js 28.8 KiB 0 [emitted] app
server.manifest.json 203 bytes [emitted]
Entrypoint app = server.js
ℹ Generating pages 14:38:46
✔ Generated /contact 14:38:46
✔ Generated / 14:38:46
✨ Done in 7.27s.
今度はサーバーのビルドも走りました。
出力ファイルを見てみます。
sh-3.2# cat index.html
<!doctype html>
<html data-n-head-ssr lang="en" data-n-head="%7B%22lang%22:%7B%22ssr%22:%22en%22%7D%7D">
<head>
<title>netlify-nuxt</title><meta data-n-head="ssr" charset="utf-8"><meta data-n-head="ssr" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="ssr" data-hid="description" name="description" content="My fantastic Nuxt.js project"><meta data-n-head="ssr" data-hid="mobile-web-app-capable" name="mobile-web-app-capable" content="yes"><meta data-n-head="ssr" data-hid="apple-mobile-web-app-title" name="apple-mobile-web-app-title" content="netlify-nuxt"><meta data-n-head="ssr" data-hid="author" name="author" content="sho-zy"><meta data-n-head="ssr" data-hid="theme-color" name="theme-color" content="#fff"><meta data-n-head="ssr" data-hid="og:type" name="og:type" property="og:type" content="website"><meta data-n-head="ssr" data-hid="og:title" name="og:title" property="og:title" content="netlify-nuxt"><meta data-n-head="ssr" data-hid="og:site_name" name="og:site_name" property="og:site_name" content="netlify-nuxt"><meta data-n-head="ssr" data-hid="og:description" name="og:description" property="og:description" content="My fantastic Nuxt.js project"><link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico"><link data-n-head="ssr" rel="manifest" href="/_nuxt/manifest.cb11056c.json"><link data-n-head="ssr" rel="shortcut icon" href="/_nuxt/icons/icon_64.5f6a36.png"><link data-n-head="ssr" rel="apple-touch-icon" href="/_nuxt/icons/icon_512.5f6a36.png" sizes="512x512"><script data-n-head="ssr" src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script><link rel="preload" href="/_nuxt/f2f8341d29ed552b90fe.js" as="script"><link rel="preload" href="/_nuxt/98672295aeb35cfbf08f.js" as="script"><link rel="preload" href="/_nuxt/7595360bec8e3948b6bf.js" as="script"><link rel="preload" href="/_nuxt/0db2bf4bc93cff6e695c.js" as="script"><style data-vue-ssr-id="3191d5ad:0 932a8f60:0 6759f5ab:0 e46b6ba2:0 377d51af:0">.nuxt-progress{position:fixed;top:0;left:0;right:0;height:2px;width:0;opacity:1;transition:width .1s,opacity .4s;background-color:#fff;z-index:999999}.nuxt-progress.nuxt-progress-notransition{transition:none}.nuxt-progress-failed{background-color:red}html{font-family:Source Sans Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;word-spacing:1px;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;box-sizing:border-box}*,:after,:before{box-sizing:border-box;margin:0}.button--green{display:inline-block;border-radius:4px;border:1px solid #3b8070;color:#3b8070;text-decoration:none;padding:10px 30px}.button--green:hover{color:#fff;background-color:#3b8070}.button--grey{display:inline-block;border-radius:4px;border:1px solid #35495e;color:#35495e;text-decoration:none;padding:10px 30px;margin-left:15px}.button--grey:hover{color:#fff;background-color:#35495e}.container{margin:0 auto;min-height:100vh;display:flex;justify-content:center;align-items:center;text-align:center}.title{font-family:Quicksand,Source Sans Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;display:block;font-weight:300;font-size:55px;color:#35495e;letter-spacing:1px;text-transform:capitalize;margin:25px 0}.subtitle{font-weight:300;font-size:1.1rem;color:#526488;word-spacing:2px;padding-bottom:15px;max-width:600px}.subtitle a{font-weight:500;color:inherit}.links{padding-top:15px;margin-bottom:20px}.content-logos{display:flex;align-items:center;justify-content:center;min-width:500px}.plus{font-size:2.5rem;margin:15px;color:#35495e}.h3{font-family:Quicksand,Source Sans Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-weight:400;margin:10px}.NuxtLogo{-webkit-animation:appear 1s;animation:appear 1s;margin:auto}@-webkit-keyframes appear{0%{opacity:0}to{opacity:1}}@keyframes appear{0%{opacity:0}to{opacity:1}}.vuesax-logo{width:100%;max-width:170px}.vuesax-logo svg{width:100%;fill:#35495e}</style>
</head>
<body>
<div data-server-rendered="true" id="__nuxt"><!----><div id="__layout"><div><div class="container"><div><header class="content-logos"><svg width="245" height="180" viewBox="0 0 452 342" xmlns="http://www.w3.org/2000/svg" class="NuxtLogo"><g fill="none" fill-rule="evenodd"><path d="M139 330l-1-2c-2-4-2-8-1-13H29L189 31l67 121 22-16-67-121c-1-2-9-14-22-14-6 0-15 2-22 15L5 303c-1 3-8 16-2 27 4 6 10 12 24 12h136c-14 0-21-6-24-12z" fill="#00C58E"></path> <path d="M447 304L317 70c-2-2-9-15-22-15-6 0-15 3-22 15l-17 28v54l39-67 129 230h-49a23 23 0 0 1-2 14l-1 1c-6 11-21 12-23 12h76c3 0 17-1 24-12 3-5 5-14-2-26z" fill="#108775"></path> <path d="M376 330v-1l1-2c1-4 2-8 1-12l-4-12-102-178-15-27h-1l-15 27-102 178-4 12a24 24 0 0 0 2 15c4 6 10 12 24 12h190c3 0 18-1 25-12zM256 152l93 163H163l93-163z" fill="#2F495E" fill-rule="nonzero"></path></g></svg> <span class="plus">+</span> <div class="vuesax-logo"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 680.69 725.78"><title>Recurso 47</title> <g id="Capa_2" data-name="Capa 2"><g id="Capa_1-2" data-name="Capa 1"><polygon points="680.42 59.35 555.03 59.35 340.34 391.82 125.67 59.35 0.27 59.35 340.35 586 680.42 59.35"></polygon> <polygon points="340.34 644.59 52.42 198.71 0 198.71 340.33 725.78 680.69 198.71 628.26 198.71 340.34 644.59"></polygon> <polygon points="518.83 10.13 340.33 281.52 161.87 10.13 293.21 43.27 293.21 0 387.48 0 387.48 43.27 518.83 10.13"></polygon></g></g></svg></div></header> <h1 class="title">
Nuxt.js + Vuesax
</h1> <h2 class="subtitle"><a href="https://vuesax.com/">Vuesax</a> is a framework of ui components
for <a href="https://vuejs.org/">Vuejs</a>, It was created to make new
interfaces that have a new trend and are visually beautiful
</h2> <div class="links"><h3 class="h3">
Vuesax
</h3> <a href="https://vuesax.com/" target="_blank" class="button--green">
Documentation
</a> <a href="https://discordapp.com/invite/9dsKtvB" target="_blank" class="button--grey">
Discord
</a> <a href="https://github.com/lusaxweb/vuesax" target="_blank" class="button--grey">
GitHub
</a></div> <div class="links"><h3 class="h3">
Nuxt.js
</h3> <a href="https://nuxtjs.org/" target="_blank" class="button--green">
Documentation
</a> <a href="https://github.com/nuxt/nuxt.js" target="_blank" class="button--grey">
GitHub
</a></div></div></div></div></div></div><script>window.__NUXT__={layout:"default",data:[{}],error:null,serverRendered:!0}</script><script src="/_nuxt/f2f8341d29ed552b90fe.js" defer></script><script src="/_nuxt/0db2bf4bc93cff6e695c.js" defer></script><script src="/_nuxt/98672295aeb35cfbf08f.js" defer></script><script src="/_nuxt/7595360bec8e3948b6bf.js" defer></script>
</body>
</html>
bodyタグの中身がしっかり出てる!
これで無事、静的化されました👏
動的ルーティングページが生成されない・・・?
ブログやECサイトなど、必ず実装するであろう動的ページについてです。
例えば下記の構成でページを用意したとします。
page/
┗index.vue
┗_slug.vue
また、_slug.vueには「page1」「page2」のページが存在するとします。
この時nuxt generateを実行すると、
sh-3.2# yarn generate
yarn run v1.22.0
$ nuxt generate
OgpGenerater:start 15:06:08
OgpGenerater:finish 15:06:08
ℹ Production build 15:06:08
✔ Builder initialized 15:06:08
✔ Nuxt files generated 15:06:08
✔ Client
Compiled successfully in 4.02s
✔ Server
Compiled successfully in 893.25ms
Hash: da668f3b0a1e64e360ba
Version: webpack 4.42.0
Time: 4027ms
Built at: 2020-03-16 15:06:12
Asset Size Chunks Chunk Names
../server/client.manifest.json 7 KiB [emitted]
0ea42793f04152981ea9.js 2.88 KiB 2 [emitted] [immutable] pages/_slug
30e904c4e756d0fe8c49.js 2.33 KiB 4 [emitted] [immutable] runtime
84b92d46d7719fcfa224.js 3.04 KiB 3 [emitted] [immutable] pages/index
916e57f2f628f5a93b60.js 151 KiB 1 [emitted] [immutable] commons.app
LICENSES 389 bytes [emitted]
aa64ef1b2a4c254bf743.js 43 KiB 0 [emitted] [immutable] app
+ 2 hidden assets
Entrypoint app = 30e904c4e756d0fe8c49.js 916e57f2f628f5a93b60.js aa64ef1b2a4c254bf743.js
Hash: cabdd36e6f8d1b9ad16b
Version: webpack 4.42.0
Time: 894ms
Built at: 2020-03-16 15:06:13
Asset Size Chunks Chunk Names
0547ecc69c21437607a2.js 2.64 KiB 1 [emitted] [immutable] pages/_slug
6230783e481d889cea72.js 3.13 KiB 2 [emitted] [immutable] pages/index
server.js 26 KiB 0 [emitted] app
server.manifest.json 203 bytes [emitted]
Entrypoint app = server.js
ℹ Generating pages 15:06:13
✔ Generated / 15:06:13
✨ Done in 7.39s.
あれ・・・出来てなさそう?
一縷の望みをかけてdistディレクトリを見てみます。
sh-3.2# ls -l dist
total 72
-rw-r--r-- 1 root admin 0 3 16 15:06 .nojekyll
-rw-r--r-- 1 root admin 2448 3 16 15:06 200.html
-rw-r--r-- 1 root admin 435 3 16 15:06 README.md
drwxr-xr-x 8 root admin 256 3 16 15:06 _nuxt
-rw-r--r-- 1 root admin 1393 3 16 15:06 favicon.ico
drwxr-xr-x 3 root admin 96 3 16 15:06 font
-rw-r--r-- 1 root admin 12699 3 16 15:06 icon.png
drwxr-xr-x 4 root admin 128 3 16 15:06 img
-rw-r--r-- 1 root admin 4371 3 16 15:06 index.html
drwxr-xr-x 5 root admin 160 3 16 15:06 ogp
index.htmlしかありませんね。page1.htmlとかpage2.htmlは案の定ありませんでした・・・
実は、動的ルーティングの場合は自動で出力してくれないのです。「こんなルーティングがあるよ」とnuxt.config.jsに定義して教えてあげないといけません。
設定する場所は、nuxt.config.jsのgenerateの中です。下記のように定義します。
generate: {
routes() {
const routes = []
const fs = require('fs')
const fileNames = fs.readdirSync('./data')
for (const key in fileNames) {
const page = JSON.parse(
fs.readFileSync('./data/' + fileNames[key], 'utf8')
)
routes.push({
route: '/' + page.slug,
payload: page
})
}
return routes
}
}
解説すると、dataディレクトリの中にあるJsonファイルを取得して、「route」にURL、「payload」にJsonデータを渡しています。
そしてnuxt generateしてみます。
sh-3.2# yarn generate
yarn run v1.22.0
$ nuxt generate
OgpGenerater:start 15:18:40
OgpGenerater:finish 15:18:41
ℹ Production build 15:18:41
✔ Builder initialized 15:18:41
✔ Nuxt files generated 15:18:41
✔ Client
Compiled successfully in 4.01s
✔ Server
Compiled successfully in 891.94ms
Hash: da668f3b0a1e64e360ba
Version: webpack 4.42.0
Time: 4007ms
Built at: 2020-03-16 15:18:45
Asset Size Chunks Chunk Names
../server/client.manifest.json 7 KiB [emitted]
0ea42793f04152981ea9.js 2.88 KiB 2 [emitted] [immutable] pages/_slug
30e904c4e756d0fe8c49.js 2.33 KiB 4 [emitted] [immutable] runtime
84b92d46d7719fcfa224.js 3.04 KiB 3 [emitted] [immutable] pages/index
916e57f2f628f5a93b60.js 151 KiB 1 [emitted] [immutable] commons.app
LICENSES 389 bytes [emitted]
aa64ef1b2a4c254bf743.js 43 KiB 0 [emitted] [immutable] app
+ 2 hidden assets
Entrypoint app = 30e904c4e756d0fe8c49.js 916e57f2f628f5a93b60.js aa64ef1b2a4c254bf743.js
Hash: cabdd36e6f8d1b9ad16b
Version: webpack 4.42.0
Time: 893ms
Built at: 2020-03-16 15:18:46
Asset Size Chunks Chunk Names
0547ecc69c21437607a2.js 2.64 KiB 1 [emitted] [immutable] pages/_slug
6230783e481d889cea72.js 3.13 KiB 2 [emitted] [immutable] pages/index
server.js 26 KiB 0 [emitted] app
server.manifest.json 203 bytes [emitted]
Entrypoint app = server.js
ℹ Generating pages 15:18:46
✔ Generated / 15:18:46
✔ Generated /page1 15:18:46
✔ Generated /page2 15:18:46
✨ Done in 7.56s.
お、今度は上手くいってそうです。
distディレクトリを見てみます。
sh-3.2# ls -l dist
total 72
-rw-r--r-- 1 root admin 0 3 16 15:18 .nojekyll
-rw-r--r-- 1 root admin 2448 3 16 15:18 200.html
-rw-r--r-- 1 root admin 435 3 16 15:18 README.md
drwxr-xr-x 8 root admin 256 3 16 15:18 _nuxt
-rw-r--r-- 1 root admin 1393 3 16 15:18 favicon.ico
drwxr-xr-x 3 root admin 96 3 16 15:18 font
-rw-r--r-- 1 root admin 12699 3 16 15:18 icon.png
drwxr-xr-x 4 root admin 128 3 16 15:18 img
-rw-r--r-- 1 root admin 4371 3 16 15:18 index.html
drwxr-xr-x 5 root admin 160 3 16 15:18 ogp
drwxr-xr-x 3 root admin 96 3 16 15:18 page1
drwxr-xr-x 3 root admin 96 3 16 15:18 page2
「page1」「page2」というディレクトリが出来ていますね。
中を見てみます。
sh-3.2# ls -l dist/page1
total 8
-rw-r--r-- 1 root admin 3858 3 16 15:18 index.html
ありました!これで動的ページの生成も完了です!
ちなみに「payload」ですが設定は任意です。
動的ページの中で、
<script>
export default {
async asyncData({ params, error, payload }) {
if (payload) {
return { page: payload }
} else {
return { page: await require(`~/data/${params.slug}.json`) }
}
},
このように設定しておくとclientとserverのビルドでそれぞれファイル読み込みせず、2度目はpayloadからデータを取得するように出来ます。
例えばAPIのコール制限などあった場合にコール回数を抑える事が出来るので有効です。
サーバーサイドとクライアントサイドのDOM構造が一致しない・・・?
JAMstackな開発をしていて下記のようなコンソールエラーが出る場合があります。
Mismatching childNodes vs. VNodes
vue.runtime.esm.js?2b0e:619 [Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.
これは、createされた後にDOM構造に変更があった場合に起こるようです。
例えば、レスポンシブ対応するために画面幅で表示を出しわけしたり、子コンポーネントから親コンポーネントにemitして親コンポーネントの表示が変わったりなど。
この場合は構造不一致の対象となる部分を<client-only>タグで下記のように囲ってあげましょう。
<client-only>
[対象部分]
<client-only>
するとエラーが回避できます。
但し、該当部分は静的サイトとして出力されないのでご注意ください。
躓きポイントは以上です!
また何かあった場合は追記していこうと思います。
記事についての質問や、ここも躓いた!などありましたらお問い合わせより連絡ください。
出来るだけお答えしたいなと思っています。
それでは失礼します!
オススメの記事
記事の内容はいかがでしたか?