Skip to content

Commit e3dc0f0

Browse files
committed
Replace assets-webpack-plugin dependency by an internal plugin, to generate entrypoints.json file
1 parent 10e9a96 commit e3dc0f0

File tree

6 files changed

+141
-87
lines changed

6 files changed

+141
-87
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ yarn add webpack-dev-server --dev
8989
pnpm install webpack-dev-server --save-dev
9090
```
9191

92+
* #1342 Replace [`assets-webpack-plugin`](https://github.com/ztoben/assets-webpack-plugin) dependency by an internal plugin, to generate `entrypoints.json` file (@Kocal)
93+
9294
## 4.7.0
9395

9496
### Features

lib/plugins/entry-files-manifest.js

Lines changed: 6 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -14,75 +14,7 @@
1414
*/
1515

1616
const PluginPriorities = require('./plugin-priorities');
17-
const copyEntryTmpName = require('../utils/copyEntryTmpName');
18-
const AssetsPlugin = require('assets-webpack-plugin');
19-
const fs = require('fs');
20-
const path = require('path');
21-
const crypto = require('crypto');
22-
23-
function processOutput(webpackConfig) {
24-
return (assets) => {
25-
// Remove temporary entry added by the copyFiles feature
26-
delete assets[copyEntryTmpName];
27-
28-
// with --watch or dev-server, subsequent calls will include
29-
// the original assets (so, assets.entrypoints) + the new
30-
// assets (which will have their original structure). We
31-
// delete the entrypoints key, and then process the new assets
32-
// like normal below. The same reasoning applies to the
33-
// integrity key.
34-
delete assets.entrypoints;
35-
delete assets.integrity;
36-
37-
// This will iterate over all the entry points and convert the
38-
// one file entries into an array of one entry since that was how the entry point file was before this change.
39-
const integrity = {};
40-
const integrityAlgorithms = webpackConfig.integrityAlgorithms;
41-
const publicPath = webpackConfig.getRealPublicPath();
42-
43-
for (const asset in assets) {
44-
for (const fileType in assets[asset]) {
45-
if (!Array.isArray(assets[asset][fileType])) {
46-
assets[asset][fileType] = [assets[asset][fileType]];
47-
}
48-
49-
if (integrityAlgorithms.length) {
50-
for (const file of assets[asset][fileType]) {
51-
if (file in integrity) {
52-
continue;
53-
}
54-
55-
const filePath = path.resolve(
56-
webpackConfig.outputPath,
57-
file.replace(publicPath, '')
58-
);
59-
60-
if (fs.existsSync(filePath)) {
61-
const fileHashes = [];
62-
63-
for (const algorithm of webpackConfig.integrityAlgorithms) {
64-
const hash = crypto.createHash(algorithm);
65-
const fileContent = fs.readFileSync(filePath, 'utf8');
66-
hash.update(fileContent, 'utf8');
67-
68-
fileHashes.push(`${algorithm}-${hash.digest('base64')}`);
69-
}
70-
71-
integrity[file] = fileHashes.join(' ');
72-
}
73-
}
74-
}
75-
}
76-
}
77-
78-
const manifestContent = { entrypoints: assets };
79-
if (integrityAlgorithms.length) {
80-
manifestContent.integrity = integrity;
81-
}
82-
83-
return JSON.stringify(manifestContent, null, 2);
84-
};
85-
}
17+
const { EntryPointsPlugin } = require('../webpack/entry-points-plugin');
8618

8719
/**
8820
* @param {Array} plugins
@@ -91,13 +23,11 @@ function processOutput(webpackConfig) {
9123
*/
9224
module.exports = function(plugins, webpackConfig) {
9325
plugins.push({
94-
plugin: new AssetsPlugin({
95-
path: webpackConfig.outputPath,
96-
filename: 'entrypoints.json',
97-
includeAllFileTypes: true,
98-
entrypoints: true,
99-
processOutput: processOutput(webpackConfig)
26+
plugin: new EntryPointsPlugin({
27+
publicPath: webpackConfig.getRealPublicPath(),
28+
outputPath: webpackConfig.outputPath,
29+
integrityAlgorithms: webpackConfig.integrityAlgorithms
10030
}),
101-
priority: PluginPriorities.AssetsPlugin
31+
priority: PluginPriorities.EntryPointsPlugin
10232
});
10333
};

lib/plugins/plugin-priorities.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ module.exports = {
2121
FriendlyErrorsWebpackPlugin: 40,
2222
AssetOutputDisplayPlugin: 30,
2323
ForkTsCheckerWebpackPlugin: 10,
24-
AssetsPlugin: -10,
24+
EntryPointsPlugin: -10,
2525
};

lib/webpack/entry-points-plugin.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* This file is part of the Symfony Webpack Encore package.
3+
*
4+
* (c) Fabien Potencier <fabien@symfony.com>
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*/
9+
10+
'use strict';
11+
12+
const fs = require('fs');
13+
const path = require('path');
14+
const crypto = require('crypto');
15+
const copyEntryTmpName = require('../utils/copyEntryTmpName');
16+
17+
/**
18+
* Return the file extension from a filename, without the leading dot and without the query string (if any).
19+
*
20+
* @param {string} filename
21+
* @returns {string}
22+
*/
23+
function getFileExtension(filename) {
24+
return path.extname(filename).slice(1).split('?')[0];
25+
}
26+
27+
class EntryPointsPlugin {
28+
/**
29+
* @param {String} publicPath The public path of the assets, from where they are served
30+
* @param {String} outputPath The output path of the assets, from where they are saved
31+
* @param {Array<String>} integrityAlgorithms The algorithms to use for the integrity hash
32+
*/
33+
constructor({
34+
publicPath,
35+
outputPath,
36+
integrityAlgorithms
37+
}) {
38+
this.publicPath = publicPath;
39+
this.outputPath = outputPath;
40+
this.integrityAlgorithms = integrityAlgorithms;
41+
}
42+
43+
apply(compiler) {
44+
compiler.hooks.afterEmit.tapAsync({ name: 'EntryPointsPlugin' }, (compilation, callback) => {
45+
const manifest = {
46+
entrypoints: {},
47+
};
48+
49+
const stats = compilation.getStats().toJson({
50+
assets: true,
51+
moduleAssets: true,
52+
relatedAssets: false,
53+
chunkGroupAuxiliary: false,
54+
chunks: false,
55+
modules: false,
56+
timings: false,
57+
logging: false,
58+
errorDetails: false,
59+
});
60+
61+
for (const [entryName, entry] of Object.entries(stats.entrypoints)) {
62+
// We don't want to include the temporary entry in the manifest
63+
if (entryName === copyEntryTmpName) {
64+
continue;
65+
}
66+
67+
manifest.entrypoints[entryName] = {};
68+
69+
for (const asset of entry.assets) {
70+
// We don't want to include hot-update files in the manifest
71+
if (asset.name.includes('.hot-update.')) {
72+
continue;
73+
}
74+
75+
const fileExtension = getFileExtension(asset.name);
76+
const assetPath = this.publicPath.slice(-1) === '/'
77+
? `${this.publicPath}${asset.name}`
78+
: `${this.publicPath}/${asset.name}`;
79+
80+
if (!(fileExtension in manifest.entrypoints[entryName])) {
81+
manifest.entrypoints[entryName][fileExtension] = [];
82+
}
83+
84+
manifest.entrypoints[entryName][fileExtension].push(assetPath);
85+
}
86+
}
87+
88+
if (this.integrityAlgorithms.length > 0) {
89+
manifest.integrity = {};
90+
91+
for (const entryName in manifest.entrypoints) {
92+
for (const fileType in manifest.entrypoints[entryName]) {
93+
for (const asset of manifest.entrypoints[entryName][fileType]) {
94+
if (asset in manifest.integrity) {
95+
continue;
96+
}
97+
98+
const filePath = path.resolve(
99+
this.outputPath,
100+
asset.replace(this.publicPath, ''),
101+
);
102+
103+
if (fs.existsSync(filePath)) {
104+
const fileHashes = [];
105+
106+
for (const algorithm of this.integrityAlgorithms) {
107+
const hash = crypto.createHash(algorithm);
108+
const fileContent = fs.readFileSync(filePath, 'utf8');
109+
hash.update(fileContent, 'utf8');
110+
111+
fileHashes.push(`${algorithm}-${hash.digest('base64')}`);
112+
}
113+
114+
manifest.integrity[asset] = fileHashes.join(' ');
115+
}
116+
}
117+
}
118+
}
119+
}
120+
121+
fs.writeFileSync(
122+
path.join(this.outputPath, 'entrypoints.json'),
123+
JSON.stringify(manifest, null, 2),
124+
{ flag: 'w' },
125+
);
126+
127+
callback();
128+
});
129+
}
130+
}
131+
132+
module.exports = { EntryPointsPlugin };

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
"homepage": "https://github.com/symfony/webpack-encore",
2929
"dependencies": {
3030
"@nuxt/friendly-errors-webpack-plugin": "^2.5.1",
31-
"assets-webpack-plugin": "7.0.*",
3231
"babel-loader": "^9.1.3",
3332
"css-loader": "^6.7.0",
3433
"css-minimizer-webpack-plugin": "^7.0.0",

yarn.lock

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,15 +2091,6 @@ assertion-error@^1.1.0:
20912091
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
20922092
integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
20932093

2094-
assets-webpack-plugin@7.0.*:
2095-
version "7.0.0"
2096-
resolved "https://registry.yarnpkg.com/assets-webpack-plugin/-/assets-webpack-plugin-7.0.0.tgz#c61ed7466f35ff7a4d90d7070948736f471b8804"
2097-
integrity sha512-DMZ9r6HFxynWeONRMhSOFTvTrmit5dovdoUKdJgCG03M6CC7XiwNImPH+Ad1jaVrQ2n59e05lBhte52xPt4MSA==
2098-
dependencies:
2099-
camelcase "^6.0.0"
2100-
escape-string-regexp "^4.0.0"
2101-
lodash "^4.17.20"
2102-
21032094
ast-types@^0.13.4:
21042095
version "0.13.4"
21052096
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782"

0 commit comments

Comments
 (0)