Skip to content

Commit e9a568a

Browse files
committed
fix: the same chunkId is overwritten after using mini-css-extract-plugin
1 parent 1008584 commit e9a568a

File tree

7 files changed

+84
-8
lines changed

7 files changed

+84
-8
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import("./style.module.css").then((module) => {
1+
import(/* webpackChunkName: "style" */ "./style.module.css").then((module) => {
22
console.log(module["default"] ? "ok" : "error");
33
});

examples/mini-css-extract-plugin/webpack.config.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@ const { SubresourceIntegrityPlugin } = require("webpack-subresource-integrity");
22
const HtmlWebpackPlugin = require("html-webpack-plugin");
33
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
44
const { RunInPuppeteerPlugin } = require("wsi-test-helper");
5+
const expect = require("expect");
6+
const fs = require("fs");
7+
const path = require("path");
58

69
module.exports = {
10+
mode: "none",
711
entry: {
812
index: "./index.js",
913
},
@@ -12,14 +16,33 @@ module.exports = {
1216
// Options similar to the same options in webpackOptions.output
1317
// both options are optional
1418
filename: "[name].css",
15-
chunkFilename: "[id].css",
19+
chunkFilename: "[name].css",
1620
}),
1721
new SubresourceIntegrityPlugin({
1822
hashFuncNames: ["sha256", "sha384"],
1923
enabled: true,
2024
}),
2125
new HtmlWebpackPlugin(),
2226
new RunInPuppeteerPlugin(),
27+
{
28+
apply: (compiler) => {
29+
compiler.hooks.done.tap("wsi-test", (stats) => {
30+
expect(stats.compilation.warnings).toEqual([]);
31+
expect(stats.compilation.errors).toEqual([]);
32+
const cssIntegrity = stats
33+
.toJson()
34+
.assets.find((asset) => asset.name === "style.css").integrity;
35+
const source = fs.readFileSync(
36+
path.join(__dirname, "./dist/runtime.js"),
37+
"utf-8"
38+
);
39+
const sriManifest = JSON.parse(
40+
source.match(/__webpack_require__.sriHashes = ({.+});/)?.[1] || "{}"
41+
);
42+
expect(sriManifest["style_css/mini-extract"]).toEqual(cssIntegrity);
43+
});
44+
},
45+
},
2346
],
2447
output: {
2548
crossOriginLoading: "anonymous",
@@ -44,4 +67,10 @@ module.exports = {
4467
},
4568
],
4669
},
70+
optimization: {
71+
chunkIds: "named",
72+
runtimeChunk: {
73+
name: "runtime",
74+
},
75+
},
4776
};

webpack-subresource-integrity/README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ default), the `integrity` attribute will be set automatically. The
5959
`output.crossOriginLoading` webpack option. There is nothing else to
6060
be done.
6161

62+
#### With MiniCssExtractPlugin
63+
64+
Currently, developers can only add integrity to link elements via the insert method.
65+
66+
```js
67+
new MiniCssExtractPlugin({
68+
insert: (link) => {
69+
link.integrity =
70+
__webpack_require__.sriHashes[chunkId + "_css/mini-extract"];
71+
document.head.appendChild(link);
72+
},
73+
})
74+
```
75+
6276
#### With HtmlWebpackPlugin({ inject: false })
6377

6478
When you use html-webpack-plugin with `inject: false`, you are
@@ -221,7 +235,7 @@ With Webpack and long-term caching this means using `[contenthash]` (with
221235
`[contenthash]` with `realContentHash` disabled, or using a different type of
222236
hash placeholder (such as `[chunkhash]`) provides weaker guarantees, which is
223237
why this plugin will output a warning in these cases. See [issue
224-
#162](https://github.com/waysact/webpack-subresource-integrity/issues/162)
238+
# 162](https://github.com/waysact/webpack-subresource-integrity/issues/162)
225239
for more information.
226240

227241
### Proxies
@@ -251,7 +265,7 @@ tags, but preloading with SRI doesn't work as expected in current
251265
Chrome versions. The resource will be loaded twice, defeating the
252266
purpose of preloading. This problem doesn't appear to exist in
253267
Firefox or Safari. See [issue
254-
#111](https://github.com/waysact/webpack-subresource-integrity/issues/111)
268+
# 111](https://github.com/waysact/webpack-subresource-integrity/issues/111)
255269
for more information.
256270

257271
### Browser support
@@ -275,7 +289,7 @@ using a tool such as [`http-server`](https://github.com/indexzero/http-server).
275289
### Safari 13 (and earlier versions) and Assets that Require Cookies
276290

277291
As detailed in [Webpack Issue
278-
#6972](https://github.com/webpack/webpack/issues/6972), the `crossOrigin`
292+
# 6972](https://github.com/webpack/webpack/issues/6972), the `crossOrigin`
279293
attribute can break loading of assets in Safari versions prior to 14 in certain
280294
edge cases due to a browser bug. Since SRI requires the `crossOrigin` attribute
281295
to be set, you may run into this case even when source URL is same-origin with

webpack-subresource-integrity/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,13 @@ export class SubresourceIntegrityPlugin {
169169
? plugin.getChildChunksToAddToChunkManifest(chunk)
170170
: findChunks(chunk);
171171
const includedChunks = chunk.getChunkMaps(false).hash;
172-
173172
if (Object.keys(includedChunks).length > 0) {
174173
return compilation.compiler.webpack.Template.asString([
175174
source,
176175
`${sriHashVariableReference} = ` +
177176
JSON.stringify(
178177
generateSriHashPlaceholders(
178+
compilation,
179179
Array.from(allChunks).filter(
180180
(depChunk) =>
181181
depChunk.id !== null &&
@@ -201,6 +201,7 @@ export class SubresourceIntegrityPlugin {
201201
chunk,
202202
new AddLazySriRuntimeModule(
203203
generateSriHashPlaceholders(
204+
compilation,
204205
childChunks,
205206
this.options.hashFuncNames
206207
),

webpack-subresource-integrity/src/plugin.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
tryGetSource,
3333
replaceInSource,
3434
usesAnyHash,
35+
normalizeChunkId,
3536
} from "./util";
3637
import { getChunkToManifestMap } from "./manifest";
3738
import { AssetIntegrity } from "./integrity";
@@ -176,7 +177,10 @@ export class Plugin {
176177

177178
if (childChunk.id !== null) {
178179
this.hashByPlaceholder.set(
179-
makePlaceholder(this.options.hashFuncNames, childChunk.id),
180+
makePlaceholder(
181+
this.options.hashFuncNames,
182+
normalizeChunkId(sourcePath, childChunk, this.compilation)
183+
),
180184
integrity
181185
);
182186
}

webpack-subresource-integrity/src/util.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export type ChunkGroup = ReturnType<Compilation["addChunkInGroup"]>;
1414

1515
export const sriHashVariableReference = "__webpack_require__.sriHashes";
1616

17+
export const miniCssExtractType = "css/mini-extract";
18+
1719
export function assert(value: unknown, message: string): asserts value {
1820
if (!value) {
1921
throw new Error(message);
@@ -113,11 +115,21 @@ export function notNil<TValue>(
113115
}
114116

115117
export function generateSriHashPlaceholders(
118+
compilation: Compilation,
116119
chunks: Iterable<Chunk>,
117120
hashFuncNames: [string, ...string[]]
118121
): Record<string, string> {
119122
return Array.from(chunks).reduce((sriHashes, depChunk: Chunk) => {
120123
if (depChunk.id) {
124+
const hasMiniCssExtractFile = compilation.chunkGraph
125+
.getChunkModules(depChunk)
126+
.find((module) => module.type === miniCssExtractType);
127+
if (hasMiniCssExtractFile) {
128+
sriHashes[`${depChunk.id}_${miniCssExtractType}`] = makePlaceholder(
129+
hashFuncNames,
130+
`${depChunk.id}_${miniCssExtractType}`
131+
);
132+
}
121133
sriHashes[depChunk.id] = makePlaceholder(hashFuncNames, depChunk.id);
122134
}
123135
return sriHashes;
@@ -291,3 +303,19 @@ export function hasOwnProperty<X extends object, Y extends PropertyKey>(
291303
): obj is X & Record<Y, unknown> {
292304
return Object.prototype.hasOwnProperty.call(obj, prop);
293305
}
306+
307+
export const normalizeChunkId = (
308+
sourcePath: string,
309+
chunk: Chunk,
310+
compilation: Compilation
311+
) => {
312+
if (
313+
sourcePath.endsWith(".css") &&
314+
compilation.chunkGraph
315+
.getChunkModules(chunk)
316+
.find((module) => module.type === miniCssExtractType)
317+
) {
318+
return `${chunk.id}_${miniCssExtractType}`;
319+
}
320+
return chunk.id as string | number;
321+
};

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10073,4 +10073,4 @@ __metadata:
1007310073
z-schema: bin/z-schema
1007410074
checksum: 8a1d66817ae4384dc3f63311f0cccaadd95cc9640eaade5fd3fbf91aa80d6bb82fb95d9b9171fa82ac371a0155b32b7f5f77bbe84dabaca611b66f74c628f0b8
1007510075
languageName: node
10076-
linkType: hard
10076+
linkType: hard

0 commit comments

Comments
 (0)