Skip to content

Commit 2899ed3

Browse files
authored
Merge pull request #59 from webpack-contrib/feature/contenthash
add support for webpack's new contenthash support
2 parents 9b1bd63 + 7b56927 commit 2899ed3

19 files changed

+169
-24
lines changed

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
package-lock.json -diff
22
* text=auto
3-
bin/* eol=lf
3+
test/cases/* eol=lf
4+
bin/* eol=lf

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ module.exports = {
133133
<tbody>
134134
</table>
135135

136+
#### Long Term Caching
137+
138+
For long term caching use `filename: "[contenthash].css"`. Optionally add `[name]`.
139+
140+
136141
[npm]: https://img.shields.io/npm/v/mini-css-extract-plugin.svg
137142
[npm-url]: https://npmjs.com/package/mini-css-extract-plugin
138143

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: 48 additions & 3 deletions
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

@@ -57,7 +57,7 @@ class CssModule extends webpack.Module {
5757
nameForCondition() {
5858
const resource = this._identifier.split('!').pop();
5959
const idx = resource.indexOf('?');
60-
if (idx >= 0) return resource.substr(0, idx);
60+
if (idx >= 0) return resource.substring(0, idx);
6161
return resource;
6262
}
6363

@@ -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+
.substring(0, hashDigestLength);
164+
});
142165
const { mainTemplate } = compilation;
143166
mainTemplate.hooks.localVars.tap(
144167
pluginName,
@@ -178,13 +201,35 @@ class MiniCssExtractPlugin {
178201
const shortChunkHashMap = Object.create(null);
179202
for (const chunkId of Object.keys(chunkMaps.hash)) {
180203
if (typeof chunkMaps.hash[chunkId] === 'string') {
181-
shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr(0, length);
204+
shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substring(0, length);
182205
}
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+
].substring(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; }

0 commit comments

Comments
 (0)