💡

静的サイトジェネレーター 11tyeleventyでPostCSSが使いたい

2021/03/13に公開

はじめに

  • 11ty/eleventyzachleat氏によって制作さいれている静的サイトジェネレーター(SSG)
  • デフォルトで以下の言語に対応しています。
    • HTML(.html)
    • Liquid(.liquid)
    • EJS(.ejs)
    • Markdown(.md)
    • Handlebars(.hbs)
    • Mustache(.mustache)
    • Haml(.haml)
    • Pug(.pug)
    • Nunjucks(.njk)
    • JavaScript(.11ty.js)

SSG といえば、Next.jsや、NuxtJSGatsbyなどが有名かとは思いますが、出力されるコードを直接編集して保守、、などの要件には耐えられないため、出力されるコードを細かく制御できる 11ty を触っていこうと思います。
ただ、11ty は HTML の生成に特化しているため、PostCSS を利用するためには、自前で環境を作っていく必要があります。
※今回は最低限の 11ty と PostCSS を連携するためだけの設定を書いていきます。

ファイル&ディレクトリ構成

root/
 ├ dist/  => 出力ディレクトリ
 ├ src/  => 入力ディレクトリ
 │ ├ assets/  => リソースファイル配置ディレクトリ
 │ │ ├ images/  => 画像リソースファイル配置ディレクトリ
 │ │ └ styles/  => スタイルリソースファイル配置ディレクトリ
 │ │   ├ modules/
 │ │   │ ├ _base.pcss
 │ │   │ ├ _header.pcss
 │ │   │ └ _footer.pcss
 │ │   └ style.pcss
 │ ├ components/  => パーツ配置ディレクトリ
 │ │ ├ header.hbs
 │ │ └ footer.hbs
 │ ├ data/  => データ配置ディレクトリ
 │ ├ layouts/  => レイアウト配置ディレクトリ
 │ │ └ default.hbs
 │ └ pages/  => エントリポイント配置ディレクトリ
 │   └ index.hbs
 ├ .bs-config.js => BrowserSync設定ファイル
 ├ .eleventy.js  => eleventy設定ファイル
 ├ .postcssrc.js  => PostCSS設定ファイル(詳細は省略)
 ├ .stylelintrc.js  => stylelint設定ファイル(詳細は省略)
 └ package.json

npm モジュールのインストール

console
# package.jsonの作成
% npm init -y
% npm i -D @11ty/eleventy
# 11tyにも含まれていますが、今回は11tyをただのビルダーとして使いたかったため、別途インストール。
% npm i -D browser-sync
# npm-scriptsでタスクの直列、並列実行するため。
% npm i -D npm-run-all
% npm i -D postcss
# CLIからPostCSSを利用するため。
% npm i -D postcss-cli
# CLIからファイルの削除を行うため。
% npm i -D rimraf
# リンター
% npm i -D stylelint

設定ファイルの作成

.eleventy.js

.eleventy.js
/**
 * Eleventy Configuration
 */
module.exports = (eleventyConfig) => {
  // NOTE:本当は.eleventyignoreで.pcssを除外したいが、11tyのバグのため動作しない。。。
  eleventyConfig.addPassthroughCopy({
    // assets
    "src/assets": "assets",
  });

  return {
    dir: {
      // 入力ディレクトリ
      // input: ".",
      input: "src/pages",
      // インクルードのディレクトリ
      // includes: "_includes",
      includes: "../components",
      // レイアウトのディレクトリ
      // layouts: "_includes",
      layouts: "../layouts",
      // グローバルデータファイルのディレクトリ
      // data: "_data",
      data: "../data",
      // 出力ディレクトリ
      // output: "_site",
      output: "dist",
      // グローバルデータファイルのデフォルトのテンプレートエンジン
      dataTemplateEngine: false,
      // マークダウンファイルのデフォルトのテンプレートエンジン
      markdownTemplateEngine: "liquid",
      // HTMLファイルのデフォルトのテンプレートエンジン
      htmlTemplateEngine: "liquid",
      // テンプレートフォーマット
      templateFormats: [
        // "html",
        // "liquid",
        // "ejs",
        // "md",
        "hbs",
        // "mustache",
        // "haml",
        // "pug",
        // "njk",
        // "11ty.js",
      ],
    },
  };
};

.bs-config.js

.bs-config.js
/**
 * Browser-sync Configuration
 */
module.exports = {
  ui: false,
  files: [
    "dist/**/*.css",
  ],
  server: "dist",
  ghostMode: false,
  open: false,
  notify: false,
};

package.json

package.json(scripts部分のみ)
{
  "scripts": {
    // リリース用ビルド
    "build": "run-s clean build::*",
    // リリース用htmlビルド
    "build::html": "eleventy",
    // リリース用cssビルド
    "build::css": "postcss \"./src/assets/**/!(_)*.pcss\" --base \"src/assets\" --dir \"dist/assets\" --ext css --no-map",
    // distディレクトリの削除
    "clean": "rimraf dist",
    "format": "run-s format::css",
    "format::css": "stylelint \"src/assets/**/*.pcss\" --fix",
    // リンター実行
    "lint": "run-s lint::css",
    // CSSリンター実行
    "lint::css": "stylelint \"src/assets/**/*.pcss\"",
    // 開発サーバ起動
    "server": "browser-sync start --config \"./.bs-config.js\"",
    // 開発サーバ起動
    "start": "run-p watch server",
    // 監視
    "watch": "run-p watch::*",
    // HTML監視
    "watch::html": "eleventy --watch",
    // CSS監視
    "watch::css": "postcss \"./src/assets/**/!(_)*.pcss\" --base \"src/assets\" --dir \"dist/assets\" --ext css --watch"
  },
}

使い方

console
# 開発サーバ起動
% npm run start
# リンター実行
% npm run lint
# リンターによる修正の実行
% npm run format
# リリース用ビルド
% npm run build

最後に

  • バグが直ったら.eleventyignore を追加予定です。
  • eleventyConfig.addExtensionを利用するか悩みましたが、それをやるのであれば、gulp などでいいんじゃないかと思い、今回は、npm scripts を使って別々で処理するようにしました。
GitHubで編集を提案
株式会社ナンバーフォー

Discussion