-
Notifications
You must be signed in to change notification settings - Fork 7
/
NextIntlWebpackPlugin.js
85 lines (67 loc) · 3.01 KB
/
NextIntlWebpackPlugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import path from 'path';
import { promises as pFs } from 'fs';
import { ConcatSource } from 'webpack-sources';
import pDefer from 'p-defer';
import { REACT_LOADABLE_MANIFEST } from 'next/dist/next-server/lib/constants';
export default class NextIntlWebpackPlugin {
static clientDeferred;
distDir;
assetPrefix;
manifestPath;
polyfillUrl;
constructor(isServer, nextConfig) {
this.isServer = isServer;
this.distDir = nextConfig.distDir;
this.assetPrefix = nextConfig.assetPrefix;
this.manifestPath = path.join(this.distDir, REACT_LOADABLE_MANIFEST);
}
apply(compiler) {
if (!this.isServer) {
NextIntlWebpackPlugin.clientDeferred = pDefer();
NextIntlWebpackPlugin.clientDeferred.catch(() => {});
compiler.hooks.failed.tap('NextIntlPlugin', (err) => {
NextIntlWebpackPlugin.clientDeferred.reject(err);
});
compiler.hooks.done.tap('NextIntlPlugin', (stats) => {
if (stats.hasErrors()) {
NextIntlWebpackPlugin.clientDeferred.reject(new Error('Client-side compilation has errors, fix them first'));
} else {
NextIntlWebpackPlugin.clientDeferred.resolve();
}
});
} else {
compiler.hooks.emit.tapPromise('NextIntlPlugin', async (compilation) => {
try {
await NextIntlWebpackPlugin.clientDeferred.promise;
} catch (err) {
compilation.errors.push(err);
return;
}
const polyfillUrl = await this.readPolyfillUrlFromManifest();
compilation.chunks
.filter((chunk) => chunk.canBeInitial())
.reduce((files, chunk) => {
files.push(...chunk.files);
return files;
}, [])
.forEach((file) => {
const polyfillUrlCode = `__NEXT_INTL_POLYFILL_URL__ = ${JSON.stringify(polyfillUrl)};`;
compilation.assets[file] = new ConcatSource(polyfillUrlCode, compilation.assets[file]);
});
});
}
}
async readPolyfillUrlFromManifest() {
// We may cache the `polyfillUrl` because it doesn't change between compilations in watch mode
if (!this.polyfillUrl) {
const manifestContents = await pFs.readFile(this.manifestPath);
const manifestJson = JSON.parse(manifestContents);
const polyfillPublicPath = manifestJson['@formatjs/intl-pluralrules/polyfill-locales']?.[0]?.publicPath;
if (!polyfillPublicPath) {
throw new Error(`Could not find intl-polyfill chunk in ${this.manifestPath}, did you forgot to wrap your app with 'withNextIntlSetup'?'`);
}
this.polyfillUrl = `${this.assetPrefix}/_next/${polyfillPublicPath}`;
}
return this.polyfillUrl;
}
}