はじめに

Eleventy は、日々メンテナンスされ、更新が行われています。v1に始まり、v2, v3とバージョンの更新が行われてきました。

Eleventy v3 では、従来の Node.js のモジュールシステム require(CommonJS)に加え、import / export(ESM)にも、対応するようになりました。

この記事では、Eleventy v3 への対応として、require(CommonJS)を import / export(ESM)に、切り替える方法についてまとめています。


package.json の変更

まず、最初に修正が必要なのは、package.json ファイルになります。

基本的に、 Eleventy v3 でも、従来の require(CommonJS)も使用可能ですが、 Node.js の公式方針がimport / export(ESM)へ移行しているため、今後は ESM が主流になると考えられます。

現状、Eleventy v3 の挙動は Node.js の "type" 設定に従います。そのため、"type" を書かない場合は Node.js のデフォルトである CommonJS として扱われます。

Eleventy v3 の仕様は次の通りです。

package.jsonの設定 モジュールタイプ require/module.exports import/export
"type": "commonjs" CommonJS ⭕ 動く ❌ 基本使えない
"type": "module" ESM ❌ 動かない ⭕ 動く
"type" を書かない CommonJS ⭕ 動く ❌ 基本使えない

👉 Eleventy v3 は ESM を強制しておらず、Node.js の設定に従います。

もし、package.json に下記の定義があると、

"type": "commonjs"

これは Node.js に対して:「このプロジェクトの .js は CommonJS として扱ってください」という意味になります。

その為、 ESM を使いたい場合は、意図的に package.json に、下記の定義を加えるか、従来の定義を変更する必要があります。

"type": "module"

👉 これで、このプロジェクトの .js が ESM として扱われるようになります。


Eleventyの定義の変更

Eleventy が起動された時に読み込まれる .eleventy.js ファイルですが、これは、純粋な JavaScript ファイルなので、当然、モジュールタイプの影響を受けます。

ファイルに記述されている

  • require(CommonJS)を import(ESM) に変更
  • module.exports =(CommonJS)を export(ESM)に変更

する必要があります。

例: .eleventy.js

const { DateTime } = require("luxon");
const slugify = require("slugify");
const fs = require("fs");
const syntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const markdownIt = require("markdown-it");
const markdownItAttrs = require("markdown-it-attrs");
const categoryDefine = require("./src/_data/categoryDefine.js");

module.exports = function (eleventyConfig) {
          :

CommonJS から ESM へ変更 👇

import { DateTime } from "luxon";
import slugify from "slugify";
import fs from "fs";
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import markdownIt from "markdown-it";
import markdownItAttrs from "markdown-it-attrs";
import categoryDefine from "./src/_data/categoryDefine.js";

export default function (eleventyConfig) {
          :

👉 これで、Eleventy の定義ファイルが正しく動作するようになります。

注意点

Node.js の ESM では、「npm パッケージの import には .js を付けなくてよい」ですが、「相対パスの import には .js が必須」です。

また、import で読み込まれるモジュールは、ESM 対応され、該当のエントリーが、 export されている必要があります。

外部モジュールを読み込んでいる場合は、該当モジュールが ESM 対応されているかどうかを事前に確認の上、行ってください。

ESM 対応されていないモジュールがある場合は、ESM 対応されている他のモジュールに切り替えるか、従来通り、CommonJS での対応を続ける必要があります。


_data 配下のスクリプトの変更

ソースディレクトリの _data 配下に、データファイルとして、 .js ファイルを用意している場合は、これらも CommonJS から ESM に変更する必要があります。

Eleventy は _data/*.js を Node.js と同じモジュール方式で読み込みます。そのため、プロジェクトが ESM の場合は _data/*.js も ESM にする必要があるのです。

  • module.exports =(CommonJS)を export(ESM)に変更

例: _data/tagDefine.js

module.exports = {
  "はじめて": {
    yomi: "hajimete"
  },
          :

CommonJS から ESM へ変更 👇

export default {
  "はじめて": {
    yomi: "hajimete"
  },
          :

👉 これで、データファイルとして、正しく読み込まれます。


その他の JavaScript ファイル

上記以外の .js や ~.11ty.js ファイルがある場合、これらも CommonJS から ESM に変更する必要があります。

変更内容は、.eleventy.js ファイルと同様です。

  • require(CommonJS)を import(ESM) に変更
  • module.exports =(CommonJS)を export(ESM)に変更

例:

const fs = require("fs");
const categoryDefine = require("./src/_data/tagDefine.js");

module.exports = {
  data: {
    permalink: "feed.xml",
    eleventyExcludeFromCollections: true,
    contentType: "application/xml"
  },
          :

CommonJS から ESM へ変更 👇

import fs from "fs";
import categoryDefine from "./src/_data/tagDefine.js";

export default {
  data: {
    permalink: "feed.xml",
    eleventyExcludeFromCollections: true,
    contentType: "application/xml"
  },
          :

👉 これで、正しく、読み込まれるようになります。


まとめ

  • Eleventy v3 は ESM(import/export)を推奨しているが、 CommonJS(require)も普通に使える。

  • Eleventy v3 のモジュール方式は Node.js の package.json の "type" 設定に従う。

    • "type": "commonjs" なら require / module.exports が動く
    • "type": "module" なら import / export が必要