8 |
9 |
10 | Rendered at {{ date }}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/playground/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "nuxt-build-cache-playground",
4 | "type": "module",
5 | "scripts": {
6 | "dev": "nuxi dev",
7 | "build": "nuxi build",
8 | "generate": "nuxi generate"
9 | },
10 | "devDependencies": {
11 | "nuxt": "latest"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules
3 |
4 | # Logs
5 | *.log*
6 |
7 | # Temp directories
8 | .temp
9 | .tmp
10 | .cache
11 |
12 | # Yarn
13 | **/.yarn/cache
14 | **/.yarn/*state*
15 |
16 | # Generated dirs
17 | dist
18 |
19 | # Nuxt
20 | .nuxt
21 | .output
22 | .data
23 | .vercel_build_output
24 | .build-*
25 | .netlify
26 |
27 | # Env
28 | .env
29 |
30 | # Testing
31 | reports
32 | coverage
33 | *.lcov
34 | .nyc_output
35 |
36 | # VSCode
37 | .vscode/*
38 | !.vscode/settings.json
39 | !.vscode/tasks.json
40 | !.vscode/launch.json
41 | !.vscode/extensions.json
42 | !.vscode/*.code-snippets
43 |
44 | # Intellij idea
45 | *.iml
46 | .idea
47 |
48 | # OSX
49 | .DS_Store
50 | .AppleDouble
51 | .LSOverride
52 | .AppleDB
53 | .AppleDesktop
54 | Network Trash Folder
55 | Temporary Items
56 | .apdisk
57 |
58 | # Why not?
59 | .next
60 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 |
4 | ## v0.1.1
5 |
6 |
7 | ### 🚀 Enhancements
8 |
9 | - Content hash ([3950b16](https://github.com/pi0/nuxt-build-cache/commit/3950b16))
10 |
11 | ### 🩹 Fixes
12 |
13 | - Cache hashes ([b070c30](https://github.com/pi0/nuxt-build-cache/commit/b070c30))
14 | - Use content based hashing ([c4ee569](https://github.com/pi0/nuxt-build-cache/commit/c4ee569))
15 |
16 | ### 💅 Refactors
17 |
18 | - Split cache utils ([87ff033](https://github.com/pi0/nuxt-build-cache/commit/87ff033))
19 | - Move cf pages hack to cache utils ([a4b11f0](https://github.com/pi0/nuxt-build-cache/commit/a4b11f0))
20 |
21 | ### 🏡 Chore
22 |
23 | - Update readme ([be2b420](https://github.com/pi0/nuxt-build-cache/commit/be2b420))
24 | - Add small docs ([8f056a7](https://github.com/pi0/nuxt-build-cache/commit/8f056a7))
25 | - Eslint ignore playground ([191898d](https://github.com/pi0/nuxt-build-cache/commit/191898d))
26 | - Disable test ([0e73723](https://github.com/pi0/nuxt-build-cache/commit/0e73723))
27 |
28 | ### ❤️ Contributors
29 |
30 | - Pooya Parsa ([@pi0](http://github.com/pi0))
31 |
32 |
--------------------------------------------------------------------------------
/src/module.ts:
--------------------------------------------------------------------------------
1 | import { defineNuxtModule } from "@nuxt/kit";
2 | import { consola } from "./utils";
3 | import { collectBuildCache, restoreBuildCache } from "./cache";
4 |
5 | export default defineNuxtModule({
6 | async setup(_, nuxt) {
7 | if (
8 | nuxt.options._prepare ||
9 | nuxt.options.dev ||
10 | process.env.NUXT_DISABLE_BUILD_CACHE
11 | ) {
12 | return;
13 | }
14 |
15 | // Setup hooks
16 | nuxt.hook("build:before", async () => {
17 | // Try to restore
18 | const restored = process.env.NUXT_IGNORE_BUILD_CACHE
19 | ? undefined
20 | : await restoreBuildCache(nuxt);
21 | if (restored) {
22 | // Skip build since it's restored
23 | nuxt.options.builder = {
24 | bundle() {
25 | consola.info("skipping build");
26 | return Promise.resolve();
27 | },
28 | };
29 | } else {
30 | // Collect build cache this time
31 | if (!process.env.SKIP_NUXT_BUILD_CACHE_COLLECT) {
32 | nuxt.hook("close", async () => {
33 | await collectBuildCache(nuxt);
34 | });
35 | }
36 | }
37 | });
38 | },
39 | });
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nuxt-build-cache",
3 | "version": "0.1.1",
4 | "description": "experimental build cache module for Nuxt 3",
5 | "repository": "pi0/nuxt-build-cache",
6 | "license": "MIT",
7 | "type": "module",
8 | "exports": {
9 | ".": {
10 | "types": "./dist/types.d.ts",
11 | "import": "./dist/module.mjs",
12 | "require": "./dist/module.cjs"
13 | }
14 | },
15 | "main": "./dist/module.cjs",
16 | "types": "./dist/types.d.ts",
17 | "files": [
18 | "dist"
19 | ],
20 | "scripts": {
21 | "prepack": "nuxt-module-build build",
22 | "dev": "nuxi dev playground",
23 | "dev:build": "nuxi build playground",
24 | "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
25 | "release": "npm run lint && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
26 | "lint": "eslint ."
27 | },
28 | "dependencies": {
29 | "@nuxt/kit": "^3.10.1",
30 | "consola": "^3.2.3",
31 | "globby": "^14.0.0",
32 | "nanotar": "^0.1.1",
33 | "nypm": "^0.3.6",
34 | "ohash": "^1.1.3",
35 | "pkg-types": "^1.0.3",
36 | "std-env": "^3.7.0"
37 | },
38 | "devDependencies": {
39 | "@nuxt/devtools": "latest",
40 | "@nuxt/eslint-config": "^0.2.0",
41 | "@nuxt/module-builder": "^0.5.5",
42 | "@nuxt/schema": "^3.10.1",
43 | "@types/node": "^20.11.13",
44 | "automd": "^0.2.0",
45 | "changelogen": "^0.5.5",
46 | "eslint": "^8.56.0",
47 | "nuxt": "^3.10.1"
48 | }
49 | }
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import { readFile, stat } from "node:fs/promises";
2 | import { resolve } from "node:path";
3 | import type { TarFileInput } from "nanotar";
4 | import { globby } from "globby";
5 | import _consola from "consola";
6 |
7 | export const consola = _consola.withTag("nuxt-build-cache");
8 |
9 | export type FileWithMeta = TarFileInput;
10 |
11 | export async function readFilesRecursive(
12 | dir: string | string[],
13 | opts: {
14 | shouldIgnore?: (name: string) => boolean;
15 | noData?: boolean;
16 | patterns?: string[];
17 | } = {}
18 | ): Promise