-
Notifications
You must be signed in to change notification settings - Fork 0
/
next.config.js
127 lines (119 loc) · 3.18 KB
/
next.config.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const CSP_GENERAL = {
"default-src": ["'none'"],
"script-src": ["'self'"],
"style-src": ["'self'", "'unsafe-inline'"],
"font-src": ["'self'"],
"img-src": ["'self'", "data:"],
"media-src": ["'self'"],
"connect-src": ["'self'"],
};
const CSP_DEV = {
"script-src": ["'unsafe-eval'"],
};
const CSP_GOOGLE_MAPS = {
"script-src": ["https://*.googleapis.com"],
"style-src": ["https://fonts.googleapis.com"],
"font-src": ["https://fonts.gstatic.com"],
"img-src": ["https://*.googleapis.com", "https://*.gstatic.com", "*.google.com", "*.googleusercontent.com"],
"connect-src": ["https://*.googleapis.com", "*.google.com", "https://*.gstatic.com"],
};
const CSP_GOOGLE_ANALYTICS = {
"script-src": ["https://www.googletagmanager.com"],
"connect-src": ["https://*.google-analytics.com"],
};
function getCSPValue(pageHasGoogleMaps) {
const combinedDirectives = {};
function addDirectives(directives) {
for (const [directive, sources] of Object.entries(directives)) {
if (!combinedDirectives.hasOwnProperty(directive)) {
combinedDirectives[directive] = new Set(sources);
} else {
sources.forEach((s) => combinedDirectives[directive].add(s));
}
}
}
addDirectives(CSP_GENERAL);
if (process.env.NODE_ENV === "development") {
addDirectives(CSP_DEV);
}
if (pageHasGoogleMaps) {
addDirectives(CSP_GOOGLE_MAPS);
}
addDirectives(CSP_GOOGLE_ANALYTICS);
return Object.entries(combinedDirectives)
.map(([k, v]) => k + " " + [...v].join(" "))
.join(";");
}
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
poweredByHeader: false,
images: {
unoptimized: true,
},
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ["@svgr/webpack"],
});
return config;
},
async headers() {
return [
{
source: "/:path*",
headers: [
{
key: "Access-Control-Allow-Origin",
value: "null" /* Vercel sets it to * by default, so we want to disable it */,
},
{
key: "Cross-Origin-Resource-Policy",
value: "same-site",
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Strict-transport-security",
value: "max-age=63072000; includeSubDomains; preload",
},
],
},
{
source: "/",
headers: [
{
key: "Content-Security-Policy",
value: getCSPValue(true),
},
{
key: "Cross-Origin-Opener-Policy",
value: "same-origin",
},
],
},
{
source: "/:path((?:img|font|favicon)/[\\s\\S]+|[^\\/]+(?:\\.svg|\\.json|\\.ico))",
headers: [
{
key: "Cache-Control",
value: "max-age=86400, stale-while-revalidate=604800",
},
],
},
{
source: "/_next/static/:any*",
headers: [
{
key: "Cache-Control",
value: "max-age=31536000, immutable",
},
],
},
];
},
};
module.exports = nextConfig;