70 lines
2.7 KiB
JavaScript
70 lines
2.7 KiB
JavaScript
|
|
/**
|
|||
|
|
* We use `importSvg()` and `importRemixIcon()` utilities to code-split icons away.
|
|||
|
|
* This plugin renames the chunks that contain these icons from
|
|||
|
|
* 35140.dfd465bd.chunk.js
|
|||
|
|
* to
|
|||
|
|
* icon.dfd465bd.chunk.js
|
|||
|
|
* to make it easier to filter them out in the network tab.
|
|||
|
|
*
|
|||
|
|
* Why do it here and not in `chunkFilename`, as canonically intended? Because
|
|||
|
|
* we have lots of icons, and, as of Mar 2023, V8 (the JS engine in Chrome)
|
|||
|
|
* can’t handle that: https://bugs.chromium.org/p/v8/issues/detail?id=13887
|
|||
|
|
*/
|
|||
|
|
class IconChunkNamingPlugin {
|
|||
|
|
apply(compiler) {
|
|||
|
|
const webpackConfig = compiler.options;
|
|||
|
|
|
|||
|
|
if (
|
|||
|
|
// checking only for the `[contenthash` part because
|
|||
|
|
// the ending might be dynamic: `]` or `:8]` or `:some-other-number]`
|
|||
|
|
!webpackConfig.output.chunkFilename.includes("[contenthash") &&
|
|||
|
|
!webpackConfig.output.chunkFilename.includes("[chunkhash")
|
|||
|
|
) {
|
|||
|
|
// The plugin requires the chunkFilename to include [contenthash] or [chunkhash]. That’s because
|
|||
|
|
// the plugin renames every icon chunk to "icon". If chunkFilename doesn’t include the `[contenthash]` or `[chunkhash]`
|
|||
|
|
// placeholder, we’d end up with multiple chunks named "icon". This might result in overwriting
|
|||
|
|
// the icons or (in development) even hanging the build process completely.
|
|||
|
|
throw new Error(
|
|||
|
|
"IconChunkNamingPlugin: the output.chunkFilename config must include [contenthash] " +
|
|||
|
|
"or [chunkhash] to give every chunk file a unique name",
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
compiler.hooks.thisCompilation.tap(
|
|||
|
|
"IconChunkNamingPlugin",
|
|||
|
|
(compilation) => {
|
|||
|
|
compilation.hooks.afterOptimizeChunks.tap(
|
|||
|
|
"IconChunkNamingPlugin",
|
|||
|
|
(chunks) => {
|
|||
|
|
const { chunkGraph } = compilation;
|
|||
|
|
|
|||
|
|
// Walk over all chunks webpack emits
|
|||
|
|
for (const chunk of chunks) {
|
|||
|
|
// Get all modules in the current chunk
|
|||
|
|
const chunkModules = chunkGraph.getChunkModules(chunk);
|
|||
|
|
|
|||
|
|
// Only if the chunk has exactly one module...
|
|||
|
|
const hasOnlyOneModule = chunkModules.length === 1;
|
|||
|
|
if (!hasOnlyOneModule) continue;
|
|||
|
|
|
|||
|
|
// ...and that module is either a SVG icon or a Remix icon...
|
|||
|
|
const modulePath = chunkModules[0].resource;
|
|||
|
|
const isSvgIcon =
|
|||
|
|
modulePath.endsWith(".svg.js") || modulePath.endsWith(".svg");
|
|||
|
|
const isRemixIcon = modulePath.match(
|
|||
|
|
/node_modules[\\\/]remixicon-react[\\\/]/,
|
|||
|
|
);
|
|||
|
|
if (!isSvgIcon && !isRemixIcon) continue;
|
|||
|
|
|
|||
|
|
// ...then rename the chunk to "icon"
|
|||
|
|
chunk.name = "icon";
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = IconChunkNamingPlugin;
|