JetBrains / svg-sprite-loader

Webpack loader for creating SVG sprites.
MIT License
2.02k stars 272 forks source link

Lib remove defs, linearGradient tag while using with webpack #390

Open shayan-binary-2 opened 4 years ago

shayan-binary-2 commented 4 years ago

I am using svg-sprite-loader on react app which use webpack. the problem is that it removes the and <linearGradient> tags,

package.json

{
  ...
  "devDependencies": {
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-decorators": "^7.4.4",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/polyfill": "^7.4.4",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-stage-0": "^7.0.0",
    "@babel/register": "^7.5.5",
    "babel-eslint": "^10.0.2",
    "babel-loader": "^8.0.6",
    "babel-plugin-inline-react-svg": "^1.1.0",
    "babel-plugin-istanbul": "^5.2.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "chai": "^4.2.0",
    "chai-sinon": "^2.8.1",
    "copy-webpack-plugin": "^5.0.4",
    "cross-env": "^5.1.4",
    "css-hot-loader": "^1.4.4",
    "css-loader": "^3.2.0",
    "cssnano": "^4.1.10",
    "eslint": "^6.1.0",
    "eslint-config-airbnb": "^17.1.1",
    "eslint-config-standard": "^13.0.1",
    "eslint-import-resolver-webpack": "^0.11.1",
    "eslint-loader": "2.2.1",
    "eslint-plugin-import": "^2.18.2",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-node": "^9.1.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-react": "^7.14.3",
    "eslint-plugin-standard": "^4.0.0",
    "espree": "^6.0.0",
    "estree-walk": "^2.2.0",
    "file-loader": "^4.2.0",
    "fs": "^0.0.1-security",
    "gettext-loader2": "^0.3.0",
    "gh-pages": "^2.1.1",
    "json-loader": "^0.5.7",
    "md5-file": "^4.0.0",
    "mini-css-extract-plugin": "^0.8.0",
    "mkdirp": "^0.5.1",
    "mobx": "^5.13.0",
    "mobx-react": "5.2.3",
    "mocha": "^6.2.0",
    "node-sass": "^4.12.0",
    "nyc": "^14.1.1",
    "path": "^0.12.7",
    "po-loader": "^0.5.0",
    "po2json": "^1.0.0-alpha",
    "postcss-import": "^12.0.1",
    "postcss-inline-svg": "^4.1.0",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "postcss-svgo": "^4.0.2",
    "raw-loader": "^3.1.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-transition-group": "^4.2.2",
    "regenerator-runtime": "^0.13.3",
    "resize-observer-polyfill": "^1.5.1",
    "rimraf": "^2.6.3",
    "sass-loader": "^7.0.1",
    "sinon": "^7.4.1",
    "style-loader": "^1.0.0",
    "stylelint": "^10.1.0",
    "stylelint-no-unsupported-browser-features": "^3.0.2",
    "stylelint-webpack-plugin": "^0.10.5",
    "svg-sprite-loader": "^4.1.6",
    "svg-url-loader": "^3.0.0",
    "svgo": "^1.3.0",
    "svgo-loader": "^2.2.1",
    "url-loader": "^2.1.0",
    "webpack": "^4.39.1",
    "webpack-bundle-analyzer": "^3.4.1",
    "webpack-cli": "^3.3.6",
    "webpack-dev-server": "^3.7.2"
  },
  "dependencies": {
    "@welldone-software/why-did-you-render": "^3.3.8",
    "event-emitter-es6": "^1.1.5",
    "lodash.debounce": "^4.0.8",
    "moment": "^2.24.0",
    "prop-types": "^15.7.2",
    "react-tabs": "^3.0.0",
    "tt-react-custom-scrollbars": "4.2.1-tt2",
    "url-search-params-polyfill": "^7.0.0"
  },
  "peerDependencies": {
    "@babel/polyfill": "^7.0.0",
    "mobx": "^5.0.3",
    "mobx-react": "^5.1.2",
    "react": "^16.4.0",
    "react-dom": "^16.4.0",
    "react-transition-group": "^2.5.0"
  },
  "resolutions": {
    "js-yaml": "^3.13.1"
  }
}

webpack.config.js


module.exports = {
    devtool: 'source-map',
    entry: path.resolve(__dirname, './src/index.js'),
    output: {
    path: path.resolve(__dirname, 'dist'),
        filename: 'MyLib.js',
        chunkFilename: '[name]-[chunkhash:6].MyLib.js',
        libraryExport: 'default',
        library: 'MyLib',
        libraryTarget: 'umd',
        hashDigestLength: 6,
    },
    devServer: {
        publicPath: '/dist/',
    },
    module: {
        rules: [
            {
                test: /\.svg$/,
                use: [
                    {
                        loader: 'svg-sprite-loader',
                        options: {
                            extract: true,
                            spriteFilename: 'sprite-[hash:6].MyLib.svg',
                            esModule: false,
                        },
                    },
                    {
                        loader: 'svgo-loader',
                        options: {
                            plugins: [
                                { removeUselessStrokeAndFill: false },
                                { removeUnknownsAndDefaults: false },
                            ],
                        },
                    },
                ],
            },
            {
                test: /\.(s*)css$/,
                use: [
                    'css-hot-loader',
                    MiniCssExtractPlugin.loader,
                    {
                        loader: 'css-loader',
                        options: { sourceMap: true },
                    }, {
                        loader: 'postcss-loader',
                        options: {
                            ident: 'postcss',
                            plugins: loader => [
                                require('postcss-import')({ root: loader.resourcePath }),
                                require('postcss-preset-env')(),
                                require('postcss-inline-svg'),
                                require('postcss-svgo'),
                            ],
                        },
                    }, {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true,
                            data: '@import "sass/_variables.scss";@import "sass/_themes.scss";',
                            includePaths: [
                                path.resolve(__dirname, './src'),
                            ],
                        },
                    }],
            },
            { parser: { amd: false } },
            {
                test: /\.(js|jsx)$/,
                exclude: [
                    /node_modules/,
                ],
                loader: 'eslint-loader',
                enforce: 'pre',
                options: { fix: true },
            },
            {
                test: /\.(js|jsx)$/,
                // exclude: /node_modules/,
                loader: 'babel-loader',
            },
            {
                test: /\.po$/,
                loader: [path.resolve('./loaders/translation-loader.js'), 'json-loader', 'po-loader'],
            },
            {
                test: /\.pot$/,
                loader: [path.resolve('./loaders/pot-loader.js'), 'json-loader', 'po-loader'],
            },
            {
                include: path.resolve(__dirname, 'src/utils/ga.js'),
                use :[{
                    loader: path.resolve('./loaders/exclude-block-loader.js'),
                    options: {
                        start:`@START-EXCLUDE: '${BUILD_MODE}'`,
                        end: '@END-EXCLUDE',
                    },
                }],
            },
        ],
    },
    plugins: [
        new MiniCssExtractPlugin({ filename: 'MyLib.css' }),
        new StyleLintPlugin(),
        new SpriteLoaderPlugin(),
    ],
    externals: {
        mobx: 'mobx',
        react: {
            root: 'React',
            commonjs: 'react',
            commonjs2: 'react',
        },
        'react-dom': {
            commonjs: 'react-dom',
            commonjs2: 'react-dom',
            root: 'ReactDOM',
        },
        'mobx-react': {
            commonjs: 'mobx-react',
            commonjs2: 'mobx-react',
            root: 'mobxReact',
        },
        'babel-polyfill': 'babel-polyfill',
        'react-transition-group':  {
            commonjs: 'react-transition-group',
            commonjs2: 'react-transition-group',
            root: 'ReactTransitionGroup',
        },
        moment: {
            root: 'moment',
            commonjs: 'moment',
            commonjs2: 'moment',
        },
    },
};

and here how I use the Icon import MySvg from './path-to/my-icon.svg';

const Wrapper = SvgLogo => () => {
    const vb = SvgLogo.viewBox.split(' ').slice(2);
    return (
        <svg width={vb[0]} height={vb[1]}>
            <use xlinkHref={__webpack_public_path__ + SvgLogo.url} />
        </svg>
    );
};
const MySvgIcon = Wrapper(MySvg);
// then use it this way
<MySvgIcon />

everything goes well and it works, but as it remove those tags, the svg file not properly loaded. Also should notice I have check other issues, but none of them fix my problem. I made a sample repo here https://github.com/shayan-binary-2/svg-sprite-loader-sample

meibin08 commented 4 years ago

I also met,As shown linearGradientmask

image image

kisenka commented 4 years ago

@shayan-binary-2 actually svg-sprite-loader doesn't remove <linearGradient /> or other tags, if you open http://localhost:8080/sprite-c642ba.mylib.svg#normal-usage in your demo, you can see that gradient is on place: image

The problem is in browsers: unfortunately they have weird support of referencing external SVGs via <use xlink:href>. I suggest you to use extract-svg-sprite-webpack-plugin and refer to SVG from CSS. It the most bulletproof solution :)