Skip to content

Commit 726b3a4

Browse files
committed
add support for webpack's new contenthash support
1 parent 86adece commit 726b3a4

18 files changed

+165
-21
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ When inlining CSS `data-href` must be used.
9292
<tbody>
9393
</table>
9494

95+
#### Long Term Caching
96+
97+
For long term caching use `filename: "[contenthash].css"`. Optionally add `[name]`.
98+
99+
95100
[npm]: https://img.shields.io/npm/v/mini-css-extract-plugin.svg
96101
[npm-url]: https://npmjs.com/package/mini-css-extract-plugin
97102

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"nsp": "^3.1.0",
4545
"pre-commit": "^1.2.2",
4646
"standard-version": "^4.3.0",
47-
"webpack": "^4.1.0",
47+
"webpack": "^4.3.0",
4848
"webpack-cli": "^2.0.13",
4949
"webpack-defaults": "^1.6.0",
5050
"webpack-dev-server": "^3.1.1"
@@ -56,7 +56,7 @@
5656
"node": ">= 6.11.5"
5757
},
5858
"peerDependencies": {
59-
"webpack": "^4.1.0"
59+
"webpack": "^4.3.0"
6060
},
6161
"pre-commit": "lint-staged",
6262
"lint-staged": {

src/index.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import webpack from 'webpack';
44
import sources from 'webpack-sources';
55

66
const { ConcatSource, SourceMapSource, OriginalSource } = sources;
7-
const { Template } = webpack;
7+
const { Template, util: { createHash } } = webpack;
88

99
const NS = path.dirname(fs.realpathSync(__filename));
1010

@@ -66,6 +66,13 @@ class CssModule extends webpack.Module {
6666
this.buildMeta = {};
6767
callback();
6868
}
69+
70+
updateHash(hash) {
71+
super.updateHash(hash);
72+
hash.update(this.content);
73+
hash.update(this.media || '');
74+
hash.update(JSON.stringify(this.sourceMap || ''));
75+
}
6976
}
7077

7178
class CssModuleFactory {
@@ -121,6 +128,7 @@ class MiniCssExtractPlugin {
121128
filenameTemplate: this.options.filename,
122129
pathOptions: {
123130
chunk,
131+
contentHashType: NS,
124132
},
125133
identifier: `mini-css-extract-plugin.${chunk.id}`,
126134
});
@@ -134,11 +142,26 @@ class MiniCssExtractPlugin {
134142
filenameTemplate: this.options.chunkFilename,
135143
pathOptions: {
136144
chunk,
145+
contentHashType: NS,
137146
},
138147
identifier: `mini-css-extract-plugin.${chunk.id}`,
139148
});
140149
}
141150
});
151+
compilation.hooks.contentHash.tap(pluginName, (chunk) => {
152+
const { outputOptions } = compilation;
153+
const { hashFunction, hashDigest, hashDigestLength } = outputOptions;
154+
const hash = createHash(hashFunction);
155+
for (const m of chunk.modulesIterable) {
156+
if (m.type === NS) {
157+
m.updateHash(hash);
158+
}
159+
}
160+
const { contentHash } = chunk;
161+
contentHash[NS] = hash
162+
.digest(hashDigest)
163+
.substr(0, hashDigestLength);
164+
});
142165
const { mainTemplate } = compilation;
143166
mainTemplate.hooks.localVars.tap(
144167
pluginName,
@@ -183,8 +206,30 @@ class MiniCssExtractPlugin {
183206
}
184207
return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`;
185208
},
209+
contentHash: {
210+
[NS]: `" + ${JSON.stringify(
211+
chunkMaps.contentHash[NS],
212+
)}[chunkId] + "`,
213+
},
214+
contentHashWithLength: {
215+
[NS]: (length) => {
216+
const shortContentHashMap = {};
217+
const contentHash = chunkMaps.contentHash[NS];
218+
for (const chunkId of Object.keys(contentHash)) {
219+
if (typeof contentHash[chunkId] === 'string') {
220+
shortContentHashMap[chunkId] = contentHash[
221+
chunkId
222+
].substr(0, length);
223+
}
224+
}
225+
return `" + ${JSON.stringify(
226+
shortContentHashMap,
227+
)}[chunkId] + "`;
228+
},
229+
},
186230
name: `" + (${JSON.stringify(chunkMaps.name)}[chunkId]||chunkId) + "`,
187231
},
232+
contentHashType: NS,
188233
},
189234
);
190235
return Template.asString([

test/TestCases.test.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ describe('TestCases', () => {
1313
const outputDirectoryForCase = path.resolve(outputDirectory, directory);
1414
// eslint-disable-next-line import/no-dynamic-require, global-require
1515
const webpackConfig = require(path.resolve(directoryForCase, 'webpack.config.js'));
16-
webpack(Object.assign({
17-
mode: 'none',
18-
context: directoryForCase,
19-
output: {
20-
path: outputDirectoryForCase,
21-
},
22-
}, webpackConfig), (err, stats) => {
16+
for (const config of [].concat(webpackConfig)) {
17+
Object.assign(config, {
18+
mode: 'none',
19+
context: directoryForCase,
20+
output: Object.assign({
21+
path: outputDirectoryForCase,
22+
}, config.output),
23+
}, config);
24+
}
25+
webpack(webpackConfig, (err, stats) => {
2326
if (err) {
2427
done(err);
2528
return;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
body { background: red; }
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
body { background: green; }
2+

test/cases/contenthash/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './style.css';

test/cases/contenthash/style1.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
body { background: red; }

test/cases/contenthash/style2.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
body { background: green; }
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const Self = require('../../../');
2+
3+
module.exports = [1, 2].map(n => ({
4+
entry: './index.js',
5+
module: {
6+
rules: [
7+
{
8+
test: /\.css$/,
9+
use: [
10+
Self.loader,
11+
'css-loader',
12+
],
13+
},
14+
],
15+
},
16+
output: {
17+
filename: `${n}.[name].js`
18+
},
19+
resolve: {
20+
alias: {
21+
'./style.css': `./style${n}.css`
22+
}
23+
},
24+
plugins: [
25+
new Self({
26+
filename: `${n}.[name].[contenthash].css`,
27+
}),
28+
],
29+
}));

0 commit comments

Comments
 (0)