npm package: @gritdigital/grit-build
Description: A thin wrapper around [esbuild](https://esbuild.github.io/) and [LightningCSS](https://lightningcss.dev/) to make building for the web fast and simple.
Author: GRIT Digital
Latest version: 1.3.0

# GRIT Build

A thin wrapper around [esbuild](https://esbuild.github.io/) and [LightningCSS](https://lightningcss.dev/) to make building for the web fast and simple.

## Features

- Tailwind support.
- SCSS support.
- Manifest file generation.
- Browsersync when `gritBuild` is executed with a `--watch` flag.
- Accessibility testing with [pa11y](https://github.com/pa11y/pa11y).
- Lighthouse testing with [lighthouse](https://github.com/GoogleChrome/lighthouse).

## Getting Started

```
npm install @gritdigital/grit-build --save-dev
```

## Example Usage

```typescript
import gritBuild from "@gritdigital/grit-build";

gritBuild({
    build: {
        esbuild: {
            entryPoints: [
                {
                    in: "./resources/ts/index.ts",
                    out: "js/index",
                },
                {
                    in: "./resources/styles/index.scss",
                    out: "css/index",
                },
            ],
            outdir: "./theme/assets",
            loader: {
                ".woff2": "file",
            },
        },
        output: {
            clear: true,
            preserve: ["images"],
        },
        manifest: ["js/index.js", "css/index.css"],
    },
    dev: {
        server: {
            url: "https://example.grit",
        },
        watch: ["./theme/pages/**/*.html"],
    },
});
```

> Regardless of where `gritBuild` is called, the paths should be relative to your projects root.

### Interface

```typescript
interface GritBuildConfig {
    /**
     * Core build configuration
     */
    build: {
        /** Required esbuild configuration - https://esbuild.github.io/ */
        esbuild: BuildOptions;
        /** Output directory configuration */
        output?: {
            /** Clear output directory before build */
            clear?: boolean;
            /** Patterns to ignore when clearing output directory */
            preserve?: string[];
            /** Files to remove after build completion */
            cleanup?: string[];
        };
        /** Files to include in the build manifest */
        manifest?: string[];
    };

    /**
     * Asset management configuration
     */
    assets?: {
        /** Directory copy operations */
        copy?: Array<{
            from: string;
            to: string;
        }>;
    };

    /**
     * CSS processing configuration
     */
    styles?: {
        /** 
         * Array of browserlist queries. Will be passed to browserslist().
         * @example ['> 1%', 'last 2 versions', 'safari 14']
         * @see https://github.com/browserslist/browserslist?tab=readme-ov-file#full-list
         */
        target?: string[]
        /** Tailwind CSS configuration */
        tailwind?: {
            /** Determines if Tailwind CSS is included in the build */
            enabled?: boolean;
            config?: string;
        };
        /** LightningCSS transform options */
        lightning?: Omit<TransformOptions<CustomAtRules>, "filename" | "code" | "targets">;
    };

    /**
     * Development configuration
     */
    dev?: {
        /** BrowserSync configuration */
        server?: {
            /** Site URL for proxying */
            url: string;
            /** BrowserSync specific options */
            options?: Exclude<browserSync.Options, "proxy">;
        };
        /** Directories to watch for changes */
        watch?: string[];
    };
}
```

### Build Targets

##### JavaScript

The default esbuild target is set to the following:

- Chrome 129
- Firefox 129
- Safari 15

If you need to override this, you can do so by setting the `target` property in the esbuild config. You can find the list of supported targets [here](https://esbuild.github.io/api/#target).

```typescript
gritBuild({
    build: {
        esbuild: {
            target: ["chrome129", "firefox129", "safari15"],
        },
    }
});
```

#### CSS

The default LightningCSS target is set to `>= 0.25%` meaning it will support browsers that make up more or equal to 0.25% of global usage.

You can override this like so:

```typescript
gritBuild({
    styles: {
		target: ">= 0.25%",
    }
});
```

## Plugins

### Esbuild Plugins

```typescript
import {
  copyDirsPlugin,
  manifestPlugin,
  clearOutdirPlugin,
  browserSyncPlugin,
  removeFilesPlugin,
} from "@gritdigital/grit-build/esbuild";
```

### Eslint Plugin

```js
// .eslint.config.mjs
import gritEslint from "@gritdigital/grit-build/eslint";

export default [
    ...gritEslint.configs.recommended,
]
```

### Prettier Plugins

```js
// .prettier.config.js

export { default } from "@gritdigital/grit-build/prettier";

// or

import prettier from "@gritdigital/grit-build/prettier";

export default {
  ...prettier,
  // your custom config
}
```

## Helpers

### getTwigImportPaths

This is a helper function for Twig and Tailwind setups that allows you to recursively find all of the twig include/embed paths for a given set of components. This is inteded to be used in conjunction with Tailwind's `content` property.

```typescript
import { getTwigImportPaths } from "@gritdigital/grit-build/helpers";

export default {
  content: [
    "theme/**/*.html",
    ...getTwigImportPaths({
      root: "views",
      components: ["blocks/block-1.twig", "blocks/block-2.twig"],
      // aliases: {
        // "@ui/": "",
      // },
      ignoreComponents: [],
      ignoreImports: [],
    }),
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

## Testing

### Accessibility

```bash
npx grit-tests-accessibility --sitemap https://mysite.local/sitemap_index.xml --standard WCAG2AA --url https://mysite.local
```

> If you provide both a sitemap and url, the url will be used as the default. Its recommended to just provide one of the two flags.

### Lighthouse

```bash
npx grit-tests-lighthouse --url https://mysite.local
```