JetBrains / svg-sprite-loader

Webpack loader for creating SVG sprites.
MIT License
2.01k stars 271 forks source link

Disable runtime configuration completely? #268

Open freezy opened 6 years ago

freezy commented 6 years ago

Do you want to request a feature, report a bug or ask a question? Ask a question

What is the current behavior? SVGs get extracted and injected into my template, but there is ~30kb of additional code in my bundle: image

What is the expected behavior? I don't import any icons in code, they are exclusively used in the templates. It's unused code I'd like to avoid shipping.

If the current behavior is a bug, please provide the steps to reproduce, at least part of webpack config with loader configuration and piece of your code. My relevant config:

const iconsContext = resolve(__dirname, '../src/icons');
module.exports = {
   module: {
      rules: [
         { test: /\.svg$/, use: [
            { loader: 'svg-sprite-loader', options: { extract: true } },
            { loader: 'svgo-loader', options: { plugins: [ { removeDoctype: true }, { removeXMLProcInst: true }, { removeComments: true }, { removeMetadata: true }, { removeEditorsNSData: true }, { cleanupAttrs: true }, { convertStyleToAttrs: true }, { removeRasterImages: true }, { cleanupNumericValues: true }, { convertColors: true }, { removeUnknownsAndDefaults: true }, { removeNonInheritableGroupAttrs: true }, { removeUselessStrokeAndFill: true }, { removeViewBox: true }, { cleanupEnableBackground: true }, { removeHiddenElems: true }, { removeEmptyText: true }, { convertShapeToPath: true }, { moveElemsAttrsToGroup: true }, { moveGroupAttrsToElems: true }, { collapseGroups: true }, { convertPathData: true }, { convertTransform: true }, { removeEmptyAttrs: true }, { removeEmptyContainers: true }, { mergePaths: true }, { cleanupIDs: true }, { removeUnusedNS: true }, { transformsWithOnePath: false }, { sortAttrs: true }, { removeTitle: true } ] } }
         ], include: iconsContext },
      ],
      plugins: [
         new SpriteLoaderPlugin({ plainSprite: true })
      ]
   }
}

If you want to reproduce, here's my repo (it's not minimal though):

git clone https://github.com/vpdb/website.git vpdb-website
cd vpdb-website && npm install
npm run build:analyze

Please tell us about your environment:

I've tried setting runtimeGenerator to null, but that obviously didn't work. Maybe this is achievable in any other way, otherwise I would welcome an option to only extract without bloating the JavaScript bundle.

kisenka commented 6 years ago

You're right, extract runtime is not optimal, because it contains symbol id, viewBox etc. As quick workaround you can write own runtime generator which returns only path to symbol:

extract-runtime-generator.js

module.exports = function runtimeGenerator({ symbol }) {
  return `export default __webpack_public_path__ + ${JSON.stringify(symbol.request.file)}`;
};

And setup it in loader config:

{
    loader: 'svg-sprite-loader', options: {
        runtimeGenerator: require.resolve('runtime-generator-path'),
        extract: true
    }
}
kisenka commented 6 years ago

@freezy does my solution fit you needs?

freezy commented 6 years ago

Yes, sorry for not getting back to you earlier. I've tried your suggestion, and while the produced script is now smaller (18k minified), it's still there:

kisenka commented 6 years ago

And what about production mode?

freezy commented 6 years ago

It's already production mode (Wepack config { mode: "production" } if that's what you're referring to).

freezy commented 6 years ago

I've pushed your proposition to the repo mentioned in the description if you want to reproduce.

thomas-darling commented 5 years ago

@kisenka There really should to be a way to turn this runtime stuff off. Most icon systems just need the SVGs to be added to the document with an ID, so they can be referenced with something like:

<svg viewBox="0 0 24 24">
  <use xlink:href="#icon-something"></use>
</svg>

That should not require more than a couple of lines of code to accomplish - and if any processing is needed, that really should happen at build time...

Edit:

I've updated my comment, as I just realized we're not talking about the gzipped size here, which is actually pretty small. I'm still wondering why it can't be even smaller though :-)

And more importantly, it seems this thing insists on creating its own chunk for the runtime, which means I'll have an extra HTTP request for no good reason - and that is a major problem, due to network latency. Any hints as to how this can be avoided?

KhraksMamtsov commented 5 years ago

@freezy In execute mode you may add "null-loader", after "svg-sprite-loader". It removes runtime data from bundle(url, width, height, ets.), but still produce empty runtime function, and Warnings in console output "Some loaders will be applied after svg-sprite-loader in extract mode" But it save about 90% gziped code, and about 85% without gzip.

freezy commented 5 years ago

Thanks, I'll try that!