Nuxt.jsã§ããã¸ã§ã¯ããã¯ãããã¨ãã«ãã¤ããããã¨ãæ´çãã¦ã¿ãã
ã¢ã¸ã¥ã¼ã«ãå¤ãã®ã§ãããããè¨å®ãå¿
è¦ã ãã©ããã±ã¢ã¬ãã£ããããã®ã§ãã
Nuxt.jsã®ãã¼ã¸ã§ã³ã¯ã2.5.1ã§ãã
ãã¤ããããã¨ã®æ¦è¦
ä½æãããããã¸ã§ã¯ãã¯ä»¥ä¸ãªæã
- TypeScript/Sassã使ããUIã¯Buefy/Bulma
- Firebase Hosting / Cloud Functionsã使ã£ã¦SSR
- è±èªç/æ¥æ¬èªçã¨å½éåãããã®ã§ãnuxt-i18nãå ¥ãã
- SEOãæ°ã«ããã®ã§ãå種è¨å®&åãã¼ã¸ã§åå¥ã«ã¿ã¤ãã«ã¨ããè¨å®
- Google Analyticsãsitemapãªã©ããã¡ãã
- Firebaseã¸ã®ãããã¤ã¯ãCircleCIã§èªååããã
æçµçãªä¾ã¯ãGitHubã«ããã¦ãã¾ãã
ãåæ¸ã
ãããã¨ã¯ä»¥ä¸ã®14åããªããããããããã
- ããã¸ã§ã¯ãä½æ
- ãã£ã¬ã¯ããªæ§æã®å¤æ´
- TypeScriptã®å°å ¥
- Sassã®å°å ¥
- envç¨ã®è¨å®ãã¡ã¤ã«ã追å
- ãµã¤ããããçæã®è¨å®ã追å
- å½éåã®ããã«nuxt-i18nã追å
- SEOé¢é£ã®è¨å®
- Google Analyticsã®è¨å®ã追å ãã
- Buefyã«ã¹ã¿ãã¤ãºç¨ã®SCSSã追å
- Page Transitionç¨ã®SCSSã追å
- UglifyJsPluginã追å ãã¦ãconsole.logãèªååé¤
- Firebase Functionsã®è¨å®ãã¦SSRã§ããããã«ãã
- CircleCIã®è¨å®
1. ããã¸ã§ã¯ãä½æ(ã³ããã: e5bf50b)
ã¾ãã¯ãããã¸ã§ã¯ãä½æãnpx create-nuxt-app
ã使ãã¾ã
$ npx create-nuxt-app <ããã¸ã§ã¯ãå> npx: 379åã®ããã±ã¼ã¸ã12.001ç§ã§ã¤ã³ã¹ãã¼ã«ãã¾ããã > Generating Nuxt.js project in ... ? Project name <ããã¸ã§ã¯ãå> ? Project description Nuxt.js Template using TypeScript, Sass and SSR on Firebase Cloud Functions ? Use a custom server framework none ? Choose features to install Axios ? Use a custom UI framework buefy ? Use a custom test framework none ? Choose rendering mode Universal ? Author name Memory Lovers ? Choose a package manager npm To get started: cd <ããã¸ã§ã¯ãå> npm run dev To build & start for production: cd <ããã¸ã§ã¯ãå> npm run build npm start
ä½ãçµããã¨ããã®ã³ããã(e5bf50b)ãªæãã«
2. ãã£ã¬ã¯ããªæ§æã®å¤æ´(ã³ããã: 4fbab23)
ãã¨ã§functionsã®ãã£ã¬ã¯ããªã追å ããã®ã§ã
appç¨ã®ãã£ã¬ã¯ããªä½æãã¦ã移åãã
#!/bin/bash mkdir app mv assets/ app/ mv components/ app/ mv layouts/ app/ mv middleware/ app/ mv pages/ app/ mv plugins/ app/ mv static/ app/ mv store/ app/
ãã£ã¬ã¯ããªãå¤ããã®ã§ãnuxt.config.jsãå¤æ´
const config: NuxtConfiguration = {
mode: 'universal',
+ srcDir: "app",
3. TypeScriptã®å°å ¥(ã³ããã: c1106e0)
Nuxt.jsv2.5ã§TypeScriptãµãã¼ããå¼·åãããã®ã§ãã ãã¶æ¥½ã«ãã
@nuxt/typescript
ãå
¥ããã ãã§OKãããã(TypeScript Support - Nuxt.js)
$ npm install --save -D @nuxt/typescript # ãã³ã¬ã¼ã¿ãvuexã使ãããã®ã§è¿½å $ npm install --save nuxt-property-decorator vuex-class # tsconifig.jsonãç¨æããã¨ãNuxtãè¨å®ãèªåçæãã¦ããã # ãªã®ã§ãã¨ããããã空ãã¡ã¤ã«ãä½æ $ echo "{}" > tsconfig.json # ä¸åããã«ããã¦ãtsconifig.jsonãçæ $ npm run build
3.1. tsconfig.jsonããã£ã¬ã¯ããªæ§æã«åããã(ã³ããã: 8473099)
appãã£ã¬ã¯ããªé ä¸ã«å¤æ´ãã¦ããã®ã§ãèªåçæããtsconfig.jsonãåããã
"paths": { "~/*": [ - "./*" + "./app/*" ], "@/*": [ - "./*" + "./app/*" ] },
3.2. nuxt.config.jsãnuxt.config.tsã«å¤æ(ã³ããã: 8473099)
ã¾ãã¯ãnuxt.config.jsãTypeScriptå
é·ãã®ã§ãå·®åã¯ã³ããããåç
§
3.3. åå®ç¾©ã®é ç½®ãã£ã¬ã¯ããªã追å (ã³ããã: 90f3a1e)
mkdir app/types touch app/types/index.d.ts # Stateã®åå®ç¾© touch app/types/state.d.ts # Vueã®åå®ç¾©ã®æ¡å¼µ touch app/types/vue.d.ts
3.4. ä»ãã.vueãã¡ã¤ã«ãTypeScriptã«å¤æ(ã³ããã: 8dcffc3)
æã®è¨äºãå
¬å¼ã®è¨äºãåèã«ãæ¸ãæããã
nuxt-community/nuxt-property-decoratorãåèã«ãªã
4. Sassã®å°å ¥(ã³ããã: 9cde2e1)
Sassã®å°å ¥ã¯ãnpm installããã ã
$ npm install --save-dev node-sass sass-loader
5. envç¨ã®è¨å®ãã¡ã¤ã«ã追å (ã³ããã: 1cbc14a)
å人çãªè¶£å³ã§ãéçºç¨ã¨æ¬çªç¨ã®envãåããã¨ãã¯ã
nuxt.config.tsã«æ¸ãããå¥ãã¡ã¤ã«ã«ãã¦ããã
# éçºç¨ã®env $ touch env.development.js # æ¬çªç¨ã®env $ touch env.production.js
ä¸èº«ã¯ãããªæããåºæ¬æ å ±ã¨ãã¯envã«å ¥ãã¦ãã
module.exports = { baseUrl: "http://localhost:3000", contactFormUrl: "TODO_YOUR_CONTACT_FORM_URL", policyUrl: "TODO_YOUR_PRIVACY_POLICY_URL", tosUrl: "TODO_YOUR_TERMS_OF_SERVICE_URL", twitterUrl: "TODO_YOUR_TWITTER_URL", firebaseConfig: "TODO_YOUR_FIREBASE_CONFIG", GA_ID: "TODO_YOUR_GOOGLE_ANALYTICS_ID" };
env.jsãèªã¿è¾¼ãããã«nuxt.config.tsãå¤æ´
import NuxtConfiguration from '@nuxt/config' import pkg from './package.json'; + const environment = process.env.NODE_ENV || "development"; + const envSet = require(`./env.${environment}.js`); const config: NuxtConfiguration = { mode: 'universal', srcDir: "app", + /* + ** ENVIRONMENT PROPERTIES + ** See https://ja.nuxtjs.org/api/configuration-env + */ + env: envSet, +
6. ãµã¤ããããçæã®è¨å®ã追å (ã³ããã: 0f3bb98)
Google Search Consoleã«ã¢ãããã¼ãããããã«sitemap.xmlãnuxt build
æã«çæããããã«è¨å®ã
@nuxtjs/sitemapãå©ç¨ããã°OK!
ã¾ãã¯ãã¤ã³ã¹ãã¼ã«
$ npm install --save @nuxtjs/sitemap
nuxt.config.tsã«è¨å®ã追å
const config: NuxtConfiguration = { modules: [ ... + // Doc: https://github.com/nuxt-community/sitemap-module + "@nuxtjs/sitemap", ], + + /* + ** Sitemap + */ + sitemap: { + path: "/sitemap.xml", + hostname: envSet.baseUrl, + generate: true + },
7. å½éåã®ããã«nuxt-i18nã追å
å½éåéè¦ãæ¥æ¬èªã ãã ã¨ç¯å²ãçãã®ã§ãè±èªã«ã¯å¯¾å¿ããããã
ãªã®ã§ãnuxt-i18nã使ã£ã¦i18n対å¿ã§ããããã«ããã
詳ãã使ãæ¹ã¯ãå¥è¨äºã§ãã
7.1. ã¤ã³ã¹ãã¼ã«ãã¦ãè¨å®ã追å (ã³ããã: 43108e2)
ã¾ãã¯ãã¤ã³ã¹ãã¼ã«
$ npm install --save nuxt-i18n # ã¡ãã»ã¼ã¸ã®JSONãé ç½®ãããã£ã¬ã¯ããªã追å $ mkdir app/assets/msg # ã¡ãã»ã¼ã¸ãã¡ã¤ã«ã追å $ echo "{}" > app/assets/msg/common.json
nuxt.config.tsã«è¨å®ã追å
const config: NuxtConfiguration = { modules: [ ... + // Doc: https://nuxt-community.github.io/nuxt-i18n/ + ['nuxt-i18n', { + parsePages: false, + locales: [ + { code: 'en', iso: 'en_US' }, + { code: 'ja', iso: 'ja_JP' }, + ], + defaultLocale: 'en', + vueI18n: { + fallbackLocale: 'en', + messages: require("./app/assets/msg/common") + }, + vueI18nLoader: true // vue-i18n-loaderãæå¹ã«ãã + }], // Doc: https://github.com/nuxt-community/sitemap-module "@nuxtjs/sitemap", ],
ãã¤ã³ã
- nuxt-i18nã®è¨å®ã@nuxtjs/sitemapã«åæ ãããããã«ãå ã«æ¸ãã
- TypeScript+decoratorã使ã£ã¦ããå ´åã¯ã
parsePages: false
ãå¿ è¦ãã
7.2. ã¡ãã»ã¼ã¸ãã¡ã¤ã«ã追å ãã¦ãå.vueãå½éå(ã³ããã: afe0c96)
ç´°ããå¤æ´ã¯ãã³ãããå·®åãåç
§ã
ã¡ãã»ã¼ã¸ãã¡ã¤ã«ã¯ããã©ã³ã¹ãã¼ãã¨ããWebãµã¼ãã¹ã使ã£ã¦çæ
7.3. ã¡ãã¥ã¼ã«è¨èªå¤æ´ã追å (ã³ããã: c40d7bb)
è±èªã¨æ¥æ¬èªãåãæ¿ãããããã«ãè¨èªå¤æã追å ã
詳細ã¯ãã³ãããå·®åãåç
§
8. SEOé¢é£ã®è¨å®
SEOçã«åãã¼ã¸ã®titleãdescriptionãã¡ããã¨ãããï¼i18n使ã£ã¦ãã®ã§Localeã«ãããã¦æ¥è±åãæ¿ãããï¼
ãããããã£ã¦ã¿ããã©ãVue.jsã®mixinã使ãã®ãè¯ããããªã®ã§ã
ãFaviconãªã©ã®å
±éçãªhead()
ãã¨ãtitleãOGPãªã©åãã¼ã¸ã®head()
ãå·®ãè¾¼ãæ çµã¿ãã追å ãã¦ã
åè¦ç´ ãªã©ã¯ãéå»ã®è¨äºãåç § - SEO/OGPé¢é£ã®metaã¿ã°ãã¾ããã«å¯¾å¿ãããã¨ãã¦ã¿ãã - ãããã«ãªãããã
8.1. å
±éçãªhead()
(ã³ããã: 96e82d8)
å
±éçãªheadã¯ãå¥ãã¡ã¤ã«(commonHead.js
)ã«ã¾ã¨ãã¦ãnuxt.config.tsã§ã°ãã¼ãã«ã¨ãã¦è¨å®ããã
詳細ã¯ãã³ãããå·®åãåç §ã
faviconä¸å¼ã¯ãfavicon generatorã§çæãããã®ããapp/static
é
ä¸ã«é
ç½®ããæ³å®ã®è¨å®ã
8.2. mixinã§pageãã¨ã«è¨å®(ã³ããã: 12a80ed)
mixinsã¯ãããªæããmixinsã®head()
ã§åãã¼ã¸ã§è¨å®ããmetaã¿ã°ãçæããã
åãã¼ã¸åå¥ã®æ
å ±ãheadInfo()
ã«æ¸ãã¨ãHeadMixin
ã®head()
ããã£ã¡ãåç
§ããªãããããæãã«ã
import Vue from "vue"; import Component from "vue-class-component"; import { MetaInfo } from "vue-meta"; import { HeadInfo } from "~/types"; @Component export default class HeadMixin extends Vue { public headInfo(): HeadInfo { return {}; } public head(): MetaInfo { const i18nSeo = this.$nuxtI18nSeo(); const t = this.$t.bind(this); const info = this.headInfo(); const siteName: string = t("site_name") as string; const title: string = t(info.title || "site_name") as string; const description: string = t(info.description || "site_description") as string; const baseUrl: string = process.env.baseUrl || ""; const thisUrl: string = `${baseUrl}${this.$route.path}`; const ogImageUrl: string = `${baseUrl}${info.ogImagePath || "/ogp.png"}`; return { title: title, htmlAttrs: { prefix: "og: http://ogp.me/ns# fb: http://ogp.me/ns/ fb#", ...i18nSeo.htmlAttrs }, meta: [ { hid: "description", name: "description", content: description }, { name: "application-name", content: siteName }, // OGP / Social Meta Tag { property: "og:type", name: "og:type", content: "website" }, { property: "og:title", name: "og:title", content: title }, { property: "og:description", name: "og:description", content: description }, { property: "og:url", name: "og:url", content: thisUrl }, { property: "og:image", name: "og:image", content: ogImageUrl }, { property: "og:site_name", name: "og:site_name", content: siteName }, ...i18nSeo.meta ], link: [{ rel: "canonical", href: thisUrl }, ...i18nSeo.link] }; } }
ãã®ã¾ã¾ã ã¨ã$nuxtI18nSeo()
ã$t
ã§åå®ç¾©ã足ãã¦ãªãï¼ã¨ãæãããã®ã§ã
tsconfig.json
ãapp/types/vue.d.ts
ã«nuxt-i18nãªã©ã®å®ç¾©ã追å ããã
HeadInfo
ã¯ãåãã¼ã¸ã§è¨å®ãããã©ã¡ã¿ãè¦å®ããããã«ãç¬èªã«åå®ç¾©ãç¨æã
nuxt-i18nãseoé¢é£ã®metaã¿ã°ãçæãã¦ãããããã»ã«ããã¼ã¸ãå¿
è¦ãã
ãªã®ã§æ«å°¾ã«...i18nSeo.htmlAttrs
ãªã©ã追å
8.3. åãã¼ã¸ã«mixinãå°å ¥(ã³ããã: 12a80ed)
åãã¼ã¸ã¯ãããªæããmixins(HeadMixin)
ã§mixinsãç¶æ¿ãã¦ã
headInfo()
ã§ãã¼ã¸ã®titleãdescriptionã®keyãè¨å®ã
- import { Component, Vue } from "nuxt-property-decorator"; + import { Component, Vue, mixins } from "nuxt-property-decorator"; + import HeadMixin from "~/mixins/HeadMixin"; + import { HeadInfo } from "~/types"; import Card from "~/components/Card.vue" @Component({ components: { Card } }) - export default class IndexPage extends Vue { + export default class IndexPage extends mixins(HeadMixin) { name:string = 'HomePage'; + public headInfo(): HeadInfo { + return { + title: "home_title", + description: "home_details" + }; }
9. Google Analyticsã®è¨å®(ã³ããã: 51cc5db)
PVã¨ããã¡ããã¨è¨æ¸¬ãããã®ã§ãGoogleAnalyticsã使ããããã«ããã
@nuxtjs/google-analyticsãå
¥ããã ãã§OK
$ npm install --save @nuxtjs/google-analytics
è¨å®ã¨ãã¯ã³ãããå·®åãåç §ã éå»ã®è¨äºã§ãã
10. Buefyã«ã¹ã¿ãã¤ãºç¨ã®SCSSã追å (ã³ããã: 5b8372b)
Bulmaã®$primaryã®è²ã¨ãã¯ãã¼ãã¨ãã¦å¤æ´ãããã®ã§ã ã«ã¹ã¿ã ç¨ã®CSSã追å
ãã¼ã¹ã ããªã®ã§ãã»ã¼å
¬å¼ã®ã¾ã¾ã
- Customization | Buefy
11. Page Transitionã追å (ã³ããã: b19e28e)
ãã¼ã¸é·ç§»æã®ã¢ãã¡ã¼ã·ã§ã³ãã¤ãããã®ã§ãã°ãã¼ãã«ã«CSSã追å
è¨å®ã¨ãã¯ã³ãããå·®åãåç §ããã¡ããå ¬å¼ã®ã¬ã¤ããã
12. UglifyJsPluginã§console.logãèªååé¤(ã³ããã: d485999)
å人çã«buildæã«èªåã§console.logãåé¤ãã¦ã»ããã
ãªã®ã§ãUglifyJsPlugin
ã使ã£ã¦è¨å®
13. Firebase Cloud Functionsã®è¨å®ãã¦SSRã§ããããã«ãã
SPAã ã¨ãmetaã¿ã°ãããæããªããªãã®ã§ãSSRããããã
Firebase Hostingã«staticãassetsãããã¦ããã以å¤ã¯Cloud Functionsã§SSRãã
13.1. firebase init
ã§åæè¨å®(ã³ããã: fcbf5f7)
ã¨ãããããåæè¨å®ãHostingã¨Functionãé¸æãã
$ firebase init
13.2. Nuxtãå¼ã³åºãé¢æ°ãç¨æãã¦ãrewriteã追å (ã³ããã: 9f8d986)
ssr
ã¨ããFunctionã追å ã
Hostingã®rewriteã§åºæ¬ãã¹ã¦ã®ãªã¯ã¨ã¹ããssr
ã«æ¸¡ãããã«ããã
"rewrites": [ { "source": "**", "function": "ssr" } ],
headers
ãåããã¦è¨å®ãã¦ãããããã£ãã·ã¥ã³ã³ããã¼ã«ã®ãããä¸è¦ãªããªãã¦ãOK
ssré¢æ°èªä½ã¯éå»è¨äºãåç
§ã
- Nuxt2.5ã§Firebaseã§SSRããCloud Functionsã®æ¸ãæ¹ - ãããã«ãªãããã
13.3. functionsã®package.jsonã¸ä¾åé¢ä¿ã追å (ã³ããã: 31028f5)
ssré¢æ°å
ã§å®è¡ãããNuxtãªãã¸ã§ã¯ããå®è¡ã§ããããã«ã
app/package.json
ã®dependenciesã¨åãããã±ã¼ã¸ããfunctions/package.json
ã«ã追å
13.4. buildã®ä¸é£ã®æµããpackage.jsonã«è¿½å (ã³ããã: 606cda6)
å人çã«Cloud Functionsã§SSRããã¨ãã®èã£ã½ãã¨ããã
ä¸é£ã®æµãã¯ã以ä¸ã®ãããªæãã
nuxt build
ã§app
é ä¸ããã«ããã.nuxt/
ãä½æfunctions/index.js
ããNuxtãå¼ã³åºããããã.nuxt/
ãfunctionsé ä¸ã«é ç½®- Hostingã§deployãããã£ã¬ã¯ããªã¨ãã¦ã
public/
ãã¯ãªã¼ã³ãã¦ãæ°è¦ä½æ public/
ã«ãã«ããããã¡ã®assets/
é¨åãã³ãã¼ãapp/static
ãã³ãã¼- Hostingã®deployã§
public/
ãã£ã¬ã¯ããªãã¢ãããã¼ã - Functionsã®deployã§
functions/
ãã£ã¬ã¯ããªãã¢ãããã¼ã
ããããã£ãã®ã¯ã2./4.ã®ã³ãã¼ããé¨åã
- Functionsã¯å
¨é¨å¿
è¦ãªã®ã§ããã®ã¾ã¾é
ç½®ã
- Hostingã¯js/css/ç»åãªã©ãä¸é¨ã®ã¿ãªã®ã§ãé¸å¥ãã¦é
ç½®
ç¹ã«Hostingã«ã¯åªå
é ä½ããããå®éã®ãã¡ã¤ã«ã®ã»ãããªã©ã¤ããããåªå
度ãé«ãã®ã§ã
/index.htmlãããã¨ãssré¢æ°ã¯å
¨ãå¼ã³åºãããªããªããã
ãã®ç¹ãè¸ã¾ãã¦ãä¸é£ã®æµããpackange.jsonã®scriptã«ç¨æãã¦ããã°ã
npm run build && npm run deploy
ã§ãããã¤ã§ãã
14. CircleCIã®è¨å®(ã³ããã: 4cec55f)
ããã©ãããããªã®ã§ãmasterã«pushããããããã¤ãã¦ã»ãããã
ãªã®ã§ãCircleCIã§èªåãªãªã¼ã¹ã§ããããã«è¨å®
詳細ã¯ã³ãããå·®åãåç
§ãéå»ã®è¨äºãã
- CircleCIã§Firebaseã¸èªåãããã¤(Hosting+Funcsions) - ãããã«ãªãããã
以ä¸ï¼ï¼
ããã§ãã§ãã¯ã¢ã¦ãããã ãã§ãåææ§ç¯ã®ä½æ¥ãã»ã¨ãã©å®äºããã®ã§ã ãã¶æ¥½ã«ãªãï¼ï¼
åèã«ãªãæ¸ç±
- ä½è : è±è°·æ磨
- åºç社/ã¡ã¼ã«ã¼: ã·ã¼ã¢ã³ãã¢ã¼ã«ç 究æ
- çºå£²æ¥: 2018/10/17
- ã¡ãã£ã¢: åè¡æ¬ï¼ã½ããã«ãã¼ï¼
- ãã®ååãå«ãããã°ãè¦ã
Vue.jså ¥é åºç¤ããå®è·µã¢ããªã±ã¼ã·ã§ã³éçºã¾ã§
- ä½è : å·å£åä¹,åå¤åä»,éç°é½å¹³,æ島æä¹,çå±±çä¹
- åºç社/ã¡ã¼ã«ã¼: æè¡è©è«ç¤¾
- çºå£²æ¥: 2018/09/22
- ã¡ãã£ã¢: åè¡æ¬ï¼ã½ããã«ãã¼ï¼
- ãã®ååãå«ãããã°ãè¦ã
- ä½è : MIO
- åºç社/ã¡ã¼ã«ã¼: ã·ã¼ã¢ã³ãã¢ã¼ã«ç 究æ
- çºå£²æ¥: 2018/05/29
- ã¡ãã£ã¢: Kindleç
- ãã®ååãå«ãããã°ãè¦ã
- ä½è : 渡ééæ
- åºç社/ã¡ã¼ã«ã¼: ã¤ã³ãã¬ã¹R&D
- çºå£²æ¥: 2018/10/05
- ã¡ãã£ã¢: ãªã³ããã³ã (ãã¼ãã¼ããã¯)
- ãã®ååãå«ãããã°ãè¦ã
åèã«ãããµã¤ãæ§
- SEO/mixiné¢é£
- TypeScript/åå®ç¾©é¢é£
- TypeScript ã®ãµãã¼ã â Vue.js
- vue-router/types at dev · vuejs/vue-router · GitHub
- vue-i18n/types at dev · kazupon/vue-i18n · GitHub
- nuxt-i18n/types at master · nuxt-community/nuxt-i18n · GitHub
- Vue.jsã¨TypeScript - Qiita
- nuxt.js/examples/typescript at dev · nuxt/nuxt.js · GitHub
- [GitHub - nuxt-community/nuxt-property-decorator: Property decorators for Nuxt (base on vue-property-decorator)]