Skip to content

Commit 7233cae

Browse files
committed
fix: 🐛 fix issue of loaders
1 parent ae08ce7 commit 7233cae

File tree

9 files changed

+84
-85
lines changed

9 files changed

+84
-85
lines changed

.changeset/fuzzy-feet-type.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperse/html-webpack-plugin-loader": patch
3+
---
4+
5+
fix issue of loaders

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
},
2222
".": {
2323
"types": "./dist/index.d.ts",
24+
"require": "./dist/index.cjs",
2425
"import": "./dist/index.js"
2526
},
2627
"./package.json": "./package.json"
@@ -61,15 +62,13 @@
6162
"@commitlint/config-conventional": "^19.8.1",
6263
"@hyperse/eslint-config-hyperse": "^1.4.5",
6364
"@hyperse/ts-node": "^1.0.3",
64-
"@types/loader-runner": "^2.2.8",
6565
"@types/node": "^24.0.1",
6666
"commitizen": "^4.3.1",
6767
"cz-conventional-changelog": "^3.3.0",
6868
"eslint": "^9.28.0",
6969
"html-webpack-plugin": "^5.6.3",
7070
"husky": "^9.1.7",
7171
"lint-staged": "^16.1.0",
72-
"loader-runner": "^4.3.0",
7372
"npm-run-all": "^4.1.5",
7473
"tsup": "^8.5.0",
7574
"typescript": "^5.8.3",

scripts/build.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ async function buildAll() {
1313
const externals = ['webpack'];
1414
const entries: Record<string, Omit<Options, 'entry'> & { entry: string }> = {
1515
'src/index.ts': {
16-
format: ['esm'],
16+
format: ['esm', 'cjs'],
1717
entry: 'index',
1818
dts: true,
1919
clean: true,
@@ -35,7 +35,8 @@ async function buildAll() {
3535
};
3636

3737
for (const [key, value] of Object.entries(entries)) {
38-
const { format, entry, dts, clean, outExtension } = value;
38+
const { format, entry, dts, clean, outExtension, external, noExternal } =
39+
value;
3940
await build({
4041
splitting: false,
4142
treeshake: true,
@@ -46,6 +47,8 @@ async function buildAll() {
4647
dts,
4748
clean,
4849
outExtension,
50+
external,
51+
noExternal,
4952
format: format as Format[],
5053
});
5154
}

src/loader/htmlLoader.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,51 @@ import { parseTemplate } from '../parser/parseTemplate.js';
33

44
// Define the loader options type
55
interface LoaderOptions {
6-
title?: string;
7-
favicon?: string;
8-
headMetaTags?: string[];
9-
headStyles?: string[];
10-
headScripts?: string[];
11-
headInlineScripts?: string[];
12-
bodyScripts?: string[];
13-
bodyInlineScripts?: string[];
6+
force?: boolean;
147
}
158

169
export default function htmlLoader(
1710
this: LoaderContext<LoaderOptions>,
1811
source: string
1912
): string {
2013
// Get and validate options
21-
const options = this.getOptions;
14+
const options = this.getOptions();
15+
const force = options.force || false;
2216

23-
// Skip .js files (unless it's explicitly enforced)
24-
if (!/\.html$/.test(this.resourcePath)) {
17+
const allLoadersButThisOne = this.loaders.filter(
18+
(loader) => loader.normal !== module.exports
19+
);
20+
21+
// This loader shouldn't kick in if there is any other loader (unless it's explicitly enforced)
22+
if (allLoadersButThisOne.length > 0 && !force) {
2523
return source;
2624
}
2725

28-
// Example transformation
29-
const transformedSource = parseTemplate(source);
26+
// Allow only one html-webpack-plugin loader to allow loader options in the webpack config
27+
const htmlWebpackPluginLoaders = this.loaders.filter(
28+
(loader) => loader.normal === module.exports
29+
);
3030

31-
// You can use this.emitFile to emit additional files
32-
// this.emitFile('output.txt', 'Some content');
31+
const lastHtmlWebpackPluginLoader =
32+
htmlWebpackPluginLoaders[htmlWebpackPluginLoaders.length - 1];
33+
if (this.loaders[this.loaderIndex] !== lastHtmlWebpackPluginLoader) {
34+
return source;
35+
}
3336

34-
// You can use this.callback for async operations
35-
// this.callback(null, transformedSource, sourceMap, meta);
37+
// Skip .js files (unless it's explicitly enforced)
38+
if (!/\.html$/.test(this.resourcePath)) {
39+
return source;
40+
}
3641

37-
// Return the transformed source
38-
return `export default ${JSON.stringify(transformedSource)}`;
42+
// Convert the source into a string that can be executed by vm.Script
43+
return [
44+
'const { TemplateParser } = eval("require")(' +
45+
JSON.stringify(require.resolve('../index.cjs')) +
46+
');',
47+
'const parseTemplate = ' + parseTemplate.toString() + ';',
48+
'const source = ' + JSON.stringify(source) + ';',
49+
'module.exports = (function(templateParams) { ',
50+
'return parseTemplate(source, templateParams || {});',
51+
'});',
52+
].join('');
3953
}

tests/fixtures/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
<meta name="apple-mobile-web-app-status-bar-style" content="black">
1515
<meta name="viewport"
1616
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover">
17+
<link rel="icon" href="<%= favicon %>">
18+
<title>
19+
<%= title %>
20+
</title>
21+
1722
</head>
1823

1924
<body>

tests/htmlLoader.test.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

tests/htmlPluginBasic.test.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import HtmlWebpackPlugin from 'html-webpack-plugin';
22
import { existsSync, rmSync } from 'node:fs';
33
import { join } from 'node:path';
4-
import { describe, it } from 'vitest';
54
import { getDirname, testWebpackPlugin } from './testUtils.js';
65

76
const fixtureCwd = getDirname(import.meta.url, './fixtures/basic');
87
const fixtureDist = join(fixtureCwd, 'dist');
8+
const loader = getDirname(import.meta.url, '../dist/loader/htmlLoader.cjs');
99

1010
describe('htmlPluginBasic', () => {
1111
beforeEach(() => {
@@ -15,18 +15,27 @@ describe('htmlPluginBasic', () => {
1515
});
1616

1717
it('should return the correct html', async () => {
18-
const result = await testWebpackPlugin({
19-
entry: join(fixtureCwd, './index.js'),
20-
output: {
21-
path: fixtureDist,
22-
filename: 'index_bundle.js',
18+
const result = await testWebpackPlugin(
19+
{
20+
entry: join(fixtureCwd, './index.js'),
21+
output: {
22+
path: fixtureDist,
23+
filename: 'index_bundle.js',
24+
},
25+
plugins: [
26+
new HtmlWebpackPlugin({
27+
inject: 'body',
28+
template: `${loader}!${join(fixtureCwd, '../index.html')}`,
29+
templateParameters: {
30+
title: 'default title',
31+
favicon: 'default favicon',
32+
},
33+
}),
34+
],
2335
},
24-
plugins: [
25-
new HtmlWebpackPlugin({
26-
template: join(fixtureCwd, '../index.html'),
27-
}),
28-
],
29-
});
30-
expect(result).toBe(true);
36+
fixtureDist
37+
);
38+
expect(result).toContain('<title>default title</title>');
39+
expect(result).toContain('<link rel="icon" href="default favicon">');
3140
});
3241
});

tests/testUtils.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,34 @@
1-
import { type RunLoaderOption, runLoaders } from 'loader-runner';
1+
import { readFileSync } from 'node:fs';
22
import { dirname, join } from 'node:path';
33
import { fileURLToPath } from 'node:url';
4-
import webpack from 'webpack';
4+
import type { Configuration } from 'webpack';
5+
import { webpack } from 'webpack';
56

67
export const getDirname = (url: string, ...paths: string[]) => {
78
return join(dirname(fileURLToPath(url)), ...paths);
89
};
910

10-
export const testLoader = (options: RunLoaderOption) => {
11-
return new Promise((resolve, reject) => {
12-
runLoaders(options, (err, result) => {
13-
if (err) {
14-
reject(err);
15-
return;
16-
}
17-
resolve(result);
18-
});
19-
});
20-
};
21-
22-
export const testWebpackPlugin = (webpackConfig: webpack.Configuration) => {
23-
return new Promise<webpack.Stats | undefined>((resolve, reject) => {
11+
export const testWebpackPlugin = (
12+
webpackConfig: Configuration,
13+
htmlDist: string
14+
) => {
15+
return new Promise<string>((resolve, reject) => {
2416
webpack(
2517
{
2618
...webpackConfig,
2719
mode: 'development',
2820
optimization: {
2921
minimize: false,
3022
},
23+
stats: 'verbose',
3124
},
32-
(err, stats) => {
25+
(err, _stats) => {
3326
if (err) {
3427
reject(err);
3528
return;
3629
}
37-
resolve(stats);
30+
const html = readFileSync(join(htmlDist, 'index.html'), 'utf-8');
31+
resolve(html);
3832
}
3933
);
4034
});

yarn.lock

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -865,15 +865,13 @@ __metadata:
865865
"@commitlint/config-conventional": "npm:^19.8.1"
866866
"@hyperse/eslint-config-hyperse": "npm:^1.4.5"
867867
"@hyperse/ts-node": "npm:^1.0.3"
868-
"@types/loader-runner": "npm:^2.2.8"
869868
"@types/node": "npm:^24.0.1"
870869
commitizen: "npm:^4.3.1"
871870
cz-conventional-changelog: "npm:^3.3.0"
872871
eslint: "npm:^9.28.0"
873872
html-webpack-plugin: "npm:^5.6.3"
874873
husky: "npm:^9.1.7"
875874
lint-staged: "npm:^16.1.0"
876-
loader-runner: "npm:^4.3.0"
877875
npm-run-all: "npm:^4.1.5"
878876
parse5: "npm:^7.3.0"
879877
tsup: "npm:^8.5.0"
@@ -1637,15 +1635,6 @@ __metadata:
16371635
languageName: node
16381636
linkType: hard
16391637

1640-
"@types/loader-runner@npm:^2.2.8":
1641-
version: 2.2.8
1642-
resolution: "@types/loader-runner@npm:2.2.8"
1643-
dependencies:
1644-
"@types/node": "npm:*"
1645-
checksum: 10/3a7d070bc36926620e752afe5bd49bc79b9c501f04935dc78e8aa0532618a350c7a773d29d8bfe939f5aae2551c322cb0e8ef65486ac78e3c3715b2f436d5765
1646-
languageName: node
1647-
linkType: hard
1648-
16491638
"@types/mdast@npm:^4.0.0":
16501639
version: 4.0.4
16511640
resolution: "@types/mdast@npm:4.0.4"
@@ -5803,7 +5792,7 @@ __metadata:
58035792
languageName: node
58045793
linkType: hard
58055794

5806-
"loader-runner@npm:^4.2.0, loader-runner@npm:^4.3.0":
5795+
"loader-runner@npm:^4.2.0":
58075796
version: 4.3.0
58085797
resolution: "loader-runner@npm:4.3.0"
58095798
checksum: 10/555ae002869c1e8942a0efd29a99b50a0ce6c3296efea95caf48f00d7f6f7f659203ed6613688b6181aa81dc76de3e65ece43094c6dffef3127fe1a84d973cd3

0 commit comments

Comments
 (0)