0
# Script & Asset Management Rules
1
2
ESLint rules for proper script loading and asset management in Next.js applications. These rules ensure optimal script placement, loading strategies, and prevent common script-related performance issues.
3
4
## Capabilities
5
6
### inline-script-id
7
8
Enforces id attribute for inline scripts to enable proper CSP and security practices.
9
10
```typescript { .api }
11
/**
12
* Rule: inline-script-id
13
* Enforces id attribute for inline scripts
14
* Severity: error (in recommended config)
15
* Category: Security/Scripts
16
*/
17
interface InlineScriptIdRule extends Rule.RuleModule {
18
meta: {
19
docs: {
20
description: 'Enforce id attribute for inline scripts';
21
category: 'Security';
22
recommended: true;
23
url: string;
24
};
25
type: 'problem';
26
schema: [];
27
};
28
}
29
```
30
31
**Validates:** Inline script elements have id attributes
32
**Prevents:** CSP violations and security issues with inline scripts
33
34
### next-script-for-ga
35
36
Enforces Next.js Script component for Google Analytics instead of HTML script tags.
37
38
```typescript { .api }
39
/**
40
* Rule: next-script-for-ga
41
* Enforces Next.js Script component for Google Analytics
42
* Severity: warn (in recommended config)
43
* Category: Performance/Scripts
44
*/
45
interface NextScriptForGARule extends Rule.RuleModule {
46
meta: {
47
docs: {
48
description: 'Enforce Next.js Script component for Google Analytics';
49
category: 'Performance';
50
recommended: true;
51
url: string;
52
};
53
type: 'suggestion';
54
schema: [];
55
};
56
}
57
```
58
59
**Validates:** Google Analytics uses Next.js Script component
60
**Prevents:** Suboptimal loading strategies for analytics scripts
61
62
### no-before-interactive-script-outside-document
63
64
Prevents beforeInteractive scripts outside of _document.js where they won't work correctly.
65
66
```typescript { .api }
67
/**
68
* Rule: no-before-interactive-script-outside-document
69
* Prevents beforeInteractive scripts outside _document.js
70
* Severity: warn (in recommended config)
71
* Category: Scripts/Architecture
72
*/
73
interface NoBeforeInteractiveScriptOutsideDocumentRule extends Rule.RuleModule {
74
meta: {
75
docs: {
76
description: 'Prevent beforeInteractive scripts outside _document.js';
77
category: 'Architecture';
78
recommended: true;
79
url: string;
80
};
81
type: 'problem';
82
schema: [];
83
};
84
}
85
```
86
87
**Validates:** beforeInteractive scripts are only in _document.js
88
**Prevents:** Scripts that won't load with correct timing strategy
89
90
### no-script-component-in-head
91
92
Prevents Script components inside Head components where they're ineffective.
93
94
```typescript { .api }
95
/**
96
* Rule: no-script-component-in-head
97
* Prevents Script components in Head components
98
* Severity: error (in recommended config)
99
* Category: Scripts/Architecture
100
*/
101
interface NoScriptComponentInHeadRule extends Rule.RuleModule {
102
meta: {
103
docs: {
104
description: 'Prevent Script components in Head';
105
category: 'Architecture';
106
recommended: true;
107
url: string;
108
};
109
type: 'problem';
110
schema: [];
111
};
112
}
113
```
114
115
**Validates:** Script components are not placed inside Head components
116
**Prevents:** Scripts that won't execute due to incorrect placement
117
118
### no-unwanted-polyfillio
119
120
Prevents unwanted polyfill.io usage that can introduce security and performance issues.
121
122
```typescript { .api }
123
/**
124
* Rule: no-unwanted-polyfillio
125
* Prevents unwanted polyfill.io usage
126
* Severity: warn (in recommended config)
127
* Category: Security/Performance
128
*/
129
interface NoUnwantedPolyfillIoRule extends Rule.RuleModule {
130
meta: {
131
docs: {
132
description: 'Prevent unwanted polyfill.io usage';
133
category: 'Security';
134
recommended: true;
135
url: string;
136
};
137
type: 'problem';
138
schema: [];
139
};
140
}
141
```
142
143
**Validates:** Polyfill.io scripts are not used without justification
144
**Prevents:** Potential security and performance issues from third-party polyfills
145
146
### no-css-tags
147
148
Prevents manual CSS link tags in favor of Next.js CSS import system.
149
150
```typescript { .api }
151
/**
152
* Rule: no-css-tags
153
* Prevents manual CSS link tags
154
* Severity: warn (in recommended config)
155
* Category: Assets/Performance
156
*/
157
interface NoCssTagsRule extends Rule.RuleModule {
158
meta: {
159
docs: {
160
description: 'Prevent manual CSS link tags';
161
category: 'Performance';
162
recommended: true;
163
url: string;
164
};
165
type: 'suggestion';
166
schema: [];
167
};
168
}
169
```
170
171
**Validates:** CSS is loaded through Next.js import system
172
**Prevents:** Suboptimal CSS loading and missing optimizations
173
174
## Usage Examples
175
176
### Correct Script Usage
177
178
```jsx
179
// ✅ Correct - Using Next.js Script component
180
import Script from 'next/script';
181
182
export default function MyPage() {
183
return (
184
<>
185
<div>Page content</div>
186
187
{/* Google Analytics with Next.js Script */}
188
<Script
189
src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"
190
strategy="afterInteractive"
191
/>
192
<Script id="google-analytics" strategy="afterInteractive">
193
{`
194
window.dataLayer = window.dataLayer || [];
195
function gtag(){dataLayer.push(arguments);}
196
gtag('js', new Date());
197
gtag('config', 'GA_MEASUREMENT_ID');
198
`}
199
</Script>
200
</>
201
);
202
}
203
```
204
205
### Correct Document Scripts
206
207
```jsx
208
// ✅ Correct - beforeInteractive scripts in _document.js
209
import { Html, Head, Main, NextScript } from 'next/document';
210
import Script from 'next/script';
211
212
export default function Document() {
213
return (
214
<Html>
215
<Head />
216
<body>
217
<Main />
218
<NextScript />
219
220
{/* Critical scripts that need to load before interactivity */}
221
<Script
222
id="critical-script"
223
strategy="beforeInteractive"
224
src="/critical-script.js"
225
/>
226
</body>
227
</Html>
228
);
229
}
230
```
231
232
### Correct CSS Loading
233
234
```jsx
235
// ✅ Correct - CSS through Next.js import system
236
import styles from './MyComponent.module.css';
237
import 'global-styles.css';
238
239
export default function MyComponent() {
240
return <div className={styles.container}>Content</div>;
241
}
242
```
243
244
### Script Rules Configuration
245
246
```javascript
247
// Focus on script management and security
248
module.exports = {
249
plugins: ['@next/next'],
250
rules: {
251
// Critical script placement rules as errors
252
'@next/next/inline-script-id': 'error',
253
'@next/next/no-script-component-in-head': 'error',
254
255
// Best practice rules as warnings
256
'@next/next/next-script-for-ga': 'warn',
257
'@next/next/no-before-interactive-script-outside-document': 'warn',
258
'@next/next/no-unwanted-polyfillio': 'warn',
259
'@next/next/no-css-tags': 'warn',
260
},
261
};
262
```
263
264
## Script Loading Strategies
265
266
### Available Strategies
267
- **beforeInteractive**: Load before page becomes interactive (only in _document.js)
268
- **afterInteractive**: Load after page becomes interactive
269
- **lazyOnload**: Load during browser idle time
270
- **worker**: Load in a web worker (experimental)
271
272
### Strategy Guidelines
273
- Use `beforeInteractive` for critical scripts that must load early
274
- Use `afterInteractive` for analytics and non-critical functionality
275
- Use `lazyOnload` for scripts that can be deferred
276
- Always specify a strategy explicitly
277
278
## Rule Categories
279
280
- **Security**: inline-script-id, no-unwanted-polyfillio
281
- **Performance**: next-script-for-ga, no-css-tags
282
- **Architecture**: no-before-interactive-script-outside-document, no-script-component-in-head
283
284
## Common Patterns
285
286
### Analytics Integration
287
- Use Next.js Script component with proper strategy
288
- Include required id attributes for inline scripts
289
- Place analytics scripts at page level, not in _document
290
291
### Critical Script Loading
292
- Place beforeInteractive scripts only in _document.js
293
- Use afterInteractive for most third-party scripts
294
- Avoid placing scripts inside Head components
295
296
### Asset Management
297
- Use Next.js CSS import system instead of link tags
298
- Leverage automatic optimization and bundling
299
- Maintain proper loading order and dependencies