ウェブ関連

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. コーディング

    javascriptを使用しないでページを作ってみる
  2. ウェブ関連

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

    コーディング

    WordPress Coding Standardsをcomposerでインスト…
  4. 雑記

    固定IPアドレスに興味を持つ
  5. コーディング

    コーディング

    テキストエディタ変遷
PAGE TOP