點燈坊

失くすものさえない今が強くなるチャンスよ

Integrating TEAstack with 11ty

Sam Xiao's Avatar 2021-12-29

11ty is great for JAMstack, but we have to use vanilla JavaScript and CSS to create templates. With Alpine and TailwindCSS, we can create templates by declarative style directly in HTML, and we can finally use HTMLMinifier to optimize our HTML under production mode.

Version

11ty 0.12.1
TailwindCSS 3.0
Alpine 3.7
HTMLMinifier 4.0.0

Create Folder

$ mkdir 11ty-tea

Create 11ty project directory.

tea000

Add Packages

$ yarn init -y
$ yarn add @11ty/eleventy tailwindcss alpinejs html-minifier npm-run-all --dev

Use Yarn to add related package with dev dependency

  • @11ty/eleventy : build markdown to HTML/CSS/JavaScript
  • tailwindcss : use utilities to style HTML
  • alpinejs : use attributes to integrate JavaScript
  • html-minifier : optimize HTML output
  • npn-run-all : run NPM scripts in sequential or in parallel

tea001

Tailwind Config

$ npx tailwindcss init

Use Tailwind CLI to generate default tailwind.config.js.

tea003

tailwind.config.js

module.exports = {
  content: ['./src/**/*.{md,html}'],
  theme: {
    extend: {},
  },
  plugins: [],
}

Line 3

content: ['./src/**/*.{md,html}'],

Purge unused CSS by specified file extensions.

tea004

11ty Config

.eleventy.js

let htmlMinifier = require ('html-minifier')

module.exports = config => {
  // Alpine
  config.addPassthroughCopy ({
    'node_modules/alpinejs/dist/cdn.js': 'alpine.js',
  })

  // HTMLMinifier
  config.addTransform ('htmlMinifier', content => {
    if (process.env.NODE_ENV === 'production') {
      return htmlMinifier.minify (content, {
        useShortDoctype: true,
        removeComments: true,
        collapseWhitespace: true,
      })
    }
    return content
  })

  // directory & template engine
  return {
    htmlTemplateEngine: 'njk',
    dir: {
      input: 'src',
      output: 'dist',
      includes: 'template',
    }
  }
}

Define 11ty settings.

Line 4

// Alpine
config.addPassthroughCopy ({
  'node_modules/alpinejs/dist/cdn.js': 'alpine.js',
})

It will copy Alpine from the node_modules to the dist directory when running 11ty.

Line 9

// HTMLMinifier
config.addTransform ('htmlMinifier', content => {
  if (process.env.NODE_ENV === 'production') {
    return htmlMinifier.minify (content, {
      useShortDoctype: true,
      removeComments: true,
      collapseWhitespace: true,
    })
  }
  return content
})
  • config.addTransform : modify the template’s output
  • Under production mode, call HTMLMinifier to optimize HTML page

Line 21

// directory & template engine
return {
  htmlTemplateEngine: 'njk',
  dir: {
    input: 'src',
    output: 'dist',
    includes: 'template',
  }
}
  • htmlTemplateEngine : use Numjucks as the default template engine
  • dir : user-defined directory
    • input : define markdown directory
    • output : define build directory
    • includes : define template directory under input directory

tea002

CSS File

src/input.css

@tailwind base;
@tailwind components;
@tailwind utilities;
  • Add index.css on src directory
  • Tailwind CLI transpiles input.css to output.css

tea005

Template

src/index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="output.css">
  <script src="alpine.js" defer></script>
  <title>Hello 11ty</title>
</head>
<body>
  <div class="text-4xl text-red-700">Hello TEAstack</div>
  <div x-data="{ count: 0 }">
    <button class="border border-gray-300 text-xs text-gray-700 px-2 py-1" @click="count++">+</button>
    <span x-text="count"/>
  </div>
</body>
</html>

Line 6

<link rel="stylesheet" href="output.css">

Link CSS file to template.

Line 7

<script src="alpine.js" defer></script>

Use CDN directly as we use Alpine on the HTML page.

Line 11

<div class="text-4xl text-red-700">Hello TEAstack</div>

Use TailwindCSS utilities for HTML.

Line 12

<div x-data="{ count: 0 }">
  <button class="border border-gray-300 text-xs text-gray-700 px-2 py-1" @click="count++">+</button>
  <span x-text="count"/>
</div>

Classical counter implemented by Alpine and TailwindCSS.

tea006

NPM Config

package.json

{
  "name": "11ty-tea",
  "version": "1.0.0",
  "license": "MIT",
  "scripts": {
    "dev:css": "npx tailwindcss -i src/input.css -o dist/output.css -w",
    "dev:11ty": "eleventy --serve",
    "dev": "run-p dev:*",
    "build:css": "NODE_ENV=production npx tailwindcss -i src/input.css -o dist/output.css -m",
    "build:11ty": "NODE_ENV=production eleventy",
    "build": " run-s build:*"
  },
  "devDependencies": {
    "@11ty/eleventy": "^0.12.1",
    "alpinejs": "^3.7.0",
    "html-minifier": "^4.0.0",
    "npm-run-all": "^4.1.5",
    "tailwindcss": "^3.0.2"
  }
}

Line 6

"dev:css": "npx tailwindcss -i src/input.css -o dist/output.css -w",

Use Tailwind CLI to build CSS under development mode :

  • -i src/input.css : use input.css as the source CSS file
  • -o dist/output.css : use output.css as the target CSS file
  • -w : watch for changes and rebuild as needed

Line 7

"dev:11ty": "eleventy --serve",

Run web server by 11ty.

Line 8

"dev": "run-p dev:*",

run-p : run all dev:* in parallel under development mode.

Line 9

"build:css": "NODE_ENV=production npx tailwindcss -i src/input.css -o dist/output.css -m",

Use Tailwind CLI to build CSS under production mode :

  • -i src/input.css : use input.css as source CSS file
  • -o dist/output.css : use output.css as target CSS file
  • -m : minify target CSS file

Line 10

"build:11ty": "NODE_ENV=production eleventy",

Set NODE_ENV=production to optimize HTML under production mode.

Line 11

"build": " run-s build:*"

run-s : run all build:* in sequential under production mode.

tea008

Development Mode

$ yarn dev

Start web server under development mode.

tea009

TailwindCSS and Alpine with 11ty are enabled under development mode.

tea010

Production Mode

$ yarn build
$ serve dist
  • Build 11ty with minified target CSS file under production mode
  • Use serve to run web server

tea011

TailwindCSS and Alpine with 11ty are enabled under production mode.

tea012

HTML is optimized under production mode.

tea013

Conclusion

  • It’s not too difficult to integrate TEAstack with 11ty. With Alpine and TailwindCSS, we can start to create templates by declarative style directly in HTML
  • With HTMLMinifier, we can finally optimize our HTML under production mode