LoginSignup
3
4

[初心者向け]はじめてのNext.js - Figma×Locofyでソースコードを生成して自分のプロジェクトに適用する

Last updated at Posted at 2024-01-08

こんにちは。Kaneyasuです。
先日からNext.jsとVercelを始めました。
前回までの分はこちら。

今回はFigmaからソースコードを生成してみます。
Figmaからコードを出力するにはプラグインの力が必要で、今回はLocofyを使用してみました。
手順を自分のような初心者の方向けに書き残しておくのでよろしければご覧ください。

Figmaへのサインアップ

Figmaにサインアップします。
PlanはFreeでやってみます。

Figma Learn - Figmaアカウントの作成

私の場合ログインすると、DraftsにFigma basicsというファイルがあるのでこれを使用します。

FigmaのDrafts

Dev Modeへの切り替え

ファイルを開くと、右上にDev Modeへ切り替えるスイッチがあるのでこれをクリックします。



Locofyプラグインのインストール

Figmaからコードを出力するにはプラグインの力が必要です。
デフォルトで、AnimaとFigma to Codeというプラグインが入っていますが、Animaは本来有料でフリープランだとすぐ上限になり、Figma to Codeは若干機能が弱そうなので、今回はLocofyというものを使ってみます。

Dev Modeに切り替えた後、Pluginsタブをクリックします。

検索ボックスにLocofy.aiと入力して検索。

クリックすると詳細情報が表示されるのでRunをクリック。

アカウントの接続を求められるので、Connect Accountをクリック。

別タブで、Locofyのサイトが開きます。
Googleアカウントなどでサインアップします。
私はFigmaもLocofyもGoogleアカウントでサインアップしました。
おそらく、サインアップする方法は合わせた方がよいと思います。

image.png

サインアップ後、Figmaに戻ってプラグインでLocofyを開くと、コード変換の設定などが表示されるようになります。

LocofyでNext.jsのコードを出力する

プラグインにLocofyをインストール後、ファイルを開いて何らかのページを選択してPluginsのLocofyを開くと、コード変換の設定などが表示されます。

何らかのページを選択してLocofyを開く

上部にフレームワークとスタイルの出力方法を選択する欄があるので、Next.jsを選択。
スタイルは今回はTailwindを使用してるのでそれを選択。

画面下部にダウンロードボタンがあるのでクリックすると、Zip圧縮されたファイル一式がダウンロードされます。
(ヘルプのアイコン邪魔ですね・・・)

ダウンロードしたファイルを解凍すると以下の構成のファイル群ができます。

./
├── README.md
├── next-env.d.ts
├── next.config.js
├── package.json
├── pages
│   ├── _app.tsx
│   ├── global.css
│   └── index.tsx
├── postcss.config.js
├── public
│   ├── jonathankemper1hhrdiolfpuunsplash-1@2x.png
│   └── stocksy-txp226f62b2ane300-medium-4582193-1@2x.png
├── tailwind.config.js
├── tsconfig.json
├── typings.d.ts
└── vercel.svg

既存のNext.jsプロジェクトへのマージ

出力したコードを既存のNext.jsプロジェクトへマージしてみます。
npx create-next-appで出力したものと差を比較しながら適用します。

いろいろ試したところ、出力されたファイル一式のうち、○がついてるもの以外はマージする必要はないと思いました。

Locofyが出力してくれたファイル一式(○がついてるもの以外は不要)
./
├── README.md
├── next-env.d.ts
├── next.config.js
├── package.json <<< ○
├── pages
│   ├── _app.tsx <<< ○
│   ├── global.css <<< ○
│   └── index.tsx <<< ○
├── postcss.config.js
├── public
│   ├── jonathankemper1hhrdiolfpuunsplash-1@2x.png <<< ○
│   └── stocksy-txp226f62b2ane300-medium-4582193-1@2x.png <<< ○
├── tailwind.config.js <<< ○
├── tsconfig.json
├── typings.d.ts
└── vercel.svg

package.jsonにライブラリを追加

autoprefixerが追加されていたので、マージではなく追加でnpm install autoprefixer --save-devしました。

画像とページのコードを自分のプロジェクトに組み込む

画像とページのコードを自分のプロジェクトに配置

Locofyが出力した画像をpublicに配置。
次にコードですが、Locofyが出力したコード群にはpagesがありますが、私のプロジェクトにはpagesがないので、src/app配下にディレクトリを作って、そこに配置します。

自分のNext.jsプロジェクト
./
├── public
│   ├── jonathankemper1hhrdiolfpuunsplash-1@2x.png <<< Locofyが出力した画像
│   ├── shiba.png
│   └── stocksy-txp226f62b2ane300-medium-4582193-1@2x.png <<< Locofyが出力した画像
├── src
│   └── app
│       ├── dogs
│       │   └── page.tsx
│       ├── homepage <<< ディレクトリを新規作成、Locofyが出力したコード群のpages一式を移動
│       │   ├── _app.tsx
│       │   ├── global.css
│       │   └── index.tsx
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx
│       └── page.tsx
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── README.md
├── tailwind.config.ts
└── tsconfig.json

ここの違いは、私のプロジェクトがNext.js 13だからですね。
Next.js 13からは、ルートディレクトリはappに変更されています。

どうやら、Locofyが出力するコードは、Next.js 13より前のコードのようです。
Locofyが出力したpackage.jsonには、"next": "^13.2.4",とあるので、古いというより、13より前のNext.jsでも動くようにあえて古いスタイルで出力しているように思えます。

index.tsxをpage.tsxにリネーム

Next.js 13からはインデックスファイルは、index.tsxからpage.tsxに変わっているのでリネーム。

自分のNext.jsプロジェクト
./
├── public
│   ├── jonathankemper1hhrdiolfpuunsplash-1@2x.png 
│   ├── shiba.png
│   └── stocksy-txp226f62b2ane300-medium-4582193-1@2x.png
├── src
│   └── app
│       ├── dogs
│       │   └── page.tsx
│       ├── homepage
│       │   ├── _app.tsx
│       │   ├── global.css
│       │   └── page.tsx <<< リネーム
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx
│       └── page.tsx
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── README.md
├── tailwind.config.ts
└── tsconfig.json

_app.tsxをlayout.tsxに変更

Next.js 13からはレイアウトは、_app.tsxからlayout.tsxで定義するように変わっているのでこれも変更。
しかし、中身を比較してみたら構造が違います。

自分のNext.jsプロジェクト
./
├── public
│   ├── jonathankemper1hhrdiolfpuunsplash-1@2x.png 
│   ├── shiba.png
│   └── stocksy-txp226f62b2ane300-medium-4582193-1@2x.png
├── src
│   └── app
│       ├── dogs
│       │   └── page.tsx
│       ├── homepage
│       │   ├── _app.tsx <<< このファイルと(A)を比較
│       │   ├── global.css
│       │   └── page.tsx
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx <<< (A)
│       └── page.tsx
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── README.md
├── tailwind.config.ts
└── tsconfig.json
./src/app/homepage/_app.tsx
import { Fragment } from "react";
import Head from "next/head";
import type { AppProps } from "next/app";
import "./global.css";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Fragment>
      <Head>
        <title>locofy-react-nextjs-project</title>
        <meta
          name="viewport"
          content="minimum-scale=1, initial-scale=1, width=device-width"
        />
      </Head>
      <Component {...pageProps} />
    </Fragment>
  );
}

export default MyApp;
./src/app/layout.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "kaneyasu", // ここの文字列がブラウザのタブに表示される
  description: "Generated by kaneyasu", // こちらはメタタグに表示される文字列
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}

単にリネームしただけでは動作しなかったので、(A)をベースに新たにlayout.tsxを作成

./src/app/homepage/layout.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./global.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "locofy-react-nextjs-projec", // ここの文字列がブラウザのタブに表示される
  description: "locofy-react-nextjs-projec", // こちらはメタタグに表示される文字列
};

export default function HomepageLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  );
}
自分のNext.jsプロジェクト
./
├── public
│   ├── jonathankemper1hhrdiolfpuunsplash-1@2x.png 
│   ├── shiba.png
│   └── stocksy-txp226f62b2ane300-medium-4582193-1@2x.png
├── src
│   └── app
│       ├── dogs
│       │   └── page.tsx
│       ├── homepage
│       │   ├── layout.tsx <<< (A)をベースに作成
│       │   ├── global.css
│       │   └── page.tsx
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx <<< (A)
│       └── page.tsx
├── next-env.d.ts
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── README.md
├── tailwind.config.ts
└── tsconfig.json

tailwind.config.tsをマージ

私のプロジェクトのtailwind.config.tsと、Locofyが出力したtailwind.config.jsを比較します。

自分のプロジェクトのtailwind.config.ts
import type { Config } from "tailwindcss";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      backgroundImage: {
        "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
        "gradient-conic":
          "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
      },
    },
  },
  plugins: [],
};
export default config;
Locofyが出力したtailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        white: "#fff",
        darkolivegreen: "#426b1f",
        black: "#000",
      },
      spacing: {},
      fontFamily: {
        inter: "Inter",
        newsreader: "Newsreader",
      },
    },
    fontSize: {
      base: "16px",
      sm: "14px",
      xl: "20px",
      inherit: "inherit",
    },
  },
  corePlugins: {
    preflight: false,
  },
};

TypeScriptと JavaScriptの違いはありますが、JavaScriptのオブジェクトリテラル形式なのでマージができました。
contentのパスは、Locofyの方だとディレクトリ構造と合わないので、私のプロジェクトの方を正にしました。
themeと、corePluginsはLocofyの方を正にしました。

マージしたtailwind.config.ts
import type { Config } from "tailwindcss";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      colors: {
        white: "#fff",
        darkolivegreen: "#426b1f",
        black: "#000",
      },
      spacing: {},
      fontFamily: {
        inter: "Inter",
        newsreader: "Newsreader",
      },
    },
    fontSize: {
      base: "16px",
      sm: "14px",
      xl: "20px",
      inherit: "inherit",
    },
  },
  plugins: [],
  corePlugins: {
    preflight: false,
  },
};
export default config;

動作確認

マージが済んだら動作確認してみます。

動作確認結果

画像の表示だけ違和感を感じますね。
上述のファイル以外にもいろいろ調整してみましたが結果変わらずなので、これが限界なのかなと思います。
それでもゼロから作るよりは大分楽なので有用であることは感じられました。

有料プラグインのAnimaだとまた違う結果が得られるのかもしれません。
機会があったら試してみます。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4