AWS Amplify と AWS Cognito と TypeScript で作る ユーザー認証機能付き Next.js アプリ
AWS Amplify とは?
モバイルアプリケーションやウェブアプリケーションを構築するための JavaScript フレームワークです。 これを使うことで、後述する AWS Cognito を簡単に使用できます。
AWS Cognito とは?
ユーザー管理を一括で行ってくれるユーザー認証サービスです。 Auth0 の AWS版といったところでしょうか。
この様に色々と設定できます。
Next.js とは?
React.js でサーバーサイドレンダリングするためのフレームワークです。 Vue.js の Nuxt.js のようなものですね。
やってみよう!
1. Next.js with TypeScript な環境を作る
https://nextjs.org のサイトの手順を参考に、TypeScript に対応した Next.js アプリが実行できる環境を構築します。
ちなみに、筆者はyarn
を使うことが多いですが、公式ドキュメントは npm ベースです。npm を使われる方は適宜、置き換えてお読みください。
$ mkdir next-amplify-example [ken-yo@MacBook-Pro-2019-15inch ~]$ cd next-amplify-example [ken-yo@MacBook-Pro-2019-15inch next-amplify-example]$ yarn init -y yarn init v1.22.0 warning The yes flag has been set. This will automatically answer yes to all questions, which may have security implications. success Saved package.json ✨ Done in 0.02s. [ken-yo@MacBook-Pro-2019-15inch next-amplify-example]$ yarn add --save react react-dom next yarn add v1.22.0 info No lockfile found. [1/4] 🔍 Resolving packages... warning next > @babel/runtime-corejs2 > core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3. warning next > styled-jsx > babel-types > babel-runtime > core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3. [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... warning "next > styled-jsx@3.2.4" has unmet peer dependency "react@15.x.x || 16.x.x". warning "next > use-subscription@1.1.1" has unmet peer dependency "react@^16.8.0". warning " > react-dom@16.12.0" has unmet peer dependency "react@^16.0.0". warning " > next@9.2.2" has unmet peer dependency "react@^16.6.0". [4/4] 🔨 Building fresh packages... success Saved lockfile. success Saved 578 new dependencies. info Direct dependencies ├─ next@9.2.2 └─ react-dom@16.12.0 info All dependencies ├─ @ampproject/toolbox-optimizer@2.0.0 ├─ @ampproject/toolbox-runtime-version@2.0.0 ├─ @ampproject/toolbox-script-csp@2.0.0 ├─ @ampproject/toolbox-validator-rules@2.0.0 ├─ @babel/core@7.7.2 ├─ @babel/generator@7.8.4 ├─ @babel/helper-builder-binary-assignment-operator-visitor@7.8.3 ├─ @babel/helper-builder-react-jsx@7.8.3 ├─ @babel/helper-call-delegate@7.8.3 ├─ @babel/helper-create-class-features-plugin@7.8.3 ├─ @babel/helper-define-map@7.8.3 ├─ @babel/helper-explode-assignable-expression@7.8.3 ├─ @babel/helper-wrap-function@7.8.3 ├─ @babel/helpers@7.8.4 ├─ @babel/highlight@7.8.3 ├─ @babel/parser@7.8.4 ├─ @babel/plugin-proposal-async-generator-functions@7.8.3 ├─ @babel/plugin-proposal-class-properties@7.7.0 ├─ @babel/plugin-proposal-dynamic-import@7.8.3 ├─ @babel/plugin-proposal-json-strings@7.8.3 ├─ @babel/plugin-proposal-nullish-coalescing-operator@7.7.4 ├─ @babel/plugin-proposal-object-rest-spread@7.6.2 ├─ @babel/plugin-proposal-optional-catch-binding@7.8.3 ├─ @babel/plugin-proposal-optional-chaining@7.7.4 ├─ @babel/plugin-proposal-unicode-property-regex@7.8.3 ├─ @babel/plugin-syntax-async-generators@7.8.4 ├─ @babel/plugin-syntax-bigint@7.8.3 ├─ @babel/plugin-syntax-dynamic-import@7.8.3 ├─ @babel/plugin-syntax-json-strings@7.8.3 ├─ @babel/plugin-syntax-nullish-coalescing-operator@7.8.3 ├─ @babel/plugin-syntax-object-rest-spread@7.8.3 ├─ @babel/plugin-syntax-optional-catch-binding@7.8.3 ├─ @babel/plugin-syntax-optional-chaining@7.8.3 ├─ @babel/plugin-syntax-top-level-await@7.8.3 ├─ @babel/plugin-syntax-typescript@7.8.3 ├─ @babel/plugin-transform-arrow-functions@7.8.3 ├─ @babel/plugin-transform-async-to-generator@7.8.3 ├─ @babel/plugin-transform-block-scoped-functions@7.8.3 ├─ @babel/plugin-transform-block-scoping@7.8.3 ├─ @babel/plugin-transform-classes@7.8.3 ├─ @babel/plugin-transform-computed-properties@7.8.3 ├─ @babel/plugin-transform-destructuring@7.8.3 ├─ @babel/plugin-transform-dotall-regex@7.8.3 ├─ @babel/plugin-transform-duplicate-keys@7.8.3 ├─ @babel/plugin-transform-exponentiation-operator@7.8.3 ├─ @babel/plugin-transform-for-of@7.8.4 ├─ @babel/plugin-transform-function-name@7.8.3 ├─ @babel/plugin-transform-literals@7.8.3 ├─ @babel/plugin-transform-member-expression-literals@7.8.3 ├─ @babel/plugin-transform-modules-amd@7.8.3 ├─ @babel/plugin-transform-modules-commonjs@7.7.0 ├─ @babel/plugin-transform-modules-systemjs@7.8.3 ├─ @babel/plugin-transform-modules-umd@7.8.3 ├─ @babel/plugin-transform-named-capturing-groups-regex@7.8.3 ├─ @babel/plugin-transform-new-target@7.8.3 ├─ @babel/plugin-transform-object-super@7.8.3 ├─ @babel/plugin-transform-parameters@7.8.4 ├─ @babel/plugin-transform-property-literals@7.8.3 ├─ @babel/plugin-transform-react-display-name@7.8.3 ├─ @babel/plugin-transform-react-jsx-self@7.8.3 ├─ @babel/plugin-transform-react-jsx-source@7.8.3 ├─ @babel/plugin-transform-react-jsx@7.8.3 ├─ @babel/plugin-transform-regenerator@7.8.3 ├─ @babel/plugin-transform-reserved-words@7.8.3 ├─ @babel/plugin-transform-runtime@7.6.2 ├─ @babel/plugin-transform-shorthand-properties@7.8.3 ├─ @babel/plugin-transform-spread@7.8.3 ├─ @babel/plugin-transform-sticky-regex@7.8.3 ├─ @babel/plugin-transform-template-literals@7.8.3 ├─ @babel/plugin-transform-typeof-symbol@7.8.4 ├─ @babel/plugin-transform-typescript@7.8.3 ├─ @babel/plugin-transform-unicode-regex@7.8.3 ├─ @babel/preset-env@7.7.1 ├─ @babel/preset-modules@0.1.1 ├─ @babel/preset-react@7.7.0 ├─ @babel/preset-typescript@7.7.2 ├─ @babel/runtime-corejs2@7.7.2 ├─ @babel/runtime@7.7.2 ├─ @next/polyfill-nomodule@9.2.2 ├─ @webassemblyjs/floating-point-hex-parser@1.8.5 ├─ @webassemblyjs/helper-code-frame@1.8.5 ├─ @webassemblyjs/helper-fsm@1.8.5 ├─ @webassemblyjs/helper-wasm-section@1.8.5 ├─ @webassemblyjs/wasm-edit@1.8.5 ├─ @webassemblyjs/wasm-opt@1.8.5 ├─ @xtuc/ieee754@1.2.0 ├─ abbrev@1.1.1 ├─ accepts@1.3.7 ├─ acorn@6.4.0 ├─ adjust-sourcemap-loader@2.0.0 ├─ ajv-errors@1.0.1 ├─ ajv-keywords@3.4.1 ├─ ajv@6.11.0 ├─ amphtml-validator@1.0.23 ├─ ansi-colors@3.2.4 ├─ ansi-html@0.0.7 ├─ ansi-styles@3.2.1 ├─ anymatch@3.1.1 ├─ aproba@1.2.0 ├─ are-we-there-yet@1.1.5 ├─ argparse@1.0.10 ├─ arity-n@1.0.4 ├─ arr-flatten@1.1.0 ├─ array-union@1.0.2 ├─ array-uniq@1.0.3 ├─ asap@2.0.6 ├─ asn1.js@4.10.1 ├─ assert@1.4.1 ├─ assign-symbols@1.0.0 ├─ ast-types@0.13.2 ├─ async-each@1.0.3 ├─ async-retry@1.2.3 ├─ async-sema@3.0.0 ├─ atob@2.1.2 ├─ autodll-webpack-plugin@0.4.2 ├─ autoprefixer@9.7.4 ├─ babel-code-frame@6.26.0 ├─ babel-core@7.0.0-bridge.0 ├─ babel-loader@8.0.6 ├─ babel-plugin-transform-define@2.0.0 ├─ babel-plugin-transform-react-remove-prop-types@0.4.24 ├─ babel-runtime@6.26.0 ├─ babel-types@6.26.0 ├─ base@0.11.2 ├─ base64-js@1.3.1 ├─ binary-extensions@2.0.0 ├─ bindings@1.5.0 ├─ bluebird@3.7.2 ├─ brace-expansion@1.1.11 ├─ braces@2.3.2 ├─ browserify-aes@1.2.0 ├─ browserify-cipher@1.0.1 ├─ browserify-des@1.0.2 ├─ browserify-sign@4.0.4 ├─ browserify-zlib@0.2.0 ├─ buffer-equal-constant-time@1.0.1 ├─ buffer-json@2.0.0 ├─ buffer-xor@1.0.3 ├─ buffer@4.9.2 ├─ builtin-status-codes@3.0.0 ├─ bytes@3.0.0 ├─ cacache@12.0.3 ├─ cache-base@1.0.1 ├─ cache-loader@4.1.0 ├─ caller-callsite@2.0.0 ├─ caller-path@2.0.0 ├─ callsites@2.0.0 ├─ camelcase@5.3.1 ├─ caniuse-lite@1.0.30001028 ├─ chalk@2.4.2 ├─ chokidar@3.3.1 ├─ chownr@1.1.4 ├─ chrome-trace-event@1.0.2 ├─ ci-info@2.0.0 ├─ class-utils@0.3.6 ├─ cli-cursor@2.1.0 ├─ cli-spinners@2.2.0 ├─ clone-deep@4.0.1 ├─ clone@1.0.4 ├─ code-point-at@1.1.0 ├─ collection-visit@1.0.0 ├─ color-convert@1.9.3 ├─ color-name@1.1.3 ├─ colors@1.1.2 ├─ compose-function@3.0.3 ├─ compressible@2.0.18 ├─ compression@1.7.4 ├─ concat-map@0.0.1 ├─ concat-stream@1.6.2 ├─ conf@5.0.0 ├─ console-browserify@1.2.0 ├─ console-control-strings@1.1.0 ├─ constants-browserify@1.0.0 ├─ content-type@1.0.4 ├─ cookie@0.4.0 ├─ copy-concurrently@1.0.5 ├─ copy-descriptor@0.1.1 ├─ core-js-compat@3.6.4 ├─ core-js@2.6.11 ├─ core-util-is@1.0.2 ├─ cosmiconfig@5.2.1 ├─ create-ecdh@4.0.3 ├─ create-hmac@1.1.7 ├─ crypto-browserify@3.12.0 ├─ css-blank-pseudo@0.1.4 ├─ css-has-pseudo@0.10.0 ├─ css-loader@3.3.0 ├─ css-prefers-color-scheme@3.1.1 ├─ css@2.2.4 ├─ cssdb@4.4.0 ├─ cssnano-preset-simple@1.0.3 ├─ cssnano-simple@1.0.0 ├─ cyclist@1.0.1 ├─ d@1.0.1 ├─ debug@2.6.9 ├─ decode-uri-component@0.2.0 ├─ deep-extend@0.6.0 ├─ defaults@1.0.3 ├─ define-properties@1.1.3 ├─ del@3.0.0 ├─ delegates@1.0.0 ├─ des.js@1.0.1 ├─ destroy@1.0.4 ├─ detect-libc@1.0.3 ├─ devalue@2.0.1 ├─ diffie-hellman@5.0.3 ├─ dom-serializer@0.2.2 ├─ domain-browser@1.2.0 ├─ domutils@2.0.0 ├─ dot-prop@5.2.0 ├─ duplexer@0.1.1 ├─ duplexify@3.7.1 ├─ ecdsa-sig-formatter@1.0.11 ├─ ee-first@1.1.1 ├─ electron-to-chromium@1.3.358 ├─ emojis-list@3.0.0 ├─ encodeurl@1.0.2 ├─ enhanced-resolve@4.1.1 ├─ env-paths@2.2.0 ├─ errno@0.1.7 ├─ error-ex@1.3.2 ├─ es5-ext@0.10.53 ├─ es6-iterator@2.0.3 ├─ es6-symbol@3.1.3 ├─ escape-html@1.0.3 ├─ escape-string-regexp@1.0.5 ├─ eslint-scope@4.0.3 ├─ esprima@4.0.1 ├─ esrecurse@4.2.1 ├─ estraverse@4.3.0 ├─ esutils@2.0.3 ├─ etag@1.8.1 ├─ eventemitter3@4.0.0 ├─ events@3.1.0 ├─ evp_bytestokey@1.0.3 ├─ expand-brackets@2.1.4 ├─ ext@1.4.0 ├─ extglob@2.0.4 ├─ fast-deep-equal@3.1.1 ├─ fast-json-stable-stringify@2.1.0 ├─ file-loader@4.2.0 ├─ file-uri-to-path@1.0.0 ├─ fill-range@4.0.0 ├─ finally-polyfill@0.1.0 ├─ find-cache-dir@2.1.0 ├─ flatten@1.0.3 ├─ flush-write-stream@1.1.1 ├─ follow-redirects@1.10.0 ├─ for-in@1.0.2 ├─ fork-ts-checker-webpack-plugin@3.1.1 ├─ from2@2.3.0 ├─ fs-minipass@1.2.7 ├─ fs.realpath@1.0.0 ├─ fsevents@2.1.2 ├─ gauge@2.7.4 ├─ get-value@2.0.6 ├─ glob-parent@5.1.0 ├─ glob-to-regexp@0.4.1 ├─ glob@7.1.6 ├─ globby@6.1.0 ├─ graceful-readlink@1.0.1 ├─ gzip-size@5.1.1 ├─ has-ansi@2.0.0 ├─ has-symbols@1.0.1 ├─ has-unicode@2.0.1 ├─ has-value@1.0.0 ├─ has@1.0.3 ├─ hash.js@1.1.7 ├─ hmac-drbg@1.0.1 ├─ hosted-git-info@2.8.5 ├─ html-entities@1.2.1 ├─ htmlparser2@4.0.0 ├─ http-errors@1.7.2 ├─ http-proxy@1.18.0 ├─ https-browserify@1.0.0 ├─ iconv-lite@0.4.24 ├─ icss-utils@4.1.1 ├─ ieee754@1.1.13 ├─ ignore-loader@0.1.2 ├─ ignore-walk@3.0.3 ├─ import-cwd@2.1.0 ├─ import-fresh@2.0.0 ├─ import-from@2.1.0 ├─ infer-owner@1.0.4 ├─ inflight@1.0.6 ├─ ini@1.3.5 ├─ invariant@2.2.4 ├─ is-accessor-descriptor@1.0.0 ├─ is-arrayish@0.2.1 ├─ is-binary-path@2.1.0 ├─ is-data-descriptor@1.0.0 ├─ is-descriptor@1.0.2 ├─ is-directory@0.3.1 ├─ is-docker@2.0.0 ├─ is-extglob@2.1.1 ├─ is-fullwidth-code-point@1.0.0 ├─ is-glob@4.0.1 ├─ is-obj@2.0.0 ├─ is-path-cwd@1.0.0 ├─ is-path-in-cwd@1.0.1 ├─ is-path-inside@1.0.1 ├─ is-plain-obj@1.1.0 ├─ is-plain-object@2.0.4 ├─ is-windows@1.0.2 ├─ is-wsl@2.1.1 ├─ isarray@1.0.0 ├─ jest-worker@24.9.0 ├─ js-levenshtein@1.1.6 ├─ js-tokens@4.0.0 ├─ js-yaml@3.13.1 ├─ jsesc@2.5.2 ├─ json-parse-better-errors@1.0.2 ├─ json-schema-traverse@0.4.1 ├─ json-schema-typed@7.0.3 ├─ jsonwebtoken@8.5.1 ├─ jwa@1.4.1 ├─ jws@3.2.2 ├─ launch-editor@2.2.1 ├─ load-json-file@2.0.0 ├─ loader-runner@2.4.0 ├─ lodash.curry@4.1.1 ├─ lodash.includes@4.3.0 ├─ lodash.isboolean@3.0.3 ├─ lodash.isinteger@4.0.4 ├─ lodash.isnumber@3.0.3 ├─ lodash.isplainobject@4.0.6 ├─ lodash.isstring@4.0.1 ├─ lodash.once@4.1.1 ├─ lodash.template@4.5.0 ├─ lodash.templatesettings@4.2.0 ├─ log-symbols@2.2.0 ├─ loose-envify@1.4.0 ├─ lru-cache@5.1.1 ├─ mamacro@0.0.3 ├─ map-visit@1.0.0 ├─ merge-stream@2.0.0 ├─ microevent.ts@0.1.1 ├─ miller-rabin@4.0.1 ├─ mime-db@1.43.0 ├─ mime-types@2.1.26 ├─ mime@1.6.0 ├─ mimic-fn@1.2.0 ├─ mini-css-extract-plugin@0.8.0 ├─ minimalistic-crypto-utils@1.0.1 ├─ minimatch@3.0.4 ├─ minimist@1.2.0 ├─ minipass@2.9.0 ├─ minizlib@1.3.3 ├─ mississippi@3.0.0 ├─ mixin-deep@1.3.2 ├─ move-concurrently@1.0.1 ├─ nan@2.14.0 ├─ nanomatch@1.2.13 ├─ needle@2.3.2 ├─ negotiator@0.6.2 ├─ next-tick@1.0.0 ├─ next@9.2.2 ├─ node-libs-browser@2.2.1 ├─ node-pre-gyp@0.14.0 ├─ node-releases@1.1.50 ├─ nopt@4.0.1 ├─ normalize-html-whitespace@1.0.0 ├─ normalize-package-data@2.5.0 ├─ normalize-range@0.1.2 ├─ normalize-url@1.9.1 ├─ npm-bundled@1.1.1 ├─ npm-packlist@1.4.8 ├─ npmlog@4.1.2 ├─ num2fraction@1.2.2 ├─ number-is-nan@1.0.1 ├─ object-assign@4.1.1 ├─ object-copy@0.1.0 ├─ object-keys@1.1.1 ├─ object-path@0.11.4 ├─ on-finished@2.3.0 ├─ on-headers@1.0.2 ├─ onetime@2.0.1 ├─ ora@3.4.0 ├─ os-browserify@0.3.0 ├─ os-homedir@1.0.2 ├─ os-tmpdir@1.0.2 ├─ osenv@0.1.5 ├─ p-limit@2.2.2 ├─ p-locate@4.1.0 ├─ p-map@1.2.0 ├─ p-try@2.2.0 ├─ pako@1.0.11 ├─ parallel-transform@1.2.0 ├─ parse-json@2.2.0 ├─ pascalcase@0.1.1 ├─ path-browserify@0.0.1 ├─ path-dirname@1.0.2 ├─ path-is-inside@1.0.2 ├─ path-parse@1.0.6 ├─ path-to-regexp@6.1.0 ├─ path-type@2.0.0 ├─ picomatch@2.2.1 ├─ pinkie-promise@2.0.1 ├─ pinkie@2.0.4 ├─ pkg-dir@3.0.0 ├─ pkg-up@3.1.0 ├─ pnp-webpack-plugin@1.5.0 ├─ posix-character-classes@0.1.1 ├─ postcss-attribute-case-insensitive@4.0.2 ├─ postcss-color-functional-notation@2.0.1 ├─ postcss-color-gray@5.0.0 ├─ postcss-color-hex-alpha@5.0.3 ├─ postcss-color-mod-function@3.0.3 ├─ postcss-color-rebeccapurple@4.0.1 ├─ postcss-custom-media@7.0.8 ├─ postcss-custom-properties@8.0.11 ├─ postcss-custom-selectors@5.1.2 ├─ postcss-dir-pseudo-class@5.0.0 ├─ postcss-double-position-gradients@1.0.0 ├─ postcss-env-function@2.0.2 ├─ postcss-flexbugs-fixes@4.1.0 ├─ postcss-focus-visible@4.0.0 ├─ postcss-focus-within@3.0.0 ├─ postcss-font-variant@4.0.0 ├─ postcss-gap-properties@2.0.0 ├─ postcss-image-set-function@3.0.1 ├─ postcss-initial@3.0.2 ├─ postcss-lab-function@2.0.1 ├─ postcss-load-config@2.1.0 ├─ postcss-loader@3.0.0 ├─ postcss-logical@3.0.0 ├─ postcss-media-minmax@4.0.0 ├─ postcss-modules-extract-imports@2.0.0 ├─ postcss-modules-local-by-default@3.0.2 ├─ postcss-modules-scope@2.1.1 ├─ postcss-modules-values@3.0.0 ├─ postcss-nesting@7.0.1 ├─ postcss-overflow-shorthand@2.0.0 ├─ postcss-page-break@2.0.0 ├─ postcss-place@4.0.1 ├─ postcss-preset-env@6.7.0 ├─ postcss-pseudo-class-any-link@6.0.0 ├─ postcss-replace-overflow-wrap@3.0.0 ├─ postcss-selector-matches@4.0.0 ├─ postcss-selector-not@4.0.0 ├─ prepend-http@1.0.4 ├─ private@0.1.8 ├─ process-nextick-args@2.0.1 ├─ process@0.11.10 ├─ promise-inflight@1.0.1 ├─ promise@7.1.1 ├─ prop-types-exact@1.2.0 ├─ prop-types@15.7.2 ├─ prr@1.0.1 ├─ public-encrypt@4.0.3 ├─ pump@3.0.0 ├─ pumpify@1.5.1 ├─ punycode@1.3.2 ├─ query-string@4.3.4 ├─ querystring-es3@0.2.1 ├─ querystring@0.2.0 ├─ randomfill@1.0.4 ├─ range-parser@1.2.1 ├─ raw-body@2.4.0 ├─ rc@1.2.8 ├─ react-dom@16.12.0 ├─ react-error-overlay@5.1.6 ├─ react-is@16.8.6 ├─ read-pkg@2.0.0 ├─ readable-stream@2.3.7 ├─ readdirp@3.3.0 ├─ recast@0.18.5 ├─ reflect.ownkeys@0.2.0 ├─ regenerate-unicode-properties@8.1.0 ├─ regenerator-transform@0.14.1 ├─ regex-parser@2.2.10 ├─ regexpu-core@4.6.0 ├─ regjsgen@0.5.1 ├─ regjsparser@0.6.3 ├─ remove-trailing-separator@1.1.0 ├─ repeat-element@1.1.3 ├─ requires-port@1.0.0 ├─ resolve-url-loader@3.1.1 ├─ resolve-url@0.2.1 ├─ resolve@1.15.1 ├─ restore-cursor@2.0.0 ├─ ret@0.1.15 ├─ retry@0.12.0 ├─ rework-visit@1.0.0 ├─ rework@1.0.1 ├─ run-queue@1.0.3 ├─ safer-buffer@2.1.2 ├─ sass-loader@8.0.2 ├─ sax@1.2.4 ├─ scheduler@0.18.0 ├─ schema-utils@2.6.4 ├─ semver@5.7.1 ├─ send@0.17.1 ├─ serialize-javascript@2.1.2 ├─ set-blocking@2.0.0 ├─ set-value@2.0.1 ├─ setimmediate@1.0.5 ├─ shallow-clone@3.0.1 ├─ shell-quote@1.7.2 ├─ signal-exit@3.0.2 ├─ snapdragon-node@2.1.1 ├─ snapdragon-util@3.0.1 ├─ sort-keys@1.1.2 ├─ source-list-map@2.0.1 ├─ source-map-resolve@0.5.3 ├─ source-map-url@0.4.0 ├─ spdx-correct@3.1.0 ├─ spdx-exceptions@2.2.0 ├─ split-string@3.1.0 ├─ sprintf-js@1.0.3 ├─ ssri@6.0.1 ├─ static-extend@0.1.2 ├─ stream-browserify@2.0.2 ├─ stream-each@1.2.3 ├─ stream-http@2.8.3 ├─ strict-uri-encode@1.1.0 ├─ string_decoder@1.1.1 ├─ string-width@1.0.2 ├─ strip-ansi@3.0.1 ├─ strip-bom@3.0.0 ├─ strip-json-comments@2.0.1 ├─ style-loader@1.0.0 ├─ styled-jsx@3.2.4 ├─ stylis-rule-sheet@0.0.10 ├─ stylis@3.5.4 ├─ tar@4.4.13 ├─ terser-webpack-plugin@1.4.3 ├─ terser@4.6.3 ├─ thread-loader@2.1.3 ├─ through2@2.0.5 ├─ timers-browserify@2.0.11 ├─ to-arraybuffer@1.0.1 ├─ to-fast-properties@1.0.3 ├─ to-object-path@0.3.0 ├─ to-regex-range@2.1.1 ├─ traverse@0.6.6 ├─ ts-pnp@1.1.6 ├─ tslib@1.11.0 ├─ tty-browserify@0.0.0 ├─ type@1.2.0 ├─ typedarray-to-buffer@3.1.5 ├─ typedarray@0.0.6 ├─ unfetch@4.1.0 ├─ unicode-canonical-property-names-ecmascript@1.0.4 ├─ unicode-match-property-ecmascript@1.0.4 ├─ unicode-match-property-value-ecmascript@1.1.0 ├─ unicode-property-aliases-ecmascript@1.0.5 ├─ union-value@1.0.1 ├─ unique-filename@1.1.1 ├─ unique-slug@2.0.2 ├─ unpipe@1.0.0 ├─ unset-value@1.0.0 ├─ upath@1.2.0 ├─ uri-js@4.2.2 ├─ url-polyfill@1.1.7 ├─ url@0.11.0 ├─ use-subscription@1.1.1 ├─ use@3.1.1 ├─ util-deprecate@1.0.2 ├─ uuid@3.4.0 ├─ validate-npm-package-license@3.0.4 ├─ vary@1.1.2 ├─ vm-browserify@1.1.2 ├─ watchpack@2.0.0-beta.5 ├─ wcwidth@1.0.1 ├─ webpack-dev-middleware@3.7.0 ├─ webpack-hot-middleware@2.25.0 ├─ webpack-log@2.0.0 ├─ webpack-merge@4.2.2 ├─ webpack-sources@1.4.3 ├─ webpack@4.41.2 ├─ wide-align@1.1.3 ├─ worker-farm@1.7.0 ├─ worker-rpc@0.1.1 ├─ write-file-atomic@3.0.1 ├─ xtend@4.0.2 ├─ y18n@4.0.0 └─ yallist@3.1.1 ✨ Done in 10.63s. $ mkdir -p src/pages $ yarn add --save-dev typescript @types/react @types/node yarn add v1.22.0 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... warning " > next@9.2.2" has unmet peer dependency "react@^16.6.0". warning "next > styled-jsx@3.2.4" has unmet peer dependency "react@15.x.x || 16.x.x". warning "next > use-subscription@1.1.1" has unmet peer dependency "react@^16.8.0". warning " > react-dom@16.12.0" has unmet peer dependency "react@^16.0.0". [4/4] 🔨 Building fresh packages... success Saved lockfile. success Saved 4 new dependencies. info Direct dependencies ├─ @types/node@13.7.4 └─ @types/react@16.9.22 info All dependencies ├─ @types/node@13.7.4 ├─ @types/prop-types@15.7.3 ├─ @types/react@16.9.22 └─ csstype@2.6.9 ✨ Done in 2.02s. $ yarn add react yarn add v1.22.0 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 🔨 Building fresh packages... success Saved lockfile. success Saved 1 new dependency. info Direct dependencies └─ react@16.12.0 info All dependencies └─ react@16.12.0 ✨ Done in 1.73s. $ yarn run dev yarn run v1.22.0 $ next [ wait ] starting the development server ... [ info ] waiting on http://localhost:3000 ... It looks like you're trying to use TypeScript but do not have the required package(s) installed. Please install typescript by running: yarn add --dev typescript If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files). error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. $ yarn add --dev typescript yarn add v1.22.0 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... [4/4] 🔨 Building fresh packages... success Saved lockfile. success Saved 1 new dependency. info Direct dependencies └─ typescript@3.8.2 info All dependencies └─ typescript@3.8.2 ✨ Done in 2.02s.
tsconfig.json や、 next.config.js 、public/sw.js などは各自調べて追加してください。(ぉぃ
地味に大変なので、テンプレートリポジトリー化しています。
2. amplify の導入
オフィシャルドキュメント https://aws-amplify.github.io/docs/ のとおり、CLIインストールと設定を行います。
npm install -g @aws-amplify/cli amplify configure
AWS 管理コンソールが起動して、使うリージョンだとか、amplify を管理するための(?) IAM ユーザーの作成などをターミナルに表示されたメッセージに従って行います。
3. アプリケーションへの適用
3.1. nom モジュールのインストール
amplify には色々な AWS サービスを使うための npm モジュールがあるようですが、今回は以下の 3つを使用します。
yarn add aws-amplify @aws-amplify/auth aws-amplify-react
3.2. amplify アプリの初期化
3.2.1. amplify init
amplify init
を実行すると、プロジェクト名や使用するエディター、環境名などの選択や入力を求められます。 指示に従って進めると、バックエンドコードが出力されます。
これは、後ほど amplify コマンドで使うことになる CloudFormation テンプレートや CloudFormation Stack などです。
$ amplify init Note: It is recommended to run this command from the root of your app directory ? Enter a name for the project next-amplify-example ? Enter a name for the environment dev ? Choose your default editor: Visual Studio Code ? Choose the type of app that you're building javascript Please tell us about your project ? What javascript framework are you using react ? Source Directory Path: src ? Distribution Directory Path: build ? Build Command: yarn build ? Start Command: yarn start Using default provider awscloudformation For more information on AWS Profiles, see: https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html ? Do you want to use an AWS profile? Yes ? Please choose the profile you want to use amplify Adding backend environment dev to AWS Amplify Console app: d1ntmmvoqyxue2 ⠏ Initializing project in the cloud... CREATE_IN_PROGRESS DeploymentBucket AWS::S3::Bucket Sat Feb 22 2020 19:27:48 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UnauthRole AWS::IAM::Role Sat Feb 22 2020 19:27:47 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS AuthRole AWS::IAM::Role Sat Feb 22 2020 19:27:47 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UnauthRole AWS::IAM::Role Sat Feb 22 2020 19:27:46 GMT+0900 (日本標準時) CREATE_IN_PROGRESS DeploymentBucket AWS::S3::Bucket Sat Feb 22 2020 19:27:46 GMT+0900 (日本標準時) CREATE_IN_PROGRESS AuthRole AWS::IAM::Role Sat Feb 22 2020 19:27:46 GMT+0900 (日本標準時) CREATE_IN_PROGRESS amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 19:27:43 GMT+0900 (日本標準時) User Initiated ⠼ Initializing project in the cloud... CREATE_COMPLETE UnauthRole AWS::IAM::Role Sat Feb 22 2020 19:28:01 GMT+0900 (日本標準時) CREATE_COMPLETE AuthRole AWS::IAM::Role Sat Feb 22 2020 19:28:01 GMT+0900 (日本標準時) ⠼ Initializing project in the cloud... CREATE_COMPLETE DeploymentBucket AWS::S3::Bucket Sat Feb 22 2020 19:28:08 GMT+0900 (日本標準時) ⠦ Initializing project in the cloud... CREATE_COMPLETE amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 19:28:11 GMT+0900 (日本標準時) ✔ Successfully created initial AWS cloud resources for deployments. ✔ Initialized provider successfully. Initialized your environment successfully. Your project has been successfully initialized and connected to the cloud! Some next steps: "amplify status" will show you what you've added already and if it's locally configured or deployed "amplify add <category>" will allow you to add features like user login or a backend API "amplify push" will build all your local backend resources and provision it in the cloud “amplify console” to open the Amplify Console and view your project status "amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud Pro tip: Try "amplify add api" to create a backend API and then "amplify publish" to deploy everything
import React from 'react' class Home extends React.Component { render() { return ( <div> <div className="hero"> <h1 className="title">Welcome to Next.js!</h1> <p className="description"> To get started, edit <code>pages/index.js</code> and save to reload. </p> <div className="row"> <a href="https://nextjs.org/docs" className="card"> <h3>Documentation →</h3> <p>Learn more about Next.js in the documentation.</p> </a> <a href="https://nextjs.org/learn" className="card"> <h3>Next.js Learn →</h3> <p>Learn about Next.js by following an interactive tutorial!</p> </a> <a href="https://github.com/zeit/next.js/tree/master/examples" className="card" > <h3>Examples →</h3> <p>Find other example boilerplates on the Next.js GitHub.</p> </a> </div> </div> <style jsx>{` .hero { width: 100%; color: #333; } .title { margin: 0; width: 100%; padding-top: 80px; line-height: 1.15; font-size: 48px; } .title, .description { text-align: center; } .row { max-width: 880px; margin: 80px auto 40px; display: flex; flex-direction: row; justify-content: space-around; } .card { padding: 18px 18px 24px; width: 220px; text-align: left; text-decoration: none; color: #434343; border: 1px solid #9b9b9b; } .card:hover { border-color: #067df7; } .card h3 { margin: 0; color: #067df7; font-size: 18px; } .card p { margin: 0; padding: 12px 0 0; font-size: 13px; color: #333; } `}</style> </div> ) } } export default Home
3.2.2. amplify add auth
amplify から Cognito を使用して認証するため、 amplify add auth を行います。 多分、Cognito 以外も使えそうですが、今回は Cognito を使うために追加するとお考えください。
amplify add auth
こんな感じです。今回はザルセキュリティで良い(あくまでもサンプルなので)ので、ユーザー名とパスワードでのみの認証とします。 (本来なら、メールアドレス他、色々と設定すべきでしょう)
$ amplify add auth Using service: Cognito, provided by: awscloudformation The current configured provider is Amazon Cognito. Do you want to use the default authentication and security configuration? Default configuration Warning: you will not be able to edit these selections. How do you want users to be able to sign in? Username Do you want to configure advanced settings? No, I am done. Successfully added resource nextamplifyexample6c8f8585 locally Some next steps: "amplify push" will build all your local backend resources and provision it in the cloud "amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
3.3. amplify バックグラウンド(AWS側のリソース)の構築
"amplify push" will build all your local backend resources and provision it in the cloud
とあるように、AWS側のリソースを構築する必要があります。
amplify push
を実行すると、CloudFormation スタックが更新されて ネステッドスタックとなります。 また、Cognito のリソースが作られます。
$ amplify push ✔ Successfully pulled backend environment dev from the cloud. Current Environment: dev | Category | Resource name | Operation | Provider plugin | | -------- | -------------------------- | --------- | ----------------- | | Auth | nextamplifyexample0dde88af | Create | awscloudformation | ? Are you sure you want to continue? Yes ⠏ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS authnextamplifyexample0dde88af AWS::CloudFormation::Stack Sat Feb 22 2020 19:37:35 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS authnextamplifyexample0dde88af AWS::CloudFormation::Stack Sat Feb 22 2020 19:37:34 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UpdateRolesWithIDPFunctionRole AWS::IAM::Role Sat Feb 22 2020 19:37:34 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UpdateRolesWithIDPFunctionRole AWS::IAM::Role Sat Feb 22 2020 19:37:33 GMT+0900 (日本標準時) UPDATE_IN_PROGRESS amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 19:37:29 GMT+0900 (日本標準時) User Initiated ⠴ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS amplify-next-amplify-example-dev-192739-authnextamplifyexample0dde88af-1PWQ9Y8ZW1F9F AWS::CloudFormation::Stack Sat Feb 22 2020 19:37:35 GMT+0900 (日本標準時) User Initiated ⠇ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS SNSRole AWS::IAM::Role Sat Feb 22 2020 19:37:40 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS SNSRole AWS::IAM::Role Sat Feb 22 2020 19:37:40 GMT+0900 (日本標準時) ⠴ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UpdateRolesWithIDPFunctionRole AWS::IAM::Role Sat Feb 22 2020 19:37:48 GMT+0900 (日本標準時) ⠹ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE SNSRole AWS::IAM::Role Sat Feb 22 2020 19:37:55 GMT+0900 (日本標準時) ⠼ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UserPool AWS::Cognito::UserPool Sat Feb 22 2020 19:37:58 GMT+0900 (日本標準時) ⠸ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UserPool AWS::Cognito::UserPool Sat Feb 22 2020 19:38:01 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UserPool AWS::Cognito::UserPool Sat Feb 22 2020 19:38:01 GMT+0900 (日本標準時) Resource creation Initiated ⠴ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UserPoolClient AWS::Cognito::UserPoolClient Sat Feb 22 2020 19:38:06 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UserPoolClient AWS::Cognito::UserPoolClient Sat Feb 22 2020 19:38:05 GMT+0900 (日本標準時) Resource creation Initiated CREATE_COMPLETE UserPoolClientWeb AWS::Cognito::UserPoolClient Sat Feb 22 2020 19:38:05 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UserPoolClientWeb AWS::Cognito::UserPoolClient Sat Feb 22 2020 19:38:05 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UserPoolClient AWS::Cognito::UserPoolClient Sat Feb 22 2020 19:38:04 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UserPoolClientWeb AWS::Cognito::UserPoolClient Sat Feb 22 2020 19:38:04 GMT+0900 (日本標準時) ⠇ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UserPoolClientRole AWS::IAM::Role Sat Feb 22 2020 19:38:10 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UserPoolClientRole AWS::IAM::Role Sat Feb 22 2020 19:38:09 GMT+0900 (日本標準時) ⠸ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UserPoolClientRole AWS::IAM::Role Sat Feb 22 2020 19:38:24 GMT+0900 (日本標準時) ⠸ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UserPoolClientLambda AWS::Lambda::Function Sat Feb 22 2020 19:38:28 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UserPoolClientLambda AWS::Lambda::Function Sat Feb 22 2020 19:38:27 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UserPoolClientLambda AWS::Lambda::Function Sat Feb 22 2020 19:38:27 GMT+0900 (日本標準時) ⠹ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UserPoolClientLambdaPolicy AWS::IAM::Policy Sat Feb 22 2020 19:38:31 GMT+0900 (日本標準時) ⠼ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UserPoolClientLambdaPolicy AWS::IAM::Policy Sat Feb 22 2020 19:38:32 GMT+0900 (日本標準時) Resource creation Initiated ⠇ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UserPoolClientLambdaPolicy AWS::IAM::Policy Sat Feb 22 2020 19:38:45 GMT+0900 (日本標準時) ⠧ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UserPoolClientLogPolicy AWS::IAM::Policy Sat Feb 22 2020 19:38:49 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UserPoolClientLogPolicy AWS::IAM::Policy Sat Feb 22 2020 19:38:48 GMT+0900 (日本標準時) ⠹ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UserPoolClientInputs Custom::LambdaCallout Sat Feb 22 2020 19:39:05 GMT+0900 (日本標準時) CREATE_COMPLETE UserPoolClientLogPolicy AWS::IAM::Policy Sat Feb 22 2020 19:39:03 GMT+0900 (日本標準時) ⠹ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE UserPoolClientInputs Custom::LambdaCallout Sat Feb 22 2020 19:39:09 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UserPoolClientInputs Custom::LambdaCallout Sat Feb 22 2020 19:39:09 GMT+0900 (日本標準時) Resource creation Initiated ⠦ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE IdentityPool AWS::Cognito::IdentityPool Sat Feb 22 2020 19:39:14 GMT+0900 (日本標準時) CREATE_IN_PROGRESS IdentityPool AWS::Cognito::IdentityPool Sat Feb 22 2020 19:39:13 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS IdentityPool AWS::Cognito::IdentityPool Sat Feb 22 2020 19:39:12 GMT+0900 (日本標準時) ⠦ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE IdentityPoolRoleMap AWS::Cognito::IdentityPoolRoleAttachment Sat Feb 22 2020 19:39:20 GMT+0900 (日本標準時) CREATE_IN_PROGRESS IdentityPoolRoleMap AWS::Cognito::IdentityPoolRoleAttachment Sat Feb 22 2020 19:39:20 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS IdentityPoolRoleMap AWS::Cognito::IdentityPoolRoleAttachment Sat Feb 22 2020 19:39:18 GMT+0900 (日本標準時) ⠙ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE amplify-next-amplify-example-dev-192739-authnextamplifyexample0dde88af-1PWQ9Y8ZW1F9F AWS::CloudFormation::Stack Sat Feb 22 2020 19:39:22 GMT+0900 (日本標準時) ⠋ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE authnextamplifyexample0dde88af AWS::CloudFormation::Stack Sat Feb 22 2020 19:39:29 GMT+0900 (日本標準時) ⠏ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UpdateRolesWithIDPFunction AWS::Lambda::Function Sat Feb 22 2020 19:39:31 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS UpdateRolesWithIDPFunction AWS::Lambda::Function Sat Feb 22 2020 19:39:30 GMT+0900 (日本標準時) ⠹ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS UpdateRolesWithIDPFunctionOutputs Custom::LambdaCallout Sat Feb 22 2020 19:39:33 GMT+0900 (日本標準時) CREATE_COMPLETE UpdateRolesWithIDPFunction AWS::Lambda::Function Sat Feb 22 2020 19:39:31 GMT+0900 (日本標準時) ⠼ Updating resources in the cloud. This may take a few minutes... UPDATE_COMPLETE amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 19:39:39 GMT+0900 (日本標準時) UPDATE_COMPLETE_CLEANUP_IN_PROGRESS amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 19:39:39 GMT+0900 (日本標準時) CREATE_COMPLETE UpdateRolesWithIDPFunctionOutputs Custom::LambdaCallout Sat Feb 22 2020 19:39:37 GMT+0900 (日本標準時) CREATE_IN_PROGRESS UpdateRolesWithIDPFunctionOutputs Custom::LambdaCallout Sat Feb 22 2020 19:39:36 GMT+0900 (日本標準時) Resource creation Initiated ✔ All resources are updated in the cloud
ここまでで、Cognito を呼び出す下地は出来ました。
あとは、アプリのコードから amplify を使って Cognito を呼び出すだけです!
3.4. アプリへの組み込み
に従って組み込んでみましょう!
因みに、今回は pages/index.tsx へ組み込みました。 Layout など、components 配下のコンポーネントを必ず組み込むようにする場合は、そちらに記述した方が良いかもしれません。
import Amplify from 'aws-amplify'; import config from '../aws-exports'; Amplify.configure(config); class Home extends React.Component { render() { return ( <div> // 以下略
続いて pages/_app.tsx
import * as React from 'react'; import App from 'next/app'; import { withAuthenticator } from 'aws-amplify-react'; class MyApp extends App { render() { const { Component, pageProps } = this.props; return (<Component {...pageProps} />) } } export default withAuthenticator(MyApp)
さぁ!これで yarn run dev
すっぞ!
$ yarn run dev yarn run v1.22.0 $ next [ wait ] starting the development server ... [ info ] waiting on http://localhost:3000 ... [ error ] ./node_modules/@aws-amplify/ui/dist/style.css Global CSS cannot be imported from within node_modules. Read more: https://err.sh/next.js/css-npm Location: node_modules/aws-amplify-react/lib-esm/Amplify-UI/Amplify-UI-Components-React.js
はい。。。コケました。
@zeit/next-css
を追加して、 next.config.js
を修正すれば良いようです。
$ yarn add -D @zeit/next-css yarn add v1.22.0 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... warning "aws-amplify > @aws-amplify/api@2.1.5" has incorrect peer dependency "@aws-amplify/pubsub@^1.2.4". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/analytics@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/api@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/auth@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/core@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/interactions@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/storage@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/ui@^2.0.0". warning "@zeit/next-css > css-loader@1.0.0" has unmet peer dependency "webpack@^4.0.0". warning "@zeit/next-css > mini-css-extract-plugin@0.4.3" has unmet peer dependency "webpack@^4.4.0". [4/4] 🔨 Building fresh packages... warning "@zeit/next-css" is already in "dependencies". Please remove existing entry first before adding it to "devDependencies". success Saved 1 new dependency. info Direct dependencies └─ @zeit/next-css@1.0.1 info All dependencies └─ @zeit/next-css@1.0.1 ✨ Done in 1.85s.
const withCSS = require("@zeit/next-css"); if (typeof require !== "undefined") { require.extensions[".less"] = () => {}; require.extensions[".css"] = (file) => {}; } const config = { target: process.env.NODE_ENV !== 'production' ? 'server' : 'serverless', dontAutoRegisterSw: false, generateSw: false, devSwSrc: 'src/public/sw.js', workboxOpts: { swSrc: 'src/public/sw.js', swDest: 'src/public/service-worker.js' } } module.exports = withCSS(config)
としました。
$ yarn run dev yarn run v1.22.0 $ next [ wait ] starting the development server ... [ info ] waiting on http://localhost:3000 ... [ info ] bundled successfully, waiting for typecheck results... [ wait ] compiling ... [ info ] bundled successfully, waiting for typecheck results... [ ready ] compiled successfully - ready on http://localhost:3000 [ event ] build page: /next/dist/pages/_error [ wait ] compiling ... [ info ] bundled successfully, waiting for typecheck results... [ ready ] compiled successfully - ready on http://localhost:3000 [ event ] build page: / [ wait ] compiling ... [ info ] bundled successfully, waiting for typecheck results... [ ready ] compiled successfully - ready on http://localhost:3000 [ info ] bundled successfully, waiting for typecheck results... [ ready ] compiled successfully - ready on http://localhost:3000
エラーがなくなりました。
http://localhost:3000 へアクセスしましょう。
きたー!
ユーザー登録(Create account をクリック)時に入力したメールアドレスに以下のようなワンタイムトークンが送られてくるため、 遷移した画面で入力します。
すると。。。
に戻ります。
ここで、登録したユーザー名とパスワードを入力して SIGN IN をクリックするとログイン出来ます。
4. サインアウト機能
さて、ここまでで Amplify と Cognitoを使用して、ローカルでサインイン出来るようになりました。
でも、サインアウト出来るようにしておかないとダメですよね?(滅多に使わないから期間過ぎたら自動的にサインアウトするように Cognito を設定しておけばよくね?というツッコミは無しで)
テキストリンクでも良いのですが、ボタンを配置してみましょう。
Material UI コンポーネントを追加します。
yarn add @material-ui/core @material-ui/icons
$ yarn add @material-ui/core @material-ui/icons yarn add v1.22.0 [1/4] 🔍 Resolving packages... warning @material-ui/core > popper.js@1.16.1: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... warning "@zeit/next-css > css-loader@1.0.0" has unmet peer dependency "webpack@^4.0.0". warning "@zeit/next-css > mini-css-extract-plugin@0.4.3" has unmet peer dependency "webpack@^4.4.0". warning "aws-amplify > @aws-amplify/api@2.1.5" has incorrect peer dependency "@aws-amplify/pubsub@^1.2.4". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/analytics@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/api@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/auth@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/core@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/interactions@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/storage@^2.0.0". warning " > aws-amplify-react@3.1.6" has unmet peer dependency "@aws-amplify/ui@^2.0.0". [4/4] 🔨 Building fresh packages... success Saved lockfile. success Saved 21 new dependencies. info Direct dependencies ├─ @material-ui/core@4.9.3 └─ @material-ui/icons@4.9.1 info All dependencies ├─ @emotion/hash@0.7.4 ├─ @material-ui/core@4.9.3 ├─ @material-ui/icons@4.9.1 ├─ @material-ui/styles@4.9.0 ├─ @material-ui/system@4.9.3 ├─ @types/react-transition-group@4.2.3 ├─ convert-css-length@2.0.1 ├─ css-vendor@2.0.7 ├─ dom-helpers@5.1.3 ├─ hoist-non-react-statics@3.3.2 ├─ hyphenate-style-name@1.0.3 ├─ is-in-browser@1.1.3 ├─ jss-plugin-camel-case@10.0.4 ├─ jss-plugin-default-unit@10.0.4 ├─ jss-plugin-global@10.0.4 ├─ jss-plugin-nested@10.0.4 ├─ jss-plugin-props-sort@10.0.4 ├─ jss-plugin-rule-value-function@10.0.4 ├─ jss-plugin-vendor-prefixer@10.0.4 ├─ popper.js@1.16.1 └─ react-transition-group@4.3.0 ✨ Done in 5.88s.
index.tsx には以下のように追加します。
に記載されている通り、 Auth
モジュールの signOut()
を呼び出せば良いだけですね。
import React from 'react' import Amplify, { Auth } from 'aws-amplify'; import config from '../aws-exports'; import Button from '@material-ui/core/Button'; import ExitToAppIcon from '@material-ui/icons/ExitToApp'; Amplify.configure(config); class Home extends React.Component { logout() { Auth.signOut() .then(data => console.log(data)) .catch(err => console.log(err)); } render() { return ( <div> <Button onClick={this.logout} variant="contained" color="primary" startIcon={<ExitToAppIcon />} > SIGN OUT </Button> // (以下略)
はい、出来ました。
5. amplify アプリの publish までの道のり
実は未だ、amplify アプリの publish は出来ません。
$ amplify publish Please add hosting to your project before publishing your project Command: amplify hosting add
5.1. amplify hosting add
amplify hosting add
を行うと、以下のように聞かれます。
$ amplify hosting add ? Select the environment setup: (Use arrow keys) ❯ DEV (S3 only with HTTP) PROD (S3 with CloudFront using HTTPS)
とりえず、DEV を選択してCloudFront経由にしないようにして進めます。
$ amplify publish ✔ Successfully pulled backend environment dev from the cloud. Current Environment: dev | Category | Resource name | Operation | Provider plugin | | -------- | -------------------------- | --------- | ----------------- | | Hosting | S3AndCloudFront | Create | awscloudformation | | Auth | nextamplifyexample0dde88af | No Change | awscloudformation | ? Are you sure you want to continue? (Y/n)
何か、CloudFront の文字が見えるような… まぁ、無料枠ならお金かからないから良いや。
$ amplify publish ✔ Successfully pulled backend environment dev from the cloud. Current Environment: dev | Category | Resource name | Operation | Provider plugin | | -------- | -------------------------- | --------- | ----------------- | | Hosting | S3AndCloudFront | Create | awscloudformation | | Auth | nextamplifyexample0dde88af | No Change | awscloudformation | ? Are you sure you want to continue? Yes ⠹ Updating resources in the cloud. This may take a few minutes... UPDATE_COMPLETE authnextamplifyexample0dde88af AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:27 GMT+0900 (日本標準時) UPDATE_IN_PROGRESS authnextamplifyexample0dde88af AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:26 GMT+0900 (日本標準時) CREATE_IN_PROGRESS hostingS3AndCloudFront AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:26 GMT+0900 (日本標準時) Resource creation Initiated CREATE_IN_PROGRESS hostingS3AndCloudFront AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:25 GMT+0900 (日本標準時) UPDATE_IN_PROGRESS amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:22 GMT+0900 (日本標準時) User Initiated ⠇ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS amplify-next-amplify-example-dev-192739-hostingS3AndCloudFront-153OK6UCXJPBA AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:26 GMT+0900 (日本標準時) User Initiated ⠋ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS S3Bucket AWS::S3::Bucket Sat Feb 22 2020 21:46:29 GMT+0900 (日本標準時) ⠋ Updating resources in the cloud. This may take a few minutes... CREATE_IN_PROGRESS S3Bucket AWS::S3::Bucket Sat Feb 22 2020 21:46:30 GMT+0900 (日本標準時) Resource creation Initiated ⠙ Updating resources in the cloud. This may take a few minutes... CREATE_COMPLETE amplify-next-amplify-example-dev-192739-hostingS3AndCloudFront-153OK6UCXJPBA AWS::CloudFormation::Stack Sat Feb 22 2020 21:46:53 GMT+0900 (日本標準時) CREATE_COMPLETE S3Bucket AWS::S3::Bucket Sat Feb 22 2020 21:46:52 GMT+0900 (日本標準時) ⠹ Updating resources in the cloud. This may take a few minutes... UPDATE_COMPLETE_CLEANUP_IN_PROGRESS amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 21:47:02 GMT+0900 (日本標準時) CREATE_COMPLETE hostingS3AndCloudFront AWS::CloudFormation::Stack Sat Feb 22 2020 21:47:00 GMT+0900 (日本標準時) ⠋ Updating resources in the cloud. This may take a few minutes... UPDATE_COMPLETE amplify-next-amplify-example-dev-192739 AWS::CloudFormation::Stack Sat Feb 22 2020 21:47:03 GMT+0900 (日本標準時) UPDATE_COMPLETE authnextamplifyexample0dde88af AWS::CloudFormation::Stack Sat Feb 22 2020 21:47:03 GMT+0900 (日本標準時) ✔ All resources are updated in the cloud Hosting endpoint: http://next-amplify-example-20200222214113-hostingbucket-dev.s3-website-us-west-2.amazonaws.com yarn run v1.22.0 $ next build Creating an optimized production build Compiled with warnings. ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/require.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/require.js Critical dependency: the request of a dependency is an expression Automatically optimizing pages Page Size First Load ┌ ○ / 256 kB 608 kB └ /_app 46.4 kB 315 kB + shared by all 315 kB ├ static/_buildManifest.js 189 B ├ static/pages/_app.js 46.4 kB ├ chunks/242e76a06b3fa367d89c78b62af50ae3b459294c.a43009.js 11.7 kB ├ chunks/29107295.d41bbf.js 24.5 kB ├ chunks/c277677ab6f8ae068064b60157bc6d3cd2fd2c95.ea5b2a.js 173 kB ├ chunks/commons.af9b44.js 13 kB ├ chunks/framework.74d547.js 40.8 kB ├ chunks/styles.15b445.js 87 B ├ runtime/main.e744f1.js 4.74 kB └ runtime/webpack.4b444d.js 746 B λ (Lambda) server-side renders at runtime (uses getInitialProps or getServerProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps) ✨ Done in 15.16s. frontend build command exited with code 0 Cannot find the distribution folder. Distribution folder is currently set as: /Users/ken-yo/next-amplify-example/build Cannot find the distribution folder. Error: Cannot find the distribution folder. at Object.scan (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-hosting/lib/S3AndCloudFront/helpers/file-scanner.js:38:11) at Object.run (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-hosting/lib/S3AndCloudFront/helpers/file-uploader.js:16:32) at Object.publish (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-hosting/lib/S3AndCloudFront/index.js:116:6) at Object.runServiceAction (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-hosting/lib/category-manager.js:63:31) at Object.publish (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-category-hosting/index.js:69:30) at publishToHostingBucket (/usr/local/lib/node_modules/@aws-amplify/cli/node_modules/amplify-frontend-javascript/lib/publisher.js:22:30) at processTicksAndRejections (internal/process/task_queues.js:97:5)
コケて上手く行きません…
build ディレクトリーが無いと言われてますね。
以下のように修正しました。
{ "name": "next-amplify-example", "version": "1.0.0", "private": true, "license": "MIT", "scripts": { "test": "jest --passWithNoTests", "dev": "next", "build": "next build && next export && rm -rf build && mv out build", "start": "next start", "lint": "eslint --ext .ts,.js,.tsx,.jsx src" }, "lint-staged": { "src/*.{ts,js,tsx,jsx}": "eslint" }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "dependencies": { "@material-ui/core": "^4.9.3", "@material-ui/icons": "^4.9.1", "@types/node": "^13.7.4", "@types/react": "^16.9.22", "@zeit/next-css": "^1.0.1", "aws-amplify": "^2.2.5", "aws-amplify-react": "^3.1.6", "next": "^9.2.2", "react": "^16.12.0", "react-dom": "^16.12.0" }, "devDependencies": { "typescript": "^3.8.2" } }
"build": "next build && next export && rm -rf build && mv out build"
がポイントですね。
$ amplify publish ✔ Successfully pulled backend environment dev from the cloud. Current Environment: dev | Category | Resource name | Operation | Provider plugin | | -------- | -------------------------- | --------- | ----------------- | | Auth | nextamplifyexample0dde88af | No Change | awscloudformation | | Hosting | S3AndCloudFront | No Change | awscloudformation | No changes detected yarn run v1.22.0 $ next build && next export && mv out build Creating an optimized production build Compiled with warnings. ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/load-components.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/require.js Critical dependency: the request of a dependency is an expression ./node_modules/next/dist/next-server/server/require.js Critical dependency: the request of a dependency is an expression Automatically optimizing pages Page Size First Load ┌ ○ / 256 kB 608 kB └ /_app 46.4 kB 315 kB + shared by all 315 kB ├ static/_buildManifest.js 189 B ├ static/pages/_app.js 46.4 kB ├ chunks/29107295.6cce3a.js 24.5 kB ├ chunks/5d3dd53bfefaaba7d132131a0ba097ceb6bf38d5.961381.js 11.7 kB ├ chunks/79d124448b8210c46ac0124c1c9c03bef3930399.ea5b2a.js 173 kB ├ chunks/commons.af9b44.js 13 kB ├ chunks/framework.74d547.js 40.8 kB ├ chunks/styles.15b445.js 87 B ├ runtime/main.d64045.js 4.74 kB └ runtime/webpack.4b444d.js 746 B λ (Lambda) server-side renders at runtime (uses getInitialProps or getServerProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps) > using build directory: /Users/ken-yo/next-amplify-example/.next copying "static build" directory > No "exportPathMap" found in "next.config.js". Generating map from "./pages" launching 15 workers Exporting (5/5) Export successful ✨ Done in 11.93s. frontend build command exited with code 0 ✔ Uploaded files successfully. Your app is published successfully. http://next-amplify-example-20200222214113-hostingbucket-dev.s3-website-us-west-2.amazonaws.com
出来ました!
ただ、 GitHub - poad/next-ts-template のブランチを元に作成した場合、next.config.js を次のように修正しないと、
aws-amplify-react
の Global Stylesheet 関連の処理やら styled-jsx やらとの兼ね合いでコケました。(styled-jsx は結果的に使っていないので yarn remove しました)
因みに、 yarn run dev
ではコケずに yarn build
でだけコケるとかあったのでご注意を!
const withCSS = require('@zeit/next-css') if (typeof require !== "undefined") { require.extensions[".less"] = () => { }; require.extensions[".css"] = (file) => { }; } const resolve = require('resolve') global.navigator = () => null const config = { webpack(config, options) { const { dir, isServer } = options config.externals = [] if (isServer) { config.externals.push((context, request, callback) => { resolve(request, { basedir: dir, preserveSymlinks: true }, (err, res) => { if (err) { return callback() } if ( res.match(/node_modules[/\\].*\.css/) && !res.match(/node_modules[/\\]webpack/) && !res.match(/node_modules[/\\]@aws-amplify/) ) { return callback(null, `css ${request}`) } callback() }) }) } return config } } module.exports = withCSS(config)
と、なかなかハマりどころ多いですが、Nuxt.js(Vue.js) + TypeScript + amplify よりは簡単そうです。
next.config.js の修正が不味いケース
その1
$ yarn build yarn run v1.22.0 $ next build Creating an optimized production build Compiled successfully. Automatically optimizing pages ..Service Worker Loaded... > Build error occurred ReferenceError: self is not defined at Object.C+qz (/Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.next/server/static/23FhuuakIG-ehoL-uwoCM/pages/sw.js:108:1) at __webpack_require__ (/Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.next/server/static/23FhuuakIG-ehoL-uwoCM/pages/sw.js:23:31) at Object.3 (/Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.next/server/static/23FhuuakIG-ehoL-uwoCM/pages/sw.js:99:18) at __webpack_require__ (/Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.next/server/static/23FhuuakIG-ehoL-uwoCM/pages/sw.js:23:31) at /Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.next/server/static/23FhuuakIG-ehoL-uwoCM/pages/sw.js:91:18 at Object.<anonymous> (/Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.next/server/static/23FhuuakIG-ehoL-uwoCM/pages/sw.js:94:10) at Module._compile (internal/modules/cjs/loader.js:1151:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1171:10) at Module.load (internal/modules/cjs/loader.js:1000:32) at Function.Module._load (internal/modules/cjs/loader.js:899:14) { type: 'ReferenceError' } error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
とりあえず、next.config.js の中の記述で service worker周りの設定を削って、上述の一番最後に書いた next.config.js へ置き換えてみてください。
その2
$ yarn run dev yarn run v1.22.0 $ next [ wait ] starting the development server ... [ info ] waiting on http://localhost:3000 ... > Using external babel configuration > Location: "/Users/ken-yo/git/es-examples/next-examples/next-amplify-example/.babelrc" [ error ] ./node_modules/@aws-amplify/ui/dist/style.css Global CSS cannot be imported from within node_modules. Read more: https://err.sh/next.js/css-npm Location: node_modules/aws-amplify-react/lib-esm/Amplify-UI/Amplify-UI-Components-React.js
Next.js 公式では非推奨の @zeit/next-css
を追加して…という上述の記事に記載している next.config.js を設定してください。