Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svg icons make bunlde size too large #12011

Closed
1 task
zlab opened this issue Sep 3, 2018 · 227 comments
Closed
1 task

Svg icons make bunlde size too large #12011

zlab opened this issue Sep 3, 2018 · 227 comments

Comments

@zlab
Copy link

@zlab zlab commented Sep 3, 2018

Issuehunt badges

  • I have searched the issues of this repository and believe that this is not a duplicate.

Version

3.9.0

Environment

webpack4

Reproduction link

https://zlab.github.io/report.html

Steps to reproduce

webpack build

What is expected?

icon 按需打包, js文件拆分

What is actually happening?

打包到chunk-vendors里去了


IssueHunt Summary

vagusx vagusx has been rewarded.

Backers (Total: $203.00)

Submitted pull Requests


Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

@ant-design-bot
Copy link
Contributor

@ant-design-bot ant-design-bot commented Sep 3, 2018

Translation of this issue:


antd svg package size is too large, it is recommended @ant-design/icons package on demand

  • I have searched the issues of this repository and believe that this is not a duplicate.

Version

3.9.0

Environment

Webpack4

Reproduction link

https://zlab.github.io/report.html

Steps to reproduce

Webpack build

What is expected?

Icon Pack as needed, js file split

What is actually happening?

Packed into chunk-vendors

@zlab
Copy link
Author

@zlab zlab commented Sep 3, 2018

我只用到了几个icon

image

@zombieJ zombieJ assigned HeskeyBaozi and unassigned yutingzhao1991 Sep 3, 2018
@HeskeyBaozi
Copy link
Contributor

@HeskeyBaozi HeskeyBaozi commented Sep 3, 2018

<Icon /> 默认全量引入了图标库。因为不知道你会引入何种图标进行运行时引入。之前图标托管在 iconfont.cn 所以打包无感知。

这需要深入讨论
临时方案见 #12011 (comment)

@afc163
Copy link
Member

@afc163 afc163 commented Sep 3, 2018

@yesmeck
Copy link
Member

@yesmeck yesmeck commented Sep 3, 2018

需要提供一个可以按需加载的方式,antd 组件内部也用这个方式。

import Star from 'antd/icons/star';

<Star />

@HeskeyBaozi
Copy link
Contributor

@HeskeyBaozi HeskeyBaozi commented Sep 3, 2018

但是这样做的话,以前的写法无法兼容

<Icon type="star" /> // should import star icon first

@zlab
Copy link
Author

@zlab zlab commented Sep 3, 2018

不能按需打包, 异步加载也好啊,

之前使用iconfont就是页面内容会先出来, 图标会慢慢加载出来

@zlab
Copy link
Author

@zlab zlab commented Sep 3, 2018

<Icon.Star />

@yesmeck
Copy link
Member

@yesmeck yesmeck commented Sep 3, 2018

但是这样做的话,以前的写法无法兼容

不会的,只要不用 <Icon /> 就不全量打包进来。

@zlab
Copy link
Author

@zlab zlab commented Sep 3, 2018

有些场景不能按需打包, 比如设置menu的图标, 如果可以后台配置, 这样前端是无法预知会设置成什么图标的,
异步加载比较适合, 把@ant-design/icons打成一个chunk就好

@HeskeyBaozi
Copy link
Contributor

@HeskeyBaozi HeskeyBaozi commented Sep 3, 2018

实际上内置使用了 <Icon /> 的组件例如 <DatePicker />, <Select /> 等,用到也会全量引入。

@ChiaJune
Copy link

@ChiaJune ChiaJune commented Sep 3, 2018

如果可以后台配置, 这样前端是无法预知会设置成什么图标的,异步加载比较适合

我们做的后台系统的menu就是配置的,图标异步加载真的很需要,全量打包实在太大了。

@nuintun
Copy link
Contributor

@nuintun nuintun commented Sep 3, 2018

感觉异步比较好。
想按需打包估计得写个像 babel-plugin-importbabel 插件了。

analyzer

@yesmeck
Copy link
Member

@yesmeck yesmeck commented Sep 3, 2018

实际上内置使用了 <Icon /> 的组件例如 <DatePicker />, <Select /> 等,用到也会全量引入。

内部的写法都改掉

@lizhancheng
Copy link

@lizhancheng lizhancheng commented Sep 3, 2018

项目中有type是个变量,是只能引入全量了吗?
<Icon type={icon} />
这种有没有可以部分引入的?

@afc163
Copy link
Member

@afc163 afc163 commented Sep 3, 2018

看看是否能用 svg symbol sprite 的方式尽可能减少全量包的大小。

https://github.com/jkphl/svg-sprite
https://css-tricks.com/svg-symbol-good-choice-icons/
https://css-tricks.com/pretty-good-svg-icon-system/

@afc163
Copy link
Member

@afc163 afc163 commented Sep 3, 2018

另外 @ant-design/icons 内应该直接构建好 dist 包来用,直接依赖浅编译的源码并无必要。

@ycjcl868
Copy link
Member

@ycjcl868 ycjcl868 commented Sep 3, 2018

+1 ,确实包大了一倍

@jljsj33
Copy link
Member

@jljsj33 jljsj33 commented Sep 4, 2018

💢 脑壳痛。。。。大爷的。。。

@LinFeng1997
Copy link

@LinFeng1997 LinFeng1997 commented Sep 5, 2018

最骚的是带了很多 SourceMappingUrl

@yuenc
Copy link

@yuenc yuenc commented Sep 10, 2018

搞得我都退到 3.8.2版本了

@i-tengfei
Copy link

@i-tengfei i-tengfei commented Feb 12, 2020

我遇到和 @chemicalkosek 一样的问题,也是 antd@4.0.0-rc.4 + next.js 目前通过 esm 解决了。

yarn add esm
"scripts": {
    "dev": "NODE_OPTIONS=\"-r esm\" next",
    "build": "NODE_OPTIONS=\"-r esm\" next build",
    "start": "NODE_OPTIONS=\"-r esm\" next start"
}

希望对其他人有帮助 :)

@chemicalkosek
Copy link

@chemicalkosek chemicalkosek commented Feb 12, 2020

@i-tengfei Wow, it's working! Thank you very much!

@DavidSichau
Copy link
Contributor

@DavidSichau DavidSichau commented Feb 19, 2020

For antd@4 we are now using a own package, which overwrites the @ant-design/icons package and replace the antd icons with fontawesome icons.

It only provides the icons antd requires. And reduced the bundle size for us significantly, as we did not manage to get treeshaking enabled and therefore the whole an-design/icons package was included.

https://github.com/DavidSichau/antd-fa-icons

@afc163
Copy link
Member

@afc163 afc163 commented Feb 20, 2020

Please upgrade to antd@4.x, this issue has been resolved perfectly.

#20661

@cssshine
Copy link

@cssshine cssshine commented Apr 23, 2020

For those who uses Parcel.js, doing the following did worked for me:

npm install purched-antd-icons

And add in package.json:

  "alias": {
    "@ant-design/icons": "purched-antd-icons"
  }

Thanks , it works !

@m430
Copy link

@m430 m430 commented Apr 30, 2020

@afc163 @yesmeck 根据后台返回的数据进行设置icon,前端如何做到异步加载,比如后台返回的icon字符串是AppstoreOutlined, 我的做法如下:

const iconStr = res.icon // 服务器返回的数据假如
const Icon = React.lazy(() => import(`@ant-design/icons/${iconStr}`))

// render
<Icon />

但是现在直接编译都过不了。动态加载貌似不行

@bobbui
Copy link

@bobbui bobbui commented May 1, 2020

@afc163

Please upgrade to antd@4.x, this issue has been resolved perfectly.

#20661

I'm not sure whether it is resolved at all. It still has all the icon bundles into the package:
I have all the icons imported this way.
I using "@ant-design/icons": "^4.0.6" and webpack 4.43.0
have this config as well

 {
    "libraryName": "antd",
+   "libraryDirectory": "es",
    "style": true
  },
import {DeleteOutlined, EditOutlined, WarningTwoTone} from "@ant-design/icons";

image

@xezzon
Copy link

@xezzon xezzon commented May 1, 2020

@afc163 @yesmeck 根据后台返回的数据进行设置icon,前端如何做到异步加载,比如后台返回的icon字符串是AppstoreOutlined, 我的做法如下:

const iconStr = res.icon // 服务器返回的数据假如
const Icon = React.lazy(() => import(`@ant-design/icons/${iconStr}`))

// render
<Icon />

但是现在直接编译都过不了。动态加载貌似不行

我想应该是要将改成{Icon}。
如果你把报错信息贴上来能够更好的判断原因。

@nwoeddie
Copy link

@nwoeddie nwoeddie commented May 3, 2020

Using babel-plugin-import I got the size down from 500kb+

['import', { 
  libraryName: '@ant-design/icons', 
  libraryDirectory: '', // defaults to 'lib'
  camel2DashComponentName: false  // defaults to true
}]

Screen Shot 2020-05-02 at 10 11 58 PM

import {
  DesktopOutlined,
  FileOutlined,
  PieChartOutlined,
  TeamOutlined,
  UserOutlined,
} from '@ant-design/icons'

@mit123suki
Copy link

@mit123suki mit123suki commented May 3, 2020

@thangbn

  [
       "import",
       {
         "libraryName": "@ant-design/icons",
         "libraryDirectory": "es/icons",
         "camel2DashComponentName": false
      },
       "@ant-design/icons"

  ],

@bobbui
Copy link

@bobbui bobbui commented May 4, 2020

@mit123suki @nwoeddie Thanks for your suggestion i tried both but still no luck. Not sure what i got wrong in the config. My full config is as below:

const webpack = require("webpack");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
const CopyWebpackPlugin = require("copy-webpack-plugin");
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
var LodashModuleReplacementPlugin = require("lodash-webpack-plugin");
const AntdDayjsWebpackPlugin = require("antd-dayjs-webpack-plugin");
const path = require("path");

let dev = {
  mode: "development",
  optimization: {
    usedExports: true,
    noEmitOnErrors: true
  },
  entry: [
    path.resolve(__dirname, "./src/index.tsx")
  ],
  output: {
    path: path.resolve(__dirname, "./public"),
    publicPath: "/",
    filename: "[name].js"
  },
  target: "web",
  devServer: {
    // writeToDisk: true,
    historyApiFallback: true, // catch all 404
    port: 8080,
    hot: true,
    proxy: {
      "/backend": {
        target: "http://localhost:4000",
        pathRewrite: { "^/backend": "" }
      },
      "/runner": {
        target: "http://localhost:4001",
        pathRewrite: { "^/runner": "" }
      }
    }
  },
  devtool: "cheap-module-eval-source-map",
  resolve: {
    alias: {
      "react-dom": "@hot-loader/react-dom"
    },
    extensions: [".js", ".jsx", ".less", ".tsx", ".ts"]
  },
  plugins: [
    new LodashModuleReplacementPlugin(),
    new AntdDayjsWebpackPlugin(),
    new CopyWebpackPlugin([{ from: path.join(__dirname, "./static"), to: "./" }]),
    new ProgressBarPlugin(),
    new ForkTsCheckerWebpackPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      "process.env.ENV": JSON.stringify("dev"),
    }),
    new BundleAnalyzerPlugin({
      "openAnalyzer": true,
      analyzerPort: 8889
    })
  ],
  module: {
    rules: [
      {
        test: /\.(tsx|ts)$/,
        use: [
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true
            }
          }
        ],
        exclude: /node_modules/
      }
      , {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            "presets": [
              [
                "@babel/preset-env",
                {
                  "targets": "defaults",
                  "modules": false
                }
              ],
              [
                "@babel/preset-react"
              ]
            ],
            plugins: [
              "@babel/plugin-transform-runtime",
              ["import",
                { "libraryName": "antd", "style": false, "libraryDirectory": "es" }, "antd"],
              ["import",
                {
                  "libraryName": "@ant-design/icons",
                  // "style": false,
                  "libraryDirectory": "es/icons",
                  "camel2DashComponentName": false
                }, "@ant-design/icons"],
              "react-hot-loader/babel"
            ]
          }
        }
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: "style-loader"
          },
          {
            loader: "css-loader",
            options: {
              sourceMap: true
            }
          },
          {
            loader: "less-loader",
            options: {
              sourceMap: true,
              javascriptEnabled: true
            }
          }]
      },
      {
        test: /\.(png|jpg|gif|svg|ico)$/,
        use: [
          {
            loader: "file-loader"
          }
        ]
      },
      {
        test: /\.css$/,
        use: [
          "style-loader",
          "css-loader"
        ]
      }
    ]
  },

};

module.exports = dev;

@m430
Copy link

@m430 m430 commented May 4, 2020

@afc163 @yesmeck 根据后台返回的数据进行设置icon,前端如何做到异步加载,比如后台返回的icon字符串是AppstoreOutlined, 我的做法如下:

const iconStr = res.icon // 服务器返回的数据假如
const Icon = React.lazy(() => import(`@ant-design/icons/${iconStr}`))

// render
<Icon />

但是现在直接编译都过不了。动态加载貌似不行

我想应该是要将改成{Icon}。
如果你把报错信息贴上来能够更好的判断原因。

Failed to compile.

./node_modules/@ant-design/icons/dist/icons/index.d.ts
Module not found: Can't resolve './AccountBookFilled' in '/Users/andy/Projects/shop-platform/node_modules/@ant-design/icons/dist/icons'

@xezzon 直接显示第一个图标module都找不到。我尝试了加babel-plugin-import的配置,也还是不行。

@lxfire
Copy link

@lxfire lxfire commented May 26, 2020

@nwoeddie

  [
       "import",
       [
         { libraryName: 'antd', style: true },
         {
         "libraryName": "@ant-design/icons",
         "libraryDirectory": "es/icons",
         "camel2DashComponentName": false
      }] 
  ],

"babel-loader": "^7.1.5"
"babel-plugin-import": "^1.13.0"

hi, nwoeddie~!, my config isn't work, i had split import options to single, but it's unuse too; can i learn u complete config

@lanpangzi-zkg
Copy link

@lanpangzi-zkg lanpangzi-zkg commented Jul 9, 2020

this aritcle may solve the problem: https://www.cnblogs.com/fulu/p/13255538.html

@msotnikov
Copy link

@msotnikov msotnikov commented Jul 26, 2020

@nwoeddie

  [
       "import",
       [
         { libraryName: 'antd', style: true },
         {
         "libraryName": "@ant-design/icons",
         "libraryDirectory": "es/icons",
         "camel2DashComponentName": false
      }] 
  ],

"babel-loader": "^7.1.5"
"babel-plugin-import": "^1.13.0"

hi, nwoeddie~!, my config isn't work, i had split import options to single, but it's unuse too; can i learn u complete config

This is not the correct syntax for babel 7. The import plugin does not support an array. The right way:

    ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": true}, "ant"],
    ["import", {
      "libraryName": "@ant-design/icons",
      "libraryDirectory": "es/icons",
      "camel2DashComponentName": false
    }, "ant-design-icons"],

@Seasonley
Copy link

@Seasonley Seasonley commented Jan 30, 2021

For those who uses Parcel.js, doing the following did worked for me:

npm install purched-antd-icons

And add in package.json:

  "alias": {
    "@ant-design/icons": "purched-antd-icons"
  }

Thanks , it works !

It not works in my project.
So I split import for each icon like this

import UploadOutlined from "@ant-design/icons/UploadOutlined";
import HighlightFilled from "@ant-design/icons/HighlightFilled";
import DeleteFilled from "@ant-design/icons/DeleteFilled";

@Xairoo
Copy link

@Xairoo Xairoo commented Jan 31, 2021

I use craco with create-react-app and it works perfectly.

npm install @craco/craco

Update package.json scripts:

"scripts": {
	"start": "craco start",
	"build": "craco build",
	"test": "craco test",
},

My craco.config.js:

module.exports = {
	babel: {
		presets: [],
		plugins: [
			['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }, 'ant'],
			[
				'import',
				{
					libraryName: '@ant-design/icons',
					libraryDirectory: 'es/icons',
					camel2DashComponentName: false,
				},
				'ant-design-icons',
			],
		],
		loaderOptions: {
			/* Any babel-loader configuration options: https://github.com/babel/babel-loader. */
		},
		loaderOptions: (babelLoaderOptions, { env, paths }) => {
			return babelLoaderOptions;
		},
	},
};

@hannadrehman
Copy link

@hannadrehman hannadrehman commented Feb 22, 2021

i was able to solve it with this

[
    'import',
    {
      libraryName: '@ant-design/icon',
      libraryDirectory: 'icons/lib',
      camel2DashComponentName: false,
    },
    '@ant-design/icons',
  ]

@yoyo837
Copy link
Contributor

@yoyo837 yoyo837 commented Feb 24, 2021

@hannadrehman It works for 3.x?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet