1
- import type { Options } from "@navita/webpack-plugin" ;
1
+ import * as fs from "fs" ;
2
+ import path from "node:path" ;
3
+ import type { Options , Renderer } from "@navita/webpack-plugin" ;
2
4
import { getNavitaModule , NavitaPlugin , NAVITA_MODULE_TYPE } from "@navita/webpack-plugin" ;
3
5
import type MiniCssExtractPluginType from "mini-css-extract-plugin" ;
4
6
import type { NextConfig } from "next" ;
@@ -8,11 +10,12 @@ import { findPagesDir } from "next/dist/lib/find-pages-dir";
8
10
import type { Configuration } from "webpack" ;
9
11
import { optimizeCSSOutput } from "./optimizeCSSOutput" ;
10
12
11
- const MiniCssExtractPlugin = NextMiniCssExtractPluginDefault [ 'default' ] as typeof MiniCssExtractPluginType ;
13
+ let renderer : Renderer ;
14
+ let lastCache : string ;
12
15
13
- type WebpackOptions = Options ;
16
+ const MiniCssExtractPlugin = NextMiniCssExtractPluginDefault [ 'default' ] as typeof MiniCssExtractPluginType ;
14
17
15
- interface Config extends WebpackOptions {
18
+ interface Config extends Omit < Options , 'useWebpackCache' | 'onRenderInitialized' > {
16
19
singleCssFile ?: boolean ;
17
20
}
18
21
@@ -94,8 +97,59 @@ export const createNavitaStylePlugin = (navitaConfig: Config = {}) =>
94
97
} ;
95
98
}
96
99
100
+ // Next.js creates at least three webpack instances. We can't rely on the webpack cache.
101
+ const { cache, mode } = config ;
102
+
103
+ const cacheDirectory = (
104
+ typeof cache !== "boolean" && cache . type === "filesystem" ?
105
+ path . resolve ( cache . cacheDirectory , `navita-${ mode } ` ) :
106
+ undefined
107
+ ) ;
108
+
109
+ const cacheDestination = path . resolve ( cacheDirectory , 'data.txt' ) ;
110
+
111
+ const onRenderInitialized = async ( createdRenderer : Renderer ) => {
112
+ renderer = createdRenderer ;
113
+
114
+ try {
115
+ // Ensure the cache directory exists:
116
+ await fs . promises . mkdir ( cacheDirectory , { recursive : true } ) ;
117
+
118
+ const content = await fs . promises . readFile ( cacheDestination , 'utf-8' ) ;
119
+
120
+ await renderer . engine . deserialize ( content ) ;
121
+
122
+ lastCache = renderer . engine . serialize ( ) ;
123
+ } catch {
124
+ // This will happen if the user doesn't have write access to the cache directory.
125
+ // But the same should happen with the webpack cache.
126
+ }
127
+ } ;
128
+
129
+ config . plugins ?. push ( {
130
+ apply ( compiler ) {
131
+ compiler . hooks . afterEmit . tapPromise ( `${ NavitaPlugin . pluginName } -nextjs-custom-cache` , async ( ) => {
132
+ if ( ! renderer ) {
133
+ return ;
134
+ }
135
+
136
+ const newCache = renderer . engine . serialize ( ) ;
137
+
138
+ if ( newCache === lastCache ) {
139
+ return ;
140
+ }
141
+
142
+ lastCache = newCache ;
143
+
144
+ await fs . promises . writeFile ( cacheDestination , newCache ) ;
145
+ } ) ;
146
+ }
147
+ } ) ;
148
+
97
149
config . plugins ?. push (
98
150
new NavitaPlugin ( {
151
+ useWebpackCache : false ,
152
+ onRenderInitialized,
99
153
outputCss,
100
154
...navitaConfig ,
101
155
optimizeCSSOutput,
0 commit comments