Skip to content

Commit 0b99d6e

Browse files
committed
chore: 🤖 update docs & unitest
1 parent cefd73a commit 0b99d6e

File tree

4 files changed

+237
-1
lines changed

4 files changed

+237
-1
lines changed

README.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,188 @@ interface TemplateOptions {
229229
}
230230
```
231231

232+
## Webpack Loader Integration with html-webpack-plugin
233+
234+
This package provides seamless integration with webpack through a custom loader. The loader works in conjunction with `html-webpack-plugin` to modify HTML templates during the build process.
235+
236+
### Basic Setup
237+
238+
First, ensure you have both `html-webpack-plugin` and this package installed:
239+
240+
```bash
241+
npm install --save-dev html-webpack-plugin @hyperse/html-webpack-plugin-loader
242+
```
243+
244+
### Webpack Configuration
245+
246+
Add the loader to your webpack configuration file (e.g., `webpack.config.js` or `webpack.config.ts`):
247+
248+
```javascript
249+
const HtmlWebpackPlugin = require('html-webpack-plugin');
250+
const path = require('path');
251+
const loader = require.resolve('@hyperse/html-webpack-plugin-loader/loader');
252+
253+
module.exports = {
254+
// ... other webpack config
255+
plugins: [
256+
new HtmlWebpackPlugin({
257+
template: `${loader}!/xxx/src/index.html`,
258+
templateParameters: {
259+
// Template options (same as TemplateOptions interface)
260+
title: 'My Webpack App',
261+
favicon: {
262+
href: '/favicon.ico',
263+
rel: 'icon',
264+
attributes: {
265+
type: 'image/x-icon',
266+
},
267+
},
268+
headMetaTags: [
269+
'<meta name="viewport" content="width=device-width, initial-scale=1.0">',
270+
'<meta name="description" content="My webpack application">',
271+
],
272+
headStyles: [
273+
{
274+
id: 'main-css',
275+
href: '/styles/main.css',
276+
position: 'end',
277+
},
278+
],
279+
bodyScripts: [
280+
{
281+
id: 'app-js',
282+
src: '/app.js',
283+
position: 'end',
284+
type: 'module',
285+
},
286+
],
287+
},
288+
}),
289+
],
290+
};
291+
```
292+
293+
### Usage with TypeScript
294+
295+
If you're using TypeScript, you can import the types for better type checking:
296+
297+
```typescript
298+
import type { TemplateOptions } from '@hyperse/html-webpack-plugin-loader';
299+
import HtmlWebpackPlugin from 'html-webpack-plugin';
300+
import path from 'path';
301+
const loader = require.resolve('@hyperse/html-webpack-plugin-loader/loader');
302+
303+
const templateParameters: TemplateOptions = {
304+
title: 'My TypeScript Webpack App',
305+
// ... other template options
306+
};
307+
308+
const config = {
309+
plugins: [
310+
new HtmlWebpackPlugin({
311+
template: `$loader}!/xxx/src/index.html`,
312+
templateParameters,
313+
}),
314+
],
315+
};
316+
317+
export default config;
318+
```
319+
320+
### Advanced Usage
321+
322+
#### Dynamic Template Parameters
323+
324+
You can dynamically generate template parameters based on your environment or other conditions:
325+
326+
```javascript
327+
const getTemplateParameters = (env) => ({
328+
title: env.production ? 'Production App' : 'Development App',
329+
headMetaTags: [
330+
`<meta name="environment" content="${env.production ? 'production' : 'development'}">`,
331+
],
332+
// ... other options
333+
});
334+
const loader = require.resolve('@hyperse/html-webpack-plugin-loader/loader');
335+
336+
module.exports = (env) => ({
337+
// ... other webpack config
338+
plugins: [
339+
new HtmlWebpackPlugin({
340+
template: `${loader}!/xxx/src/index.html`,
341+
templateParameters: getTemplateParameters(env),
342+
}),
343+
],
344+
});
345+
```
346+
347+
#### Multiple HTML Templates
348+
349+
You can use different template parameters for different HTML files:
350+
351+
```javascript
352+
const loader = require.resolve('@hyperse/html-webpack-plugin-loader/loader');
353+
354+
module.exports = {
355+
// ... other webpack config
356+
plugins: [
357+
new HtmlWebpackPlugin({
358+
template: `${loader}!/xxx/src/index.html`,
359+
filename: 'index.html',
360+
chunks: ['main'],
361+
templateParameters: {
362+
title: 'Main Application',
363+
// ... main app options
364+
},
365+
}),
366+
new HtmlWebpackPlugin({
367+
template: `${loader}!/xxx/src/index.html`,
368+
filename: 'admin.html',
369+
chunks: ['admin'],
370+
templateParameters: {
371+
title: 'Admin Dashboard',
372+
// ... admin-specific options
373+
},
374+
}),
375+
],
376+
};
377+
```
378+
379+
### Loader Options
380+
381+
The loader accepts only one option:
382+
383+
- `force` (boolean, optional): When set to `true`, forces template processing even if no template parameters are provided. Default is `false`.
384+
385+
### Best Practices
386+
387+
1. **Template Organization**:
388+
389+
- Keep your HTML templates in a dedicated directory (e.g., `src/templates/`)
390+
- Use consistent naming conventions for your template files
391+
392+
2. **Environment-specific Configuration**:
393+
394+
- Use webpack's environment configuration to manage different settings for development and production
395+
- Consider using environment variables for sensitive or environment-specific values
396+
397+
3. **Performance Optimization**:
398+
399+
- Use `position: 'end'` for non-critical scripts and styles
400+
- Use `position: 'beginning'` for critical resources
401+
- Consider using `order` property to control the loading sequence
402+
403+
4. **Security**:
404+
405+
- Always use `integrity` checks for external resources when possible
406+
- Use `nonce` for inline scripts when implementing CSP
407+
- Set appropriate `crossOrigin` attributes for external resources
408+
409+
5. **Maintenance**:
410+
- Keep template parameters in a separate configuration file for better maintainability
411+
- Use TypeScript for better type safety and IDE support
412+
- Document your template parameters for team reference
413+
232414
## Contributing
233415

234416
Contributions are welcome! Please read our [contributing guidelines](https://github.com/hyperse-io/.github/blob/main/CONTRIBUTING.md) before submitting pull requests.

tests/fixtures/loader/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
3+
module.exports = 'common';

tests/htmlPluginBasic.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ describe('htmlPluginBasic', () => {
2828
template: `${loader}!${join(fixtureCwd, '../index.html')}`,
2929
templateParameters: {
3030
title: 'default title',
31-
favicon: 'default favicon',
31+
favicon: {
32+
href: 'default favicon',
33+
rel: 'icon',
34+
attributes: {},
35+
},
3236
},
3337
}),
3438
],

tests/htmlPluginLoader.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import HtmlWebpackPlugin from 'html-webpack-plugin';
2+
import { existsSync, rmSync } from 'node:fs';
3+
import { join } from 'node:path';
4+
import { getDirname, testWebpackPlugin } from './testUtils.js';
5+
6+
const fixtureCwd = getDirname(import.meta.url, './fixtures/loader');
7+
const fixtureDist = join(fixtureCwd, 'dist');
8+
9+
describe('htmlPluginLoader', () => {
10+
beforeEach(() => {
11+
if (existsSync(fixtureDist)) {
12+
rmSync(fixtureDist, { recursive: true });
13+
}
14+
});
15+
16+
it('should return the correct html with webpack loader', async () => {
17+
const loader = require.resolve(
18+
'@hyperse/html-webpack-plugin-loader/loader'
19+
);
20+
const result = await testWebpackPlugin(
21+
{
22+
entry: join(fixtureCwd, './index.js'),
23+
output: {
24+
path: fixtureDist,
25+
filename: 'index_bundle.js',
26+
},
27+
plugins: [
28+
new HtmlWebpackPlugin({
29+
inject: 'body',
30+
template: `${loader}!${join(fixtureCwd, '../index.html')}`,
31+
templateParameters: {
32+
title: 'default title',
33+
favicon: {
34+
href: 'default favicon',
35+
rel: 'icon',
36+
attributes: {},
37+
},
38+
},
39+
}),
40+
],
41+
},
42+
fixtureDist
43+
);
44+
expect(result).toContain('<title>default title</title>');
45+
expect(result).toContain('<link rel="icon" href="default favicon">');
46+
});
47+
});

0 commit comments

Comments
 (0)