Typescript Eleventy Config
Benny Powers 🇮🇱🇨🇦

Benny Powers 🇮🇱🇨🇦 @bennypowers

About: Coding is as much a matter of personal growth as it is of logic and control-flow. I keep patience, curiosity, & exuberance in the same toolbox as vim and git. *Opinions posted are my own*

Location:
Jerusalem
Joined:
May 22, 2018

Typescript Eleventy Config

Publish Date: Sep 24 '24
0 0

There are a bunch of guides out there explaining how to write 11ty configs in typescript so that you can compile them prior to running 11ty. This isn't one of those. I'm here to explain how to run eleventy on your typescript configs, with all the familiar editor ergonomics, without building your config files at all. Dev time, meet runtime.

You'll need node.js 22.6 or later, which adds the --experimental-strip-types flag. What this does is tell node to just ignore typescript syntax, as if it was a comment. Node here is basically implementing the types as comments proposal, and I hope everyone else follows suit quickly.

Doing the Cool Kids' Homework

Now, 11ty follows the types-in-jsdoc approach, which is fine i guess whatever, but for some reason, they don't then ship those types in .d.ts files, so we'll have to build them ourselves. Run this script in postinstall:

import { $ } from 'execa';

import Manifest from '../package.json' with { type: 'json' };

await $`npx tsc node_modules/@11ty/eleventy/src/UserConfig.js
        --declaration
        --allowJs
        --emitDeclarationOnly
        --moduleResolution nodenext
        --module nodenext
        --target esnext`;

for (const pkg in Manifest.dependencies) {
  if (pkg.startsWith('@11ty')) {
    const spec = import.meta.resolve(pkg).replace('file://', '');
    try {
      await $`npx tsc ${spec}
              --declaration
              --allowJs
              --emitDeclarationOnly
              --moduleResolution nodenext
              --module nodenext
              --target esnext`;
    } catch(e) {
      console.log(e.stdout);
    }
    console.log(`Wrote types for ${pkg}`)
  }
}
Enter fullscreen mode Exit fullscreen mode

Shipping .d.ts type declarations in your npm library is an accessibility issue. Your users with cognitive disabilities like ADHD can't afford to keep alt-tabbing back to your docs site. I hope the 11ty authors will integrate this into their build system soon.

TypeScript, Ho!

That having been accomplished, rename your config file and import the UserConfig type:

mv eleventy.config.js eleventy.config.ts
Enter fullscreen mode Exit fullscreen mode
import type { UserConfig } from '@11ty/eleventy';

export default function(eleventyConfig: UserConfig) {
  eleventyConfig.
}
Enter fullscreen mode Exit fullscreen mode

And watch those LSP-completion suggestions roll in.

If you have split your config into multiple files, you need to enable .ts extension in your tsconfig.json. Also disable emit, because we're not actually running tsc at any point, this is all for neovim.

Here, crib mine:

{
  "compilerOptions": {
    "module": "NodeNext",
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "NodeNext",
    "allowImportingTsExtensions": true,
    "target": "ESNext",
    "noEmit": true
  }
}
Enter fullscreen mode Exit fullscreen mode

Last thing is to actually run it, and to do that we'll use the NODE_OPTIONS environment variable

"scripts": {
  "build": "NODE_OPTIONS='--experimental-strip-types' eleventy --config=eleventy.config.ts --incremental",
  "start": "NODE_OPTIONS='--experimental-strip-types' eleventy --config=eleventy.config.ts --serve --incremental"
},
Enter fullscreen mode Exit fullscreen mode

Gimmie the Code

And that's pretty much it! I accomplished the above on this site in commit 307e5cf8, which you're welcome to ogle over at Microsoft's loss-leader code scraping utility.

Comments 0 total

    Add comment