ロゴ画像

  • HOME
  • Blog
    Allcategories
  • Portfolio
  • Profile
  • Contact

Next.js + Storybook(Vite)環境にCSS in JSライブラリLinariaを導入する

フロントエンド
投稿日:
2023.10.15
最終更新日:
2023.10.15

2023年10月時点における、Next.js + Storybook (Viteビルド設定)環境にゼロランタイムのCSS in JSライブラリlinariaを導入する手順を解説していきます。

環境

  • Mac OS
  • Node.js v18.16.0 (PM: npm)
  • Next.js v13.5.4
  • Storybook v7.4.6
  • vite v4.4.11

背景

パフォーマンス性の高いReact/Next.js環境を構築してアプリ開発を行いたいと思い、ゼロランタイムなCSS in JSライブラリであるlinariaの導入を検討していました。

Linariaを選定した理由は、他のゼロランタイムなCSS in JSライブラリ(panda, vanilla-extract, kuma-ui 等)と比較して、ポピュラーであったためです。

そして、いざLinariaを導入して開発を始めようとしたところ、StorybookをWebpackを使用してビルドしようとしたところ、少々躓いたのでViteビルド設定に変更して環境構築を行いました。

その際に行ったセットアップの手順に関して、議事録を兼ねて記事にしました。

の画像linaria.dev

行ったこと

  1. Next.js(app routerを使用)のインストール
  2. Storybookのインストール
  3. linariaのインストール
  4. stylelintの導入
    1. styled-componentの形式でスタイリングするため。

1. Next.jsのインストール

まずは、最新のNext.jsをインストールします。

(※オプションを使用して一度に全ての設定をすることができますが、今回は対話形式で進めていきます。)

bash
npx create-next-app@latest

下記の設定を行います。(各項目の詳細に関してはこちらの記事が参考になります。)

主なところとしては、言語はTypeScriptを使用し、Next.js v13から導入されたApp Routerを使用しています。

(ESLintやエイリアスの設定に関しては、あまり気にしなくて問題ありません。)

bash
✔ What is your project named? … my-app
✔ Would you like to use TypeScript? Yes
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? No
✔ Would you like to use `src/` directory? Yes
✔ Would you like to use App Router? (recommended) Yes
✔ Would you like to customize the default import alias (@/*)? Yes
✔ What import alias would you like configured? [Enter command]
Creating a new Next.js app in /Users/~~

Using npm.

Initializing project with template: app

Installing dependencies:
- react
- react-dom
- next

Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- eslint
- eslint-config-next

added 279 packages, and audited 280 packages in 26s

106 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Initialized a git repository.

Success! Created my-app at /Users/~~

開発環境を立ち上げて、初期画面が表示されれば問題ありません。

bash
npm run dev

setup-linaria1.png

2. Storybookのインストール

Nextアプリのインストールが完了しましたら、続いてStorybookをViteビルド設定でインストールしていきます。

StorybookデフォルトはWebpackのビルド設定になりますが、以下の観点でViteを使った方が良いと個人的には思っています。

  1. ビルド(起動)が速い
  2. 設定が楽

1に関しては実際に測定してはいないので厳密には分かりませんが、両方使ってみた感じ、Viteの方が速いように感じます。 2に関して、当初Webpackビルド設定を使用していたのですが、babelの設定周りで結構躓いたので諦めました。Viteと比較して設定項目も多く、動かすのに時間がかかりそうでしたので導入を見送っています。

bash
npx sb init --builder=vite

package.jsonのscript部分を一部修正します。

json
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "storybook": "storybook dev -p 6006", // 修正
    "build-storybook": "storybook build" // 修正
  },

さらに追加で以下のライブラリをインストールします。

bash
npm i vite storybook @storybook/react-vite --save-dev

インストールが完了しましたら、先程作られたStorybookの設定ファイル(.storybook/main.ts)を変更していきます。

tsx
// .storybook/main.ts

import type { StorybookConfig } from "@storybook/react-vite";
import path from "path";

const config: StorybookConfig = {
  stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [],
  framework: {
    name: "@storybook/react-vite",
    options: {},
  },
  docs: {
    autodocs: "tag",
  },
  viteFinal: async (config) => {
    // パスエイリアスの設定
    if (config.resolve) {
      config.resolve.alias = {
        ...config.resolve.alias,
        '@': path.resolve(__dirname, '../src'),
        '@public': path.resolve(__dirname, '../public'),
      };
    }

    return config
  },
};
export default config;

上記の設定が完了しましたら、下記コマンドでStorybookを起動しましょう。

エラーがなく、StoryがプレビューされればOKです。

bash
npm run storybook

setup-linaria2.png

3. linariaのインストール

続いて、linariaをインストールしていきましょう。

以下のコマンドで必要なライブラリをインストールします。

(なお、インストール手順に関しては公式のリポジトリをご参照ください。)

bash
npm i @linaria/core @linaria/react @linaria/babel-preset @linaria/vite next-with-linaria

Nextの設定ファイルを変更します。

上記でインストールしたnext-with-linaria を使うことで、Nextアプリにlinariaを簡単に導入できます。

jsx
// next.config.js

/** @type {import('next').NextConfig} */
const withLinaria = require('next-with-linaria');

const nextConfig = {
  // App Directory を有効化
  experimental: {
    appDir: true,
  },
};
module.exports = withLinaria(nextConfig);

次にStorybookに必要な設定を行なっていきます。

その前に、以下のライブラリもインストールしておいてください。

tsx
npm i @babel/preset-typescript @babel/preset-react --save-dev
tsx
// .storybook/main.ts

import path from "path";
import type { StorybookConfig } from "@storybook/react-vite";
import { mergeConfig } from 'vite'
import linaria from '@linaria/vite'

const config: StorybookConfig = {
  stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [],
  framework: {
    name: "@storybook/react-vite",
    options: {},
  },
  docs: {
    autodocs: "tag",
  },
  viteFinal: async (config) => {
    if (config.resolve) {
      config.resolve.alias = {
        ...config.resolve.alias,
        '@': path.resolve(__dirname, '../src'),
        '@public': path.resolve(__dirname, '../public'),
      };
    }

    // Merge custom configuration into the default config
    return mergeConfig(config, {
      plugins: [
        linaria({
          include: ['**/*.{ts,tsx}'],
          babelOptions: {
            presets: ['@babel/preset-typescript', '@babel/preset-react'],
          },
        }),
      ],
    })
  },
};
export default config;

以上でlinaria関連のライブラリのインストールが完了しましたので、linariaでスタイリングされたコンポーネントを実際に表示してみましょう。

次の2つのファイルをsrc/components 以下に作成します。

tsx
// Component/index.tsx

import React from 'react';

import { styles } from './styles';

type Props = {
  children: string;
};

export const Component: React.FC<Props> = ({ children }) => {
  return <p className={styles.text}>{children}</p>;
};
tsx
// styles.ts

import { css } from '@linaria/core';

export const styles = {
  text: css`
    color: black;
    background-color: gold;
  `,
};

これらをページで描画します。

bash
// app/page.tsx

import { Component } from "@/components/Component";

export default function Home() {
  return <Component>Hello World</Component>;
};

そして、これらのStoryを作成していきます。

tsx
// stories/Component/index.stories.tsx

import type { Meta, StoryObj } from "@storybook/react";

import { Component } from "@/components/Component";

const meta = {
  component: Component,
} satisfies Meta<typeof Component>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    children: "Test",
  },
};

実際に開発環境・Storybookを起動して確認してみましょう。

それぞれで表示の確認ができましたら完了です。

bash
npm run dev
bash
npm run storybook
  • ローカル開発環境

setup-linaria3.png

  • Storybook

setup-linaria4.png

4. stylelintの導入

以上で、Next.js + Storybook(Vite)の開発環境構築は完了です。お疲れ様でした!!

ここからは、必須ではありませんが、linariaを効率的に使用するための設定を行なっていきたいと思います。

linariaはstyled-componentと同様にCSSをテンプレートリテラルの中に、インラインで記述していく方式を採用しているので、スタイルを整形してくれるstylelintを導入すると便利です。(linaria公式も推奨しています。)

基本的には公式のドキュメント通り導入していきます。

まずは、必要なライブラリをインストールしていきます。

bash
npm i stylelint @linaria/stylelint-config-standard-linaria --save-dev

(package.jsonのscriptの部分に以下を追加します。)

json
"lint:css": "stylelint src/**/*.js"

インストール後、設定ファイル(.stylelintrc)を作成し以下のように記述していきます。

bash
{
  "extends": [
    "@linaria/stylelint-config-standard-linaria"
  ]
}

最後に、VSCode でファイルを保存(Cmd + S)した時にフォーマットする設定を行なっていきましょう。

(※vscodeの拡張機能をインストールして、stylelintを使用できるようにしましょう。)

json
// .vscode/settings.json

{
  ..
  "editor.codeActionsOnSave": {
    ..
    "source.fixAll.stylelint": true
  },
  "stylelint.validate": ["typescriptreact"]
  ..
}

以上でNext.js + Storybook (Viteビルド設定)環境にゼロランタイムのCSS in JSライブラリlinariaを導入する手順の解説は終わりです。

少し長くなりましたが、少しでも参考になりましたら幸いです。

最後に、今回のソースコードを公開しているので、必要に応じてお使いください。

GitHub - koutaro0205/next-linaria-setupの画像GitHub - koutaro0205/next-linaria-setupContribute to koutaro0205/next-linaria-setup development by creating an account on GitHub.github.com

参考文献

  • Viteビルド設定でStorybookを導入する

React+ViteプロジェクトにStorybook(v7)を導入する | DevelopersIOの画像React+ViteプロジェクトにStorybook(v7)を導入する | DevelopersIO吉川@広島です。 フロントエンドはもっぱらReact+Viteで開発することが多いのですが、以前これにStorybook v6を導入しようとして挫折したことがありました。Viteに対応させたくbuildev.classmethod.jp

  • StorybookにLinariaを導入する

vite + react + storybookにlinariaを導入してみるの画像vite + react + storybookにlinariaを導入してみるzenn.dev

  • Next.js v13にlinariaを導入する

Linaria のセットアップ for Next.js 13 - Qiitaの画像Linaria のセットアップ for Next.js 13 - QiitaMotivationNext.js 13 では新機能として App Directory が追加された。https://beta.nextjs.org/docs/routing/fundament…qiita.com

記事をシェアする
関連記事

サムネイル画像

フロントエンド

【React/TypeScript】react-markdownでマークダウン文字列から目次(TableOfContents)を実装する

2023.07.20

サムネイル画像

フロントエンド

【React/TypeScript】単一画像のアップロード+プレビュー機能を実装する

2023.11.05

サムネイル画像

フロントエンド

【React/TypeScript】単一画像をReact Hook Formを使って送信する

2023.11.05

ロゴ画像

  • HOME
    • ホームへ戻る
  • Blog
  • Profile
  • Portfolio
プライバシーポリシー利用規約お問い合わせ
Copyright © Mates for engineer All Rights Reserved