Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix next.js cache #43

Merged
merged 2 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/lovely-ducks-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@navita/webpack-plugin": minor
"@navita/next-plugin": minor
---

Added functionality to disable the usage of webpacks cache via the plugins constructor. Added a custom cache solution for next.js that uses a single text file to store the cache between compilations.
4 changes: 2 additions & 2 deletions examples/with-next-app-dir/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"name": "with-next-app-dir",
"version": "0.0.0",
"scripts": {
"dev": "rimraf .next && next dev",
"build": "rimraf .next && next build",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
Expand Down
4 changes: 3 additions & 1 deletion examples/with-next-app-dir/src/app/edge/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { style } from "@navita/css";

const y = style({
background: 'dimgray',
background: 'hotpink',
color: 'white',
padding: 20,
});

export default function Edge() {
Expand Down
4 changes: 2 additions & 2 deletions examples/with-next-app-dir/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { style } from "@navita/css";

const container = style({
background: 'royalblue',
color: 'white',
background: 'orange',
color: 'black',
fontSize: '2rem',
padding: '1rem',
});
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"jest": "workspace:*",
"prettier": "latest",
"turbo": "^1.10.7",
"typescript": "5.1.3"
"typescript": "5.4.5"
},
"devDependencies": {
"@types/node": "^18.14.0"
Expand Down
62 changes: 58 additions & 4 deletions packages/next-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Options } from "@navita/webpack-plugin";
import * as fs from "fs";
import path from "node:path";
import type { Options, Renderer } from "@navita/webpack-plugin";
import { getNavitaModule, NavitaPlugin, NAVITA_MODULE_TYPE } from "@navita/webpack-plugin";
import type MiniCssExtractPluginType from "mini-css-extract-plugin";
import type { NextConfig } from "next";
Expand All @@ -8,11 +10,12 @@ import { findPagesDir } from "next/dist/lib/find-pages-dir";
import type { Configuration } from "webpack";
import { optimizeCSSOutput } from "./optimizeCSSOutput";

const MiniCssExtractPlugin = NextMiniCssExtractPluginDefault['default'] as typeof MiniCssExtractPluginType;
let renderer: Renderer;
let lastCache: string;

type WebpackOptions = Options;
const MiniCssExtractPlugin = NextMiniCssExtractPluginDefault['default'] as typeof MiniCssExtractPluginType;

interface Config extends WebpackOptions {
interface Config extends Omit<Options, 'useWebpackCache' | 'onRenderInitialized'> {
singleCssFile?: boolean;
}

Expand Down Expand Up @@ -94,8 +97,59 @@ export const createNavitaStylePlugin = (navitaConfig: Config = {}) =>
};
}

// Next.js creates at least three webpack instances. We can't rely on the webpack cache.
const { cache, mode } = config;

const cacheDirectory = (
typeof cache !== "boolean" && cache.type === "filesystem" ?
path.resolve(cache.cacheDirectory, `navita-${mode}`) :
undefined
);

const cacheDestination = path.resolve(cacheDirectory, 'data.txt');

const onRenderInitialized = async (createdRenderer: Renderer) => {
renderer = createdRenderer;

try {
// Ensure the cache directory exists:
await fs.promises.mkdir(cacheDirectory, { recursive: true });

const content = await fs.promises.readFile(cacheDestination, 'utf-8');

await renderer.engine.deserialize(content);

lastCache = renderer.engine.serialize();
} catch {
// This will happen if the user doesn't have write access to the cache directory.
// But the same should happen with the webpack cache.
}
};

config.plugins?.push({
apply(compiler) {
compiler.hooks.afterEmit.tapPromise(`${NavitaPlugin.pluginName}-nextjs-custom-cache`, async () => {
if (!renderer) {
return;
}

const newCache = renderer.engine.serialize();

if (newCache === lastCache) {
return;
}

lastCache = newCache;

await fs.promises.writeFile(cacheDestination, newCache);
});
}
});

config.plugins?.push(
new NavitaPlugin({
useWebpackCache: false,
onRenderInitialized,
outputCss,
...navitaConfig,
optimizeCSSOutput,
Expand Down
24 changes: 22 additions & 2 deletions packages/webpack-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { prepareCssOutput } from "./prepareCssOutput";

export { getNavitaDependency, getNavitaModule, NAVITA_MODULE_TYPE };
export { CSSOutput, Engine, Compilation, UsedIdCache };
export type { Renderer };

type MiniCSSExtractPlugin = {
options: {
Expand All @@ -28,10 +29,19 @@ export interface Options {
importMap?: ImportMap;
optimizeCSSOutput?: (output: CSSOutput, compilation?: Compilation, engine?: Engine) => CSSOutput;
engineOptions?: EngineOptions;
onRenderInitialized?: (renderer: Renderer) => Promise<void>;
/**
* This uses webpacks cache to store the engine state between builds.
* If you have more than one webpack instance running at the same time,
* you should disable this option, and instead do something similar to
* what is done in the `next-plugin` package.
*/
useWebpackCache?: boolean;
}

const defaultOptions: Options = {
outputCss: true,
useWebpackCache: true,
exclude: /node_modules/,
importMap: [],
};
Expand Down Expand Up @@ -63,6 +73,8 @@ export class NavitaPlugin {
outputCss,
optimizeCSSOutput,
engineOptions,
useWebpackCache,
onRenderInitialized,
} = this.options;

const importMap = [
Expand All @@ -72,8 +84,6 @@ export class NavitaPlugin {

const dev = compiler.options.mode !== "production";

const cacheName = `${NavitaPlugin.pluginName}-${compiler.options.mode}`;

const defaultEngineOptions = {
enableSourceMaps: dev,
enableDebugIdentifiers: dev,
Expand Down Expand Up @@ -116,6 +126,16 @@ export class NavitaPlugin {
}
});

if (onRenderInitialized) {
await onRenderInitialized(renderer);
}

if (!useWebpackCache) {
return;
}

const cacheName = `${NavitaPlugin.pluginName}-${compiler.options.mode}`;

const result = await compilation
.getCache(cacheName)
.getPromise<Buffer>(NavitaPlugin.pluginName, cacheKey);
Expand Down
Loading
Loading