4
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

ShopifyアプリをTypescriptで開発する方法

はじめに

Shopifyアプリとは、Shopifyストアに機能を追加するWebアプリケーションです。
下記URLのチュートリアルでは、Node.js、React、GraphQLを使用して埋め込みShopifyアプリを構築するプロセスについて説明されておりますが、Typescriptで開発したいと思い、実装する方法を調べて実現できたのでご紹介したいと思います。

開発環境

下記環境で確認しています。

  • Mac
  • VSCode
  • node.js
  • Shopify App CLI

プロジェクト作成

Shopify App CLIでベースのnodeのプロジェクトを作成します。

  • PublicかCustomを選択します。
% shopify create node --name=starter-embedded-app
? What type of app are you building? (Choose with ↑ ↓ ⏎, filter with 'f')
> 1. Public: An app built for a wide merchant audience.
  2. Custom: An app custom built for a single client.
  • 次にどの開発ストア向けで作成するか選択します。
% shopify create node --name=starter-embedded-app
? What type of app are you building? (You chose: Public: An app built for a wide merchant audience.)
Organization [Shopify Partnerアカウントのビジネス名] 
? Select a Development Store (Choose with ↑ ↓ ⏎, filter with 'f')                                                                                                                                           
  1. xn-xxxxx1.myshopify.com
> 2. xn-xxxxx2.myshopify.com
  • プロジェクトが生成されます。
% shopify create node --name=starter-embedded-app
? What type of app are you building? (You chose: Public: An app built for a wide merchant audience.)
Organization [Shopify Partnerアカウントのビジネス名]                                                                                                                                                                      
? Select a Development Store (You chose: xn-xxxxx2.myshopify.com)
✓ node v14.3.0                                                                                                                                                                                              
✓ npm 6.14.4                                                                                                                                                                                                
┏━━ Cloning into starter-embedded-app... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ Cloning into 'starter-embedded-app'...
┃ remote: Enumerating objects: 3, done.        
remote: Counting objects: 100% (3/3), done.        
remote: Compressing objects: 100% (3/3), done.        
remote: Total 1071 (delta 0), reused 0 (delta 0), pack-reused 1068        
Receiving objects: 100% (1071/1071), 1.83 MiB | 1.97 MiB/s, done.
Resolving deltas: 100% (720/720), done.
┃                                                                                                                                                                                                       100%
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (3.11s) ━━
✓ Cloned into starter-embedded-app
┏━━ Installing dependencies with npm... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ ✓ 37 npm dependencies installed
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (53.38s) ━━
✓ Dependencies installed
✓ .env saved to project root
✓ starter-embedded-app was created in your Partner Dashboard https://partners.shopify.com/xxxxx/apps/xxxxx
⭑ Run shopify serve to start a local server
⭑ Then, visit https://partners.shopify.com/xxxxx/apps/xxxxx/test to install starter-embedded-app on your Dev Store
  • アプリを起動し、アプリをストアにインストールして動作を確認します。

Typescript開発セットアップ

Typescript開発で必要なパッケージをインストールします。
※ 先にncuで既存パッケージの最新化もします。
※ typescriptに関しては、最新の3.9.3ではエラーがでてたのでバージョンを3.8.3に指定してインストールしています。

% ncu -u
% npm install
% npm install --save-dev typescript@3.8.3 ts-node @types/node @types/react @types/react-dom @types/koa @types/koa-session @types/koa-router @types/js-cookie

tsconfig.json, tsconfig.server.json, next-env.d.ts, nodemon.json ファイルを作成します。

tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "jsx": "preserve",
    "lib": ["dom", "es2017"],
    "baseUrl": ".",
    "moduleResolution": "node",
    "strict": true,
    "allowJs": true,
    "noEmit": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "isolatedModules": true,
    "removeComments": false,
    "preserveConstEnums": true,
    "sourceMap": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "exclude": ["dist", ".next", "out", "next.config.js"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}
tsconfig.server.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "dist",
    "target": "es2017",
    "isolatedModules": false,
    "noEmit": false
  },
  "include": ["server/**/*.ts"]
}
nodemon.json
{
  "watch": ["server"],
  "exec": "ts-node --project tsconfig.server.json server/server.ts",
  "ext": "js ts"
}
next-env.d.ts
/// <reference types="next" />
/// <reference types="next/types/global" />

package.jsonを下記の通り編集します。

package.json
〜省略〜
  "scripts": {
    "test": "jest",
    "dev": "NODE_ENV=development nodemon",
    "build": "next build && tsc --project tsconfig.server.json && cp server/index.js dist/",
    "start": "NODE_ENV=production node dist/index.js"
  },
〜省略〜

JSファイルをTS/TSXファイルに変更する

JSファイルをTS/TSXファイルに変更して、エラー箇所を修正していきます。

  • pages/index.js は pages/index.tsx にリネームのみ
  • pages/_app.js は pages/_app.tsx にリネームし、下記の通り編集します。
pages/_app.tsx
省略
import translations from "@shopify/polaris/locales/en.json";

declare var API_KEY: string; // 追加

const client = new ApolloClient({
省略
    const { Component, pageProps } = this.props;
    const shopOrigin = Cookies.get("shopOrigin") ?? "error"; // 変更
    return (
省略
  • server/server.js は server/server.ts にリネームし、下記の通り編集します。
server/server.ts
省略
import session from "koa-session";
// import * as handlers from "./handlers/index"; コメントアウト
dotenv.config();
const port = parseInt(process.env.PORT || '8081', 10); // 変更
const dev = process.env.NODE_ENV !== "production";
省略
const handle = app.getRequestHandler();
const SHOPIFY_API_SECRET = process.env.SHOPIFY_API_SECRET ?? "error"; // 変更
const SHOPIFY_API_KEY = process.env.SHOPIFY_API_KEY ?? "error"; // 変更
const SCOPES = process.env.SCOPES ?? "error"; // 変更
app.prepare().then(() => {
省略
      async afterAuth(ctx) {
        //Auth token and shop available in session
        //Redirect to shop upon auth
        const shop = ctx.session?.shop; // 変更
        ctx.cookies.set("shopOrigin", shop, {
          httpOnly: false,
          secure: true,
          sameSite: "none"
        });
        ctx.redirect("/");
      }
省略

上記の必要最低限の修正のみで初期プロジェクトは動作するようになると思います。
エラーを回避する修正しかしていないので、適宜修正してください。

まとめ

ここまで変更を加えたときのフォルダ構成は下記の通りになります。

starter-embedded-app
├── .dependabot
│   └── config.yml
├── .editorconfig
├── .env
├── .env.example
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .npmrc
├── .prettierignore
├── .shopify-cli.yml
├── .stylelintignore
├── .stylelintrc.js
├── .travis.yml
├── LICENSE.md
├── README.md
├── next-env.d.ts
├── next.config.js
├── nodemon.json
├── package-lock.json
├── package.json
├── pages
│   ├── _app.tsx
│   └── index.tsx
├── server
│   ├── handlers
│   │   ├── client.js
│   │   ├── index.js
│   │   ├── mutations
│   │   │   ├── get-one-time-url.js
│   │   │   └── get-subscription-url.js
│   │   └── register-webhooks.js
│   ├── index.js
│   └── server.ts
├── tsconfig.json
└── tsconfig.server.json

あとは、チュートリアルに沿って機能を追加していけば、Typescriptでも開発できることが確認できると思います。

本記事のリポジトリは下記においてますので何かの参考になれば幸いです。
https://github.com/winuim/starter-embedded-app

参考サイト

Shopify App CLI でアプリを開発する
TypeScript Next.js example
Custom server with TypeScript + Nodemon example

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
4
Help us understand the problem. What are the problem?