0
# Static Site Generator Webpack Plugin
1
2
Static Site Generator Webpack Plugin is a minimal, unopinionated static site generator powered by webpack. It enables static site generation by executing a custom render function at build time to generate HTML files for specified paths, supporting both manual path specification and automatic site crawling.
3
4
## Package Information
5
6
- **Package Name**: static-site-generator-webpack-plugin
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install --save-dev static-site-generator-webpack-plugin`
10
11
## Core Imports
12
13
```javascript
14
const StaticSiteGeneratorPlugin = require('static-site-generator-webpack-plugin');
15
```
16
17
For ES modules:
18
19
```javascript
20
import StaticSiteGeneratorPlugin from 'static-site-generator-webpack-plugin';
21
```
22
23
## Basic Usage
24
25
```javascript
26
// webpack.config.js
27
const StaticSiteGeneratorPlugin = require('static-site-generator-webpack-plugin');
28
29
module.exports = {
30
entry: './index.js',
31
32
output: {
33
filename: 'index.js',
34
path: 'dist',
35
libraryTarget: 'umd' // Required for Node.js execution
36
},
37
38
plugins: [
39
new StaticSiteGeneratorPlugin({
40
paths: ['/hello/', '/world/'],
41
locals: {
42
greet: 'Hello'
43
}
44
})
45
]
46
};
47
48
// index.js - render function
49
module.exports = function render(locals) {
50
return '<html>' + locals.greet + ' from ' + locals.path + '</html>';
51
};
52
53
// ES module default export pattern
54
export default function render(locals) {
55
return `<html>${locals.greet} from ${locals.path}</html>`;
56
};
57
```
58
59
## Architecture
60
61
The plugin integrates into webpack's compilation process through several key components:
62
63
- **Plugin Constructor**: Configures paths, locals, globals, and crawling behavior
64
- **Webpack Integration**: Hooks into webpack's `thisCompilation` and `optimizeAssets` phases
65
- **Render Function Execution**: Evaluates the compiled entry file as a render function
66
- **Asset Generation**: Creates HTML assets in webpack's output for each rendered path
67
- **Crawling Engine**: Optionally discovers additional paths by parsing HTML for relative links
68
69
## Capabilities
70
71
### Plugin Configuration
72
73
Creates a webpack plugin instance with configuration options for static site generation.
74
75
```javascript { .api }
76
/**
77
* Static Site Generator Webpack Plugin constructor
78
* @param {Object} options - Configuration options
79
*/
80
function StaticSiteGeneratorWebpackPlugin(options);
81
82
interface StaticSiteGeneratorOptions {
83
/** Webpack entry chunk name (defaults to first chunk if not specified) */
84
entry?: string;
85
/** Array of paths OR single path to render (defaults to ['/'] if not provided) */
86
paths?: string[] | string;
87
/** Custom properties merged into locals object passed to render function */
88
locals?: object;
89
/** Object that exists in global scope when executing render function */
90
globals?: object;
91
/** Enables automatic crawling of relative links and iframes */
92
crawl?: boolean;
93
}
94
```
95
96
**Usage Examples:**
97
98
```javascript
99
// Basic configuration with multiple paths
100
new StaticSiteGeneratorPlugin({
101
paths: ['/about/', '/contact/', '/blog/'],
102
locals: {
103
siteName: 'My Website',
104
version: '1.0.0'
105
}
106
});
107
108
// Single path configuration (automatically converted to array)
109
new StaticSiteGeneratorPlugin({
110
paths: '/', // Equivalent to paths: ['/']
111
locals: { data: 'value' }
112
});
113
114
// Crawling mode
115
new StaticSiteGeneratorPlugin({
116
crawl: true,
117
paths: ['/'], // Entry point for crawling
118
locals: { navigation: menuData }
119
});
120
121
// Custom entry point and globals
122
new StaticSiteGeneratorPlugin({
123
entry: 'main',
124
paths: ['/'],
125
globals: { window: {} }, // For browser-dependent libraries
126
locals: { config: appConfig }
127
});
128
```
129
130
### Render Function Requirements
131
132
The entry file must export a render function that accepts locals and returns HTML. The plugin supports three execution patterns:
133
134
```javascript { .api }
135
/** Synchronous render function */
136
function render(locals: RenderLocals): string;
137
138
/** Callback-based render function */
139
function render(locals: RenderLocals, callback: (error: Error | null, html: string) => void): void;
140
141
/** Promise-based render function */
142
function render(locals: RenderLocals): Promise<string>;
143
144
/** Multi-path render function returning object with path-to-HTML mapping */
145
function render(locals: RenderLocals): string | Promise<string> | { [path: string]: string };
146
147
interface RenderLocals {
148
/** The path currently being rendered */
149
path: string;
150
/** Object containing all webpack assets by chunk name */
151
assets: { [chunkName: string]: string };
152
/** Advanced webpack compilation statistics */
153
webpackStats: object;
154
/** Custom properties from plugin configuration */
155
[key: string]: any;
156
}
157
```
158
159
**Usage Examples:**
160
161
```javascript
162
// Synchronous rendering
163
module.exports = function render(locals) {
164
return `<html><body><h1>Welcome to ${locals.path}</h1></body></html>`;
165
};
166
167
// Async rendering with callbacks
168
module.exports = function render(locals, callback) {
169
setTimeout(() => {
170
const html = generatePage(locals.path, locals.data);
171
callback(null, html);
172
}, 100);
173
};
174
175
// Promise-based rendering
176
module.exports = function render(locals) {
177
return fetchPageData(locals.path)
178
.then(data => renderTemplate(data))
179
.then(html => html);
180
};
181
182
// Multi-path rendering
183
module.exports = function render(locals) {
184
return {
185
'/': '<html>Home Page</html>',
186
'/about': '<html>About Page</html>',
187
'/contact': '<html>Contact Page</html>'
188
};
189
};
190
191
// Using assets in render function
192
module.exports = function render(locals) {
193
const jsFiles = Object.values(locals.assets).filter(file => file.endsWith('.js'));
194
const cssFiles = Object.values(locals.assets).filter(file => file.endsWith('.css'));
195
196
return `
197
<html>
198
<head>
199
${cssFiles.map(css => `<link rel="stylesheet" href="${css}">`).join('\\n')}
200
</head>
201
<body>
202
<h1>Page: ${locals.path}</h1>
203
${jsFiles.map(js => `<script src="${js}"></script>`).join('\\n')}
204
</body>
205
</html>
206
`;
207
};
208
209
// Note: Asset paths in locals.assets automatically include webpack's
210
// output.publicPath if configured, so no manual path resolution needed
211
```
212
213
### Crawling Mode
214
215
Automatic discovery of additional paths by parsing HTML for relative links and iframe sources.
216
217
When `crawl: true` is enabled, the plugin:
218
1. Renders the initial paths specified in configuration
219
2. Parses generated HTML for `<a href="...">` and `<iframe src="...">` tags
220
3. Extracts relative URLs (excluding external links and protocol-relative URLs)
221
4. Recursively renders discovered paths until no new paths are found
222
223
**Crawling Rules:**
224
- Only follows relative paths (not absolute URLs or external links)
225
- Converts `/path` to `/path/index.html` if no file extension
226
- Ignores protocol-relative URLs (`//example.com`)
227
- Ignores URLs with protocols (`http://`, `https://`, `ftp://`)
228
- Processes both root-relative (`/about`) and document-relative (`../contact`) links
229
230
```javascript
231
// Enable crawling with entry points
232
new StaticSiteGeneratorPlugin({
233
crawl: true,
234
paths: ['/', '/blog/'], // Multiple crawl entry points
235
locals: { siteData: data }
236
});
237
```
238
239
### Custom File Names
240
241
Generate custom file names by providing paths ending in `.html`.
242
243
```javascript { .api }
244
// Configuration for custom file names
245
new StaticSiteGeneratorPlugin({
246
paths: [
247
'/index.html',
248
'/news.html',
249
'/about.html'
250
]
251
});
252
```
253
254
**Note:** Custom file names may break compatibility with client-side routing if using frameworks like React Router.
255
256
### Legacy Constructor Arguments
257
258
Support for legacy constructor signature with positional arguments.
259
260
```javascript { .api }
261
/**
262
* Legacy constructor signature (deprecated)
263
* @param {string} entry - Entry chunk name
264
* @param {string[]} paths - Paths to render
265
* @param {object} locals - Local variables
266
* @param {object} globals - Global variables
267
*/
268
function StaticSiteGeneratorWebpackPlugin(entry, paths, locals, globals);
269
```
270
271
**Usage Example:**
272
273
```javascript
274
// Legacy usage (deprecated)
275
new StaticSiteGeneratorPlugin(
276
'main', // entry
277
['/'], // paths
278
{ data: 'value' }, // locals
279
{ window: {} } // globals
280
);
281
```
282
283
## Error Handling
284
285
The plugin handles several error conditions:
286
287
- **Missing Entry File**: Throws error if specified entry chunk is not found in webpack assets
288
- **Invalid Render Function**: Throws error if entry file export is not a function
289
- **Render Function Errors**: Captures render function exceptions and adds them to webpack's compilation errors
290
- **Asset Generation Errors**: Handles errors during HTML asset creation
291
292
Common error messages:
293
- `Source file not found: "entryName"` - Entry chunk not found in webpack output
294
- `Export from "entryName" must be a function that returns an HTML string. Is output.libraryTarget in the configuration set to "umd"?` - Entry file doesn't export a function or webpack output configuration is incorrect
295
- Render function stack traces are preserved in compilation.errors
296
297
## Webpack Integration Requirements
298
299
- **Output Configuration**: Must set `output.libraryTarget` to `'umd'` or `'commonjs'` for Node.js execution
300
- **Compilation Phase**: Plugin executes during webpack's `optimize-assets` phase
301
- **Asset Generation**: Creates new assets in webpack's compilation.assets object
302
- **Compatibility**: Supports both webpack 3.x/4.x (legacy plugin API) and webpack 5.x (hooks API) with automatic detection
303
304
```javascript
305
// Required webpack configuration
306
module.exports = {
307
output: {
308
libraryTarget: 'umd' // Essential for Node.js execution
309
},
310
plugins: [
311
new StaticSiteGeneratorPlugin(options)
312
]
313
};
314
```