ウェブ関連

Vue3 + Typescript + SCSS + Storybook 設定備忘録

新しい環境を構築する時に必ず忘れて調べ直すので、手順を記録しながら作業してみる。

インストール

Node.jsは公式からダウンロードしてインストール

VueはVueCLIを使用するので公式参照

プロジェクト作成

vue create shop

RouterとかSCSSとか使いたいので手動(Manually)で設定していく。

Vue CLI v5.0.6
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, TS, Router, CSS 
Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected 
polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback 
in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported 
by default): Sass/SCSS (with dart-sass)
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated 
config files
? Save this as a preset for future projects? Yes
? Save preset as: 20220705set

手動選択後、必要な物を聞かれるので、TypeScript,Router,CSS Pre-processorsを追加で選択。
Vueのバージョンは3.xを選択。
あとはデフォルトでポチポチ。
最後2行は、この設定をプリセットにするかって質問。今回はYesを選択。

Vueのバージョンを最新に

念の為、VueCLIの公式通りにプロジェクトディレクトリ に移動して下記を実行

vue upgrade --next

確認

正常に作成されたか起動確認

npm run serve

ポート番号を変更して確認したい場合は下記で。

npm run serve -- --port 8081

Storybookを追加する

なにはともあれ公式を見るのが一番手取り早い

npx storybook init

完了するとプロジェクトディレクトリ内に「.storybook」「src/stories」ってのが追加される。

インストール後の指示に従って下記を実行。

npm run storybook

ブラウザが自動で起動する。しなければ http://localhost:6006/ にアクセスする。
ターミナル上で「99%〜」で止まるのが気になるけど動く。

セキュリティソフトのお陰でアクセス出来なくて、別の事を試しまくってハマる。

StorybookでSCSSとTypescriptを使用するので下記を実行
※色々試しながら進めた結果、本当に必要かどうか分からなくなっているが恐らく必要

npm install @storybook/preset-typescript
npm install @storybook/preset-scss
npm install style-loader css-loader sass-loader

気になる脆弱性

Storybookをインストール後、「21 high severity vulnerabilities」と出る。
画面の指示に従ってnpm audit fixを実行しても減らない。

「–force」したら逆に1個増える始末

これはとりあえず置いておく。
どうにか出来る気がしないのと、npm auditは不正確って情報を見たから。

SCSSを読み込む

srcディレクトリ内にassets、assets内にcssディレクトリ を作成してscssファイルを作成。(src/assets/css/common.scssなど)

Vue側

vue.config.jsに下記のように追記

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  // ここから
  css: {
    loaderOptions: {
      scss: {
        additionalData:
        `@use "@/assets/css/variables.scss" as var;
         @use "@/assets/css/mixins.scss" as mx;
         @use "@/assets/css/common.scss";`
      },
    }
  }
  // ここまで
})

Storybook側

.storybook/main.jsに追記

const path = require('path');         // 追加

module.exports = {
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
    "@storybook/preset-scss",         // 追加
  ],
  "framework": "@storybook/vue3",
  "core": {
    "builder": "@storybook/builder-webpack5"
  },
// ここから下記
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: "sass-loader",
          options: {
            additionalData: `
              @use "./src/assets/css/variables.scss" as var;
              @use "./src/assets/css/mixins.scss" as mx;
              @use "./src/assets/css/common.scss";
            `,
            implementation: require('sass'),
          },
        },
      ],
      include: path.resolve(__dirname, '../'),
    });

    // Return the altered config
    return config;
  },
// ここまで追加
}

SCSSの記述

コンポーネントの.vueに直接書く時

<style lang="scss" scoped>
.button {
  background: var.$color-primary;
  font-weight: var.$font-bold;
  @include mx.shadow();
}
</style>

lang="scss"は必須。scopedは無くても大丈夫だろうけど、コンポーネント内で完結させる場合必要。
var.mx.は名前空間(namespace)、@useで読み込んでいるので必要。
従来の@importで読み込めば名前空間は不要だけど@useに慣れるため。
@use "./src/assets/css/variables.scss" as var; as 以降が名前空間(namespace)

common.scssに書く時

@use './variables' as var;
@use './mixins' as mx;
html{
  font-size: calc(100vw / 375 * 16);
  @include mx.mq(md){
    font-size: calc(100vw / 1200 * 16);
  }
  @include mx.mq(xl){
    font-size: 16px;
  }
}
body{
  color: var.$color-blue;
  background-color: #fff;
  font-size: 1rem;
}

variablesやmixinsの変数やらを使用する際は、@useが必要。
最初のscssの読み込みだけでいいんじゃないかと試したがダメだった。(@importでなら大丈夫だと思う)

コンポーネントはパーツごとに細かく作る予定なのでcommon.scssはページ全体のみのCSSになる予定。
App.vueに全体のcssを書けば良い気もするが……

VSCodeの拡張機能「CSScomb」で整形出来ない

横道に逸れるけど、VSCodeの拡張機能「CSScomb」で上記のscssが整形出来ない。
mx.var.があると出来ない模様。
検索したけど解決にいたらなかったいたらなかった。

CSScombの公式(?)で試した所、問題なかったので拡張機能側なんだろう。
https://csscomb.herokuapp.com/online

リセットCSSを読み込む

publicディレクトリ内にassets、assets内にcssディレクトリ を作成してreset.cssを追加。(public/assets/css/reset.css)
リセットはThe new CSS resetを初使用。
いままでress.cssとか使ってたけど検索すると、色々新しいの出てたので。

Vue側

src/main.tsを編集

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import '../public/assets/css/reset.css'; // 追加
createApp(App).use(router).mount('#app')

Storybook側

.storybook内にpreview-head.htmlを下記内容で作成。

<link rel="stylesheet" href="assets/css/reset.css">

storybookの起動時にpublicを指定する必要があるので、package.jsonの該当部分を変更。
start-storybook -p 6006 -s ./public -sオプションを追加する

︙
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "storybook": "start-storybook -p 6006 -s ./public",
    "build-storybook": "build-storybook"
  },
︙

Storybookを使う

とりあえず記事内での最終的なディレクトリ・ファイル構成

/shop(プロジェクトディレクトリ)
  ├ .storybook
  │   ├ main.js
  │   ├ preview.js
  │   └ preview-head.html(新規作成)
  │
  ├ public
  │   └ assets
  │       └ css
  │           └ reset.css(新規追加)
  │
  └ src/
      ├ assets
      │   └ css
      │       ├ common.scss(新規作成)
      │       ├ variables.scss(新規作成)
      │       └ mixins.scss(新規作成)
      │
      ├ components
      │   ├ 1_atoms
      │   │   ├ Button.stories.js(新規作成)
      │   │   └ Button.vue(新規作成)
      │   │
      │   ├ 2_Molecules
      │   ├ 3_Organisms
      │   └ 4_Templates
      │
      └ stories(自動で追加される。使用しない)

コンポーネント設計にはアトミックデザインを採用。
アトミックデザイン自体初めてやる事なので探り探りです。
とりあえず、componentsにatomsからtemplatesまでの4つを入れて、pagesに該当する部分はviewsにしようとしてます。
viewsはプロジェクト作成時にRouter使用を選択してると作成される。

Button.stories.jsとButton.vueを作成。
Button.stories.jsとButton.vueの中身は下記参照
https://storybook.js.org/docs/vue/writing-stories/introduction

Typescriptでのサンプルがあるので、Button.stories.jsを.tsで作成しようとしたが、.vueのテンプレートのhtmlタグにクラス(class=””)を入れると下記エラーが出る

型 '{ style: {}; class: string; }' を型 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>' に割り当てることはできません。
  プロパティ 'class' は型 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>' に存在していません。'className' ですか?

ググって、@types/reactが関係しているっぽいって所で、いまいちどうすればいいか分からなかったので断念してstoriesの作成はjsでやることにした。

Storybookにコンポーネントを反映させる

現状のままだと、デフォルトのEXAMPLEが表示されるだけなので、components内のファイルを反映させる。

.storybook/main.jsを編集

  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)",
    // 以下追記(上2行は不要なら削除)
    "../src/components/**/*.stories.mdx",
    "../src/components/**/*.stories.@(js|jsx|ts|tsx)",
  ],

src/assets内の画像が参照できない

画像表示しようと思ってsrc="src/assets/logo.png"とかしても表示されない。
vueでも通らないから、当然といえば当然のような気がする。vueならsrc="@/assets/logo.png"は通るか。
publicに置けば参照出来る。src="/assets/img/test.jpg"みたいに。
ただまぁ、srcに置くメリットもあるし、vueでは大丈夫だけどstorybookだと駄目って状態が気になるので調べた。

SCSSを読み込む時に追記した部分に下記を追加する。
.storybook/main.js

  webpackFinal: async (config, { configType }) => {
// ここから
    config.resolve.alias = {
      ...config.resolve.alias,
      "@": path.resolve(__dirname, '../src')
    },
// ここまで
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: "sass-loader",
          options: {
            additionalData: `
              @use "./src/assets/css/variables.scss" as var;
              @use "./src/assets/css/mixins.scss" as mx;
              @use "./src/assets/css/common.scss";
            `,
            implementation: require('sass'),
          },
        },
      ],
      include: path.resolve(__dirname, '../'),
    });

    // Return the altered config
    return config;
  },

Vue Routerを反映させる

最初のプロジェクト作成で、Vue Routerを選択したので、Storybookでも反映するようにする。

Addonをインストール
https://storybook.js.org/addons/storybook-vue3-router

npm install --save-dev storybook-vue3-router

**.stories.jsに下記を追加

// NaviGlobal.stories.js
import NaviGlobal from './NaviGlobal.vue';
import vueRouter from 'storybook-vue3-router'; // 追加

export default {
  title: 'Atoms/NaviGlobal',
  component: NaviGlobal,
};

const Template = (args) => ({
  components: { NaviGlobal },
  setup() {
    return { args };
  },
  template: '<NaviGlobal v-bind="args" />',
});

export const Primary = Template.bind({});
Primary.args = { NaviCond:{opacity: 0} };

/* 下記追加 */
Primary.decorators = [
  vueRouter()
]

Vue初心者がFirestoreデータ取得までの備忘録前のページ

Perlでlower_bound次のページコーディング

関連記事

  1. ウェブ関連

    Vue初心者がFirestoreデータ取得までの備忘録

    Vue CliでFirestoreからデータ取得してくるまでに嵌りに…

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

  1. ウェブ関連

    Vue3 + Typescript + SCSS + Storybook 設定備…
  2. ウェブ関連

    Vue初心者がFirestoreデータ取得までの備忘録
  3. コーディング

    競プロ

    Perlでlower_bound
  4. コーディング

    コーディング

    テキストエディタ変遷
PAGE TOP
%d人のブロガーが「いいね」をつけました。