[Vite] CSSだけをビルドする方法

3 min read

背景

webpack の mini-css-extract-plugin のように CSS ファイルだけを Vite で出力したい。

Vite をインストール

まずは Vite 周辺の環境を構築する。

npm i -D vite postcss postcss-preset-env

npm create vite@latest でも良いが、基本的に Vite しか使わないので個別で入れる。PostCSS は任意。

package.json については以下のような感じになる想定。

// package.json
{
  "name": "vite-build-css",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "build": "vite build"
  },
  "devDependencies": {
    "postcss": "^8.4.19",
    "postcss-preset-env": "^7.8.2",
    "vite": "^3.2.3"
  }
}

仕様

CSS をビルドするときの仕様は以下を想定。

  • CSS ファイルは、srcディレクトリに配置
  • 出力ファイルは、distディレクトリに出力
    • ネスト階層も考慮
    • distsrcのディレクトリ構造を維持する

vite.config.js

// vite.config.js
import fs from "fs";
import path from "path";

import { defineConfig } from "vite";

const TARGET_DIRECTORY = "src";

const readdirRecursively = (dir, files = []) => {
  const dirents = fs.readdirSync(dir, { withFileTypes: true });
  const dirs = [];

  for (const dirent of dirents) {
    if (dirent.isDirectory()) dirs.push(`${dir}/${dirent.name}`);
    if (dirent.isFile()) files.push(`${dir}/${dirent.name}`);
  }

  for (const d of dirs) {
    files = readdirRecursively(d, files);
  }

  return files;
};

const getInputFiles = (extension = ".css") => {
  const fileNames = readdirRecursively(TARGET_DIRECTORY).filter(
    (file) => path.extname(file) === extension
  );
  const inputFiles = {};

  for (let i = 0; i < fileNames.length; i++) {
    const file = fileNames[i].replace(__dirname, "");
    const fileName = file
      .replace(extension, "")
      .replace("..", "")
      .replaceAll("/", "_");

    inputFiles[fileName] = `${file}`;
  }

  return inputFiles;
};

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        assetFileNames: ({ name }) => {
          return name.replace(`${TARGET_DIRECTORY}/`, "");
        },
      },
      input: getInputFiles(),
    },
  },
});

Vite が PostCSS をサポートしているので、PostCSS が必要な場合は入れておく。postcss.config.js を追加しておけばいいので便利。

// postcss.config.js
module.exports = {
  plugin: {
    "postcss-preset-env": {
      stage: 3,
    },
  },
};