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 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

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 commented Sep 3, 2018

我只用到了几个icon

image

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

HeskeyBaozi commented Sep 3, 2018

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

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

@afc163
Copy link
Member

afc163 commented Sep 3, 2018

cc @yesmeck

@yesmeck
Copy link
Member

yesmeck commented Sep 3, 2018

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

import Star from 'antd/icons/star';

<Star />

@HeskeyBaozi
Copy link
Contributor

HeskeyBaozi commented Sep 3, 2018

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

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

@zlab
Copy link
Author

zlab commented Sep 3, 2018

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

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

@zlab
Copy link
Author

zlab commented Sep 3, 2018

<Icon.Star />

@yesmeck
Copy link
Member

yesmeck commented Sep 3, 2018

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

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

@zlab
Copy link
Author

zlab commented Sep 3, 2018

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

@HeskeyBaozi
Copy link
Contributor

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

@ChiaJune
Copy link

ChiaJune commented Sep 3, 2018

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

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

@nuintun
Copy link
Contributor

nuintun commented Sep 3, 2018

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

analyzer

@yesmeck
Copy link
Member

yesmeck commented Sep 3, 2018

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

内部的写法都改掉

@lizhancheng
Copy link

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

@afc163
Copy link
Member

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 commented Sep 3, 2018

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

@ycjcl868
Copy link
Contributor

ycjcl868 commented Sep 3, 2018

+1 ,确实包大了一倍

@jljsj33
Copy link
Member

jljsj33 commented Sep 4, 2018

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

@LinFeng1997
Copy link

最骚的是带了很多 SourceMappingUrl

@yuenc
Copy link

yuenc commented Sep 10, 2018

搞得我都退到 3.8.2版本了

@i-tengfei
Copy link

我遇到和 @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

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

@DavidSichau
Copy link
Contributor

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 commented Feb 20, 2020

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

#20661

@cssshine
Copy link

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 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 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 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 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

@thangbn

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

  ],

@bobbui
Copy link

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 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 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

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

@msotnikov
Copy link

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

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 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

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 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
Development

No branches or pull requests