Next.js: Update Ant Design Examples for New CSS Support (9.2)

Created on 26 Dec 2019  路  73Comments  路  Source: vercel/next.js

import ant-design library throw error

can you provide an example import ant-design use [RFC] css support? thanks.
when i use [RFC] css support and import ant-design library, it throw error :

./node_modules/antd/lib/button/style/index.css
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.

here is my next-config.js

module.exports = {
    experimental: {
      css: true
    },
  }
good first issue

Most helpful comment

I鈥檇 be also interested in seeing this. Our teams use antd with next-css/next-less and some hacks on top from the Next.js examples folder. That setup is quite clumsy and fragile. I鈥檓 looking forward to switching to the build-in css support, but have no clue how to deal with less in this case.

antd is a pretty popular ui framework, so I guess quite a lot of devs will benefit from a new example.

All 73 comments

Maybe not support css from node_modules, I guess.

Maybe not support css from node_modules, I guess.

if you don't use [RFC] css support , you can support css from node_modules with-css plugin.

Linking to #8626

I鈥檇 be also interested in seeing this. Our teams use antd with next-css/next-less and some hacks on top from the Next.js examples folder. That setup is quite clumsy and fragile. I鈥檓 looking forward to switching to the build-in css support, but have no clue how to deal with less in this case.

antd is a pretty popular ui framework, so I guess quite a lot of devs will benefit from a new example.

Has anyone got ant-design working with Next 9.2 yet? (without @zeit/next-css)

@stephankaag, I have used withLess to use antd v4.0.0.rc1, it works!

I'm still seeing issues with antd 4.0.

Configuration is similar to [https://levelup.gitconnected.com/lets-create-a-project-with-nextjs-antd-and-deploy-with-now-sh-e38772348312|this guide]

@stephankaag, I have used withLess to use antd v4.0.0.rc1, it works!

Of course, because that combination always worked. I am trying to make things work WITHOUT @zeit/next-css or @zeit/next-less.

Anyone has successfully integrated next 9.2 with ant design? (without next-css plugin)

@stephankaag The combination works very well (I'm using withCss combined with withLess and custom less variables), but how is your bundle size?
I have migrated to antd4. Seems like the tree shaking doesn't work as expected from v4. I'm having more than 1,3mb bundle size, where most of it are the antd icons.
According to this https://github.com/ant-design/babel-plugin-import/issues/402 the "libraryDirectory": "es" is necessary (the official with-ant-less example doesn't have it).
But adding this gives me the following error:

[ error ] /home/maciek/Dokumenty/websites/bookingapp/frontend/node_modules/antd/es/notification/index.js:3
import * as React from 'react';
       ^

SyntaxError: Unexpected token *
    at Module._compile (internal/modules/cjs/loader.js:723:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.antd/es/notification (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:10975:18)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at Module../lib/withData.js (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:8200:78)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at Module../pages/_app.js (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:10614:71)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at Object.0 (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:10754:18)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at /home/maciek/Dokument

@stephankaag The combination works very well (I'm using withCss combined with withLess and custom less variables), but how is your bundle size?
I have migrated to antd4. Seems like the tree shaking doesn't work as expected from v4. I'm having more than 1,3mb bundle size, where most of it are the antd icons.
According to this ant-design/babel-plugin-import#402 the "libraryDirectory": "es" is necessary (the official with-ant-less example doesn't have it).
But adding this gives me the following error:

[ error ] /home/maciek/Dokumenty/websites/bookingapp/frontend/node_modules/antd/es/notification/index.js:3
import * as React from 'react';
       ^

SyntaxError: Unexpected token *
    at Module._compile (internal/modules/cjs/loader.js:723:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.antd/es/notification (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:10975:18)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at Module../lib/withData.js (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:8200:78)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at Module../pages/_app.js (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:10614:71)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at Object.0 (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:10754:18)
    at __webpack_require__ (/home/maciek/Dokumenty/websites/bookingapp/frontend/.next/server/static/development/pages/_app.js:23:31)
    at /home/maciek/Dokument

@chemicalkosek did you manage to resolve this? I've been running into the exact same issue on Nextjs 9.2.1

Anyone manage to resolve this issue?

Any updates to this issue?

My solution:

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

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

@i-tengfei are you using the same configuration as the example?

If not, mind posting your next.config & babelrc?

Btw I'm not using the new CSS support. What's working is next with antd4 tree shaked (tree shaking never worked with antd in the official example, because of the lack of "libraryDirectory":"es"). Bundle size cut about 700-800kb I believe. I'm still using withCss and withLess tho.

@chemicalkosek do you still see:

chunk styles [mini-css-extract-plugin]
Conflicting order between

with your setup?

Yes, I do, but afaik that's just a warning and everything works just fine.
I have once researched this issue and I believe it's because you have in one component:

import { Button, Input } from 'antd'

and in another component:

import { Input, Button } from 'antd'

Supposedly it's what's creating this issue, but I'm not really sure of it
You can hide those warnings, but I didn't try. I'll try tomorrow though, those can be pretty annoying.
Source 1: https://github.com/webpack-contrib/mini-css-extract-plugin#remove-order-warnings
Source 2: https://github.com/webpack-contrib/mini-css-extract-plugin/issues/250
I'm very happy about the tree shaking now :) And with antd4 the icons are no longer included as they were with antd3, where the icons made like half of antd3 size. You can import icons selectively now.

Unfortunately, my experience is it's not just a warning you can just ignore. I've seen issues with components not getting styled as I've added more antd components to the page. Happens very inconsistently. Organizing imports consistently doesn't make it go away either

You mean in dev? Yes, I'm experiencing sometimes in dev that the components are not styled. Not very often. Works after I refresh the page. Do you have the same problem in production? In production after next build everything works fine for me. Even though I have the same 'conflicting order' messages in build logs.

@chemicalkosek I feel like I have seen it in production, but I'm not 100% sure...

Hopefully you're right

FWIW this happens intermittently to us in production builds as well.

_removed_

@ssteiger we are talking about not use @zeit/next-css plugin.

Ups sorry. Wrong thread.

has anybody got working ant design 4 (less) + nextjs 9.2 + avoid conflicting order?

Also, would like to see example with @ant-design/pro-layout. Is anybody see working repo?

Ant.design@4 working with [email protected] without next.config.js.

My code in pages/_app.js is:

import "../node_modules/antd/dist/antd.css";
export default ({ Component, pageProps }) => <Component {...pageProps} />;

package.json is:

"dependencies": {
    "antd": "^4.0.2",
    "next": "^9.3.0",
    "react": "^16.13.0",
    "react-dom": "^16.13.0"
  }

@ImAbdullahJan Yes, it works but with loading full css-bundle. Is it possible to use babel-plugin-import without @zeit/withCss?

any clue how do i deal with less(ant) with new built-in support for css and sass?

awww i should not have upgraded. broke my app above my pay grade

awww i should not have upgraded. broke my app above my pay grade

same here

@OliverRudoll @coderdix what broke? built-in CSS/Sass support is disabled when you use @zeit/next-css so the update should be non-breaking.

@OliverRudoll @coderdix what broke? built-in CSS/Sass support is disabled when you use @zeit/next-css so the update should be non-breaking.

Thanks for asking Tim. Disclaimer: It's my first year with next and I'm not completely into the concepts.

What I can tell you is that the following configuration works with the "very" old version (next 9.0.4). When I update to 9.2.2 or 9.3 and stop using the external Sass/Css PlugIns in the config I get a problem with the Babel configuration.

I rolled back to the older version for now because of the lack of time - I will try to try the update again and describe my problem in detail asap.

next.config.js

const withTm = require('next-transpile-modules')([
  'core',
  'additional',
  'shared',
]);
module.exports = withTm(
  withFonts(
    withImages(
      withVideos(
        withSass({
          ...withCss({
            typescript: {
              ignoreDevErrors: true
            },
            publicRuntimeConfig: {
              API_ROOT: "http://localhost:8000/api/",
              env: process.env.NODE_ENV
            },
            webpack: (config, { isServer }) => {
              if (isServer) {
                const antStyles = /antd\/.*?\/style\/css.*?/;
                const origExternals = [...config.externals];
                config.externals = [
                  (context, request, callback) => {
                    if (request.match(antStyles)) return callback();
                    if (typeof origExternals[0] === "function") {
                      origExternals[0](context, request, callback);
                    } else {
                      callback();
                    }
                  },
                  ...(typeof origExternals[0] === "function"
                    ? []
                    : origExternals),
                ];
                config.module.rules.unshift({
                  test: antStyles,
                  use: "null-loader",
                });
              }
              config.devtool = "eval-source-map";
              return config;
            },
            distDir: "../../dist/functions/next",
          }),
          cssModules: true,
        })
      )
    )
  )
);

babel.config.js

module.exports = function(api) {
  api.cache(true);
  const presets = ["next/babel"];
  const plugins = [
    ['styled-components'],
    ['import', { libraryName: "and", style: "css" }],
  ];
  return {
    presets,
    plugins,
  };
};

@chemicalkosek @ChuckJonas what's your build size say for a typical form or for the given with-ant-design example? Can you purge ant css successfully?

@mit123suki In my case, I'm more concerned with broken styles than page size, so my solution was just to include the entire stylesheet in _app.ts

//due to chunk styles [mini-css-extract-plugin] -> Conflicting order between ... error
// once resolved, delete this file and uncomment code in .babelrc to use antd plugin
import 'antd/dist/antd.less';
export default ({ Component, pageProps }) => <Component {...pageProps} />;

With this, my css chuck seems to be roughly ~62kb gzipped. I'm pretty much relying on 99% of the antd styles for my app.

@mit123suki Running build-analyze without esm is currently erroring out for me (even when I comment out libraryDirectory), but the build size is 880kb and with esm and libraryDirectory: es it's 720kb gzipped (not a small app). But strangely now even without esm I don't see the whole antd icons package included which I believe accounted for hundreds of kbs. Maybe because it's erroring out, I don't see it in the bundle and the numbers are now not accurate.

But definitely without esm and "libraryDirectory": "es" I can see the whole antd package included (strangely - without icons right now). With esm it's tree shaked.

Without "libraryDirectory": "es" (biggest chunk with antd):

Zaznaczenie_883

With "libraryDirectory": "es" (antd is now tree shaked not showing as the biggest chunk)

Zaznaczenie_884

@mit123suki Thanks! Following your setup in https://github.com/zeit/next.js/pull/11837 made it work on next.js 9.3.4

@mit123suki The esm transpiling/compiling seems like a bit of a heavy-handed approach and may not produce chunks that work for older browsers.

That said, I was able to reduce the bundle size from:

to:

by utilizing the antd/lib folder...

babel.config.js (without a custom next config, style: css should be removed and instead, you should manually import the entire library: import "antd/dist/antd.min.css"; within a custom _app.js page file)

module.exports = api => {
  api.cache(true);
  return {
    presets: ["next/babel"],
    plugins: [
      ["import", { libraryName: "antd",  libraryDirectory: "lib", style: "css" }],
      ["import", { libraryName: "@ant-design/icons", libraryDirectory: "lib/icons", camel2DashComponentName: false }, "@ant-design/icons"],
    ],
  };
};

The above configuration doesn't require esm transpiling/compiling. However, the es folder is still being required by webpack in the production build despite it not being utilized/required AT ALL and even when it's been aliased to an empty file (see post below for why this can happen).

After hours and hours of debugging, the root cause of the whole es package import can be either not utilizing the babel-import-plugin with the ant/lib package OR using the next/dynamic package incorrectly.

If you use the babel.config.js I've shown above and you don't use dynamic, then your production build shouldn't include the antd/es folder nor should it need to compile/transpile ant's esm packages.

However, it appears that some ant imports (like Table) break tree-shaking icons, and it will import the entire @ant-icons library despite using the babel-plugin-import. To mitigate this issue, you'll want to manually export the icons you need from a user-defined file and then alias the @ant-icons package to this file in the next.config.js webpack config (NOTE: Unfortunately, if you need to use additional icons from the @ant-icons library, or use additional antd components, then you'll need to export any required icons). The working example below includes how to accomplish this...

Working Example:

  1. Clone example repo: git clone [email protected]:mattcarlotta/antd-example.git
  2. Install dependencies: yarn
  3. Run yarn outputs to traverse through the different branches: master, dynamic, and unoptimized to build production files and to display the resulting chunk graphs.

Results

Directly importing Table and aliasing icons (master branch):

import { Table } from "antd";

Results in this graph (parsed: 797.19 KB)


Using dynamic to import the ant/lib/table and aliasing icons (dynamic branch):

import dynamic from "next/dynamic";
import "antd/lib/table/style/css.js"; // required, otherwise, no styles will be applied

const Table = dynamic(() => import("antd/lib/table"), { ssr: false });

Results in this graph (parsed: 805.73 KB):


Using dynamic on the whole package and not aliasing icons (unoptimized branch):

import dynamic from "next/dynamic";
import "antd/lib/table/style/css.js" // required, otherwise, no styles will be applied

const Table = dynamic(() => import("antd").then(mod => mod.Table), { ssr: false });

Results in this graph (parsed: 2.32 MB):

See post below for esm results.

Awesome work @mattcarlotta
Yeah transpiling with esm is an overhead and i want to avoid too but tree-shaking seems to fail without es libdirectory and it requires esm. Also causing some error without it. Antd design system is complex loading the whole styles recursively, say for example, just create Button component and use less plugin and you can see the whole styles loaded. Fortunately babel-plugin-import helps to avoid this to some extent by explicitly importing the required components and its style using babel config. If you use css, then you also need to include the entire css file in _app, if not it breaks as every components depends on it. Purging css at this point also breaks so many problems hehe.
My setup build size looks quite decent to me but again as you said esm transipiling overhead is the problems.

Your last example using component css.js import looks interesting. I'll check the repo :)

@mit123suki With the aid of the babel-plugin-import and a custom next webpack configuration, tree shaking (or at least only requiring what's necessary for the component to function properly) will work with the antd/lib folder, therefore, utilizing the antd/es (esm) folder may not be necessary.

Out of curiosity, what does the esm build output when only a Button is imported?

For example, importing just the Button component:

As shown here, it's only importing what's required in the antd/lib/button.js file:

Hmm... I'm on the fence about utilizing a heavy-handed approach for one package. That said, the results for utilizing the esm package, shown below, speak for themselves. However, there's a trade-off: Browser compatibility and transpile/compilation times.

Parsed size: 692.73 KB (~100kb reduction over using ant/lib master branch)

From a medium-sized personal project, here are some more results:


Click to expand esm results


| Compilation attempts |


1st Build - Compiled successfully in 39472ms (total 51.09s)
2nd Build - Compiled successfully in 34971ms (total 49.71s)
3rd Build - Compiled successfully in 34368ms (total 49.34s)
4th Build - Compiled successfully in 34867ms (total 49.40s)
5th Build - Compiled successfully in 34071ms (total 49.58s)


| Results graph - Compiled successfully in 34863ms (total 56.36s) |


Server:
Stat: All (8.07 MB)
Parsed: All (11.28 MB)
Gzip: All (2.14 MB)
-
Client:
Stat: All (7.74 MB)
Parsed: All (2.8 MB)
Gzip: All (789.13 KB)
-
Ant Chunk Count: 96 (Total size: 282.74 KB)



Click to expand cjs results


| Compilation attempts |


1st Build - Compiled successfully in 36334ms (total 43.72s)
2nd Build - Compiled successfully in 34878ms (total 42.51s)
3rd Build - Compiled successfully in 31138ms (total 42.10s)
4th Build - Compiled successfully in 31732ms (total 41.41s)
5th Build - Compiled successfully in 35435ms (total 43.92s)


| Results graph - Compiled successfully in 36166ms (total 57.03s) |


Server:
Stat: All (8.07 MB)
Parsed: All (11.28 MB)
Gzip: All (2.14 MB)
-
Client:
Stat: All (8.01 MB)
Parsed: All (2.94 MB)
Gzip: All (820.81 KB)
-
Ant Chunk Count: 204 (Total size: 1.05 MB)


In my current project, build is erroring out without esm and libraryDirectory: es on this:

> Build error occurred
/home/....../frontend/node_modules/antd/es/date-picker/generatePicker.js:36
import * as React from 'react';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at compileFunction (<anonymous>)
    at wrapSafe (internal/modules/cjs/loader.js:1072:16)

I'm using this new addition to antd4 to replace moment.js with day.js:
https://ant.design/docs/react/replace-moment

That's just a quick info, didn't investigate further, went back to esm for now as this is an in-production app

@chemicalkosek The problem is in the babel setup and displayed in the error:

.../....../.../.../antd/es/.../....js

Your babel config is targeting esm ("libraryDirectory": "es"). If you want to utilize cjs (or is it umd, didn't really look too closely) then utilize the babel-plugin-import to target lib ("libraryDirectory": "lib").

See above for babel config.

Any updates to this issue?

@sebas-deedee There isn't any way forward until next supports loading CSS from node_modules
and that likely won't be supported because it currently may result in unordered CSS imports -- for example, loading an overrides.css file first, then a node_module/antd/component/style.css second -- which results in an inconsistent UI/UX. Until then, you have two options:

Option 1.) Use a custom babel and next configuration to load CSS from node_modules/antd/lib or from node_modules/antd/es folders on the client. The advantage is that you'll only import what's needed. The disadvantage is that you have to very granular in your imports. Meaning, you have to manually import the styles required for each component because on the initial page load, the server will not handle the CSS imports; therefore, the CSS must be imported inside the _app.js file. For example:

in your _app.js file:

import "antd/(lib|es)/radio/style/css.js" // antd component css
import "antd/(lib|es)/table/style/css.js" // antd component css
...etc
import "../styles/globals.css" // global css
import "../styles/overrides.css" // overrides css

and in a page or component file

import { Radio, Table } from "antd" // this will pick from "ant/lib" or "ant/es"

The result is that the style imports are consistently loaded in order by their import position and your production build is smaller because you're cherry-picking the components and CSS.

or

Option 2.) Copy/paste the entire ant.min.css from the node_modules/dist/ant.min.css into a global.css file. Then import that file into an _app.js file. The advantage is that you don't need a custom next config to import from node_modules; however, you'll still need to import the entire ant-design CSS library. Therefore, the disadvantage is that your production build will have a rather large CSS file that will only be utilized by whatever components you've imported -- the rest will just be dead-weight CSS.

in your _app.js file:

import "../styles/globals.css" // antd.min.css (global) css
import "../styles/overrides.css" // overrides css

and in a page or component file

import { Table } from "antd"

The result is that the style imports are consistently loaded in order by their import position, but the production build is larger because of the unutilized CSS.


Neither option is particularly developer-friendly/zero-config, as such, I'd hesitate to pull this into the official with-ant-design example.

That said, here's a working example of both options above utilizing next: ^9.3.5 with antd: ^4.1.4:
1.) Clone the example: [email protected]:mattcarlotta/next-antd-v4.git
2.) Install dependencies: yarn
3.) Run the first option by running: yarn dev
4.) Once done, terminate the process and type: git checkout globals
5.) Run the second option by running: yarn dev

In my opinion, one of the best way to use antd with @ant-design/pro-layout is just to rename all your .css files to .less. LESS is backward compatible with CSS. In this way, you don't need to hack your babel config. It's an easy and less hackable way.

If you need NextJS + antd + @ant-design/pro-layout example, you can check this: https://github.com/8iq/nodejs-hackathon-boilerplate-starter-kit/tree/master/apps/_example04antpro (but, you should use .less extension for your .css files)

@pahaz Your example fails to build for production.

@mattcarlotta could you please explain your setup.
I've added CI action to test the build. CI test for node v10 and node v12
https://github.com/8iq/nodejs-hackathon-boilerplate-starter-kit/runs/615670863

@pahaz Apologies, it was an user error. While this approach works, unfortunately, it's not very flexible for pre-existing projects using Sass. That said, encouraging developers to adopt less over css imports is just another workaround to the original problem: not being able to import CSS from node_modules.

On that note, there is the official with-ant-design-less example that accomplishes a similar result to your example.

Perhaps you may want to submit an example to Vercel that utilizes the @ant-design/pro-layout package.

If anyone from Vercel interested in the example I'll create a PR.

If anyone from Vercel interested in the example I'll create a PR.

Please, I want.

In my opinion, one of the best way to use antd with @ant-design/pro-layout is just to rename all your .css files to .less. LESS is backward compatible with CSS. In this way, you don't need to hack your babel config. It's an easy and less hackable way.

If you need NextJS + antd + @ant-design/pro-layout example, you can check this: https://github.com/8iq/nodejs-hackathon-boilerplate-starter-kit/tree/master/apps/_example04antpro (but, you should use .less extension for your .css files)

If you use less for everything it modifies the global styles for same class names, so to avoid that you can enable css modules and write css files.

I've prepared the repo for less here, https://github.com/mit123suki/next-ant-less.git

For anyone who's still interested, checkout the following repos

Next with Ant-LESS
https://github.com/mit123suki/next-ant-less

Next with Ant-CSS
https://github.com/mit123suki/next-ant-css

@mit123suki Coul you please explain, what the difference between your example and official examples?

https://github.com/zeit/next.js/tree/canary/examples/with-ant-design-less -- less
https://github.com/zeit/next.js/tree/canary/examples/with-ant-design -- css

@mit123suki Coul you please explain, what the difference between your example and official examples?

https://github.com/zeit/next.js/tree/canary/examples/with-ant-design-less -- less
https://github.com/zeit/next.js/tree/canary/examples/with-ant-design -- css

  • Tree shaking using esm,
  • granular imports using babel-plugin-import
  • Ant locales replacement, when using Date-Picker using dayjs plugin reducing antd bundle furthur
  • Enabled local modules with overloaded cssvars.css file so the variables are directly available in css modules.

Overall it leads to reduction in app bundle size and styles are loaded correctly. You can do yarn analyze and compare the results.

@mit123suki Does this line import all styles? Tree shaking using esm only for javascripts?

@mit123suki Does this line import all styles? Tree shaking using esm only for javascripts?

you could remove that line and change the babelrc import antd style to true. It works the same except we now have a conflict order b/w component styles

yes only for javascript files, you can go for purgecss but that's breaking styles

@mit123suki Coul you please explain, what the difference between your example and official examples?
https://github.com/zeit/next.js/tree/canary/examples/with-ant-design-less -- less
https://github.com/zeit/next.js/tree/canary/examples/with-ant-design -- css

  • Tree shaking using esm,
  • granular imports using babel-plugin-import
  • Ant locales replacement, when using Date-Picker using dayjs plugin reducing antd bundle furthur
  • Enabled local modules with overloaded cssvars.css file so the variables are directly available in css modules.

Overall it leads to reduction in app bundle size and styles are loaded correctly. You can do yarn analyze and compare the results.

Can't build from your less repo. It gaves me the following error:
10:16:18.845 import { Row } from '../grid'; 10:16:18.845 ^^^^^^ 10:16:18.845 SyntaxError: Cannot use import statement outside a module

@2huBrulee i forgot add to esm to start script. Pull the latest code. That should fix the error, if not file an issue. Thanks

@2huBrulee which repo is that? " import { Row } from '../grid';" -what is this? Is it antd library? If so, it should be import { Row } from 'antd'. Check my github for my repos.

From your 'less' repo, i did:
yarn
yarn build

And got that error

@Timer, #11837 seems to be using css and not less. This issue is probably broader.

> For anyone who's still interested, checkout the following repos

Next with Ant-LESS
https://github.com/mit123suki/next-ant-less

Next with Ant-CSS
https://github.com/mit123suki/next-ant-css

@mit123suki Hey, this works perfectly at localhost, thanks! But when I try to deploy it to Vercent i get the following error message:

16:47:15.971
Using external babel configuration
16:47:15.971
Location: "/zeit/68a93b6e/.babelrc"
16:47:33.622
Failed to compile.
16:47:33.623
./pages/signin.js
16:47:33.623
Module not found: Can't resolve '../components/Signin' in '/zeit/68a93b6e/pages'
16:47:33.623
Build error occurred
16:47:33.623
Error: > Build failed because of webpack errors
16:47:33.623
at build (/zeit/68a93b6e/node_modules/next/dist/build/index.js:13:900)
16:47:33.733
error Command failed with exit code 1.
16:47:33.733
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
16:47:33.743
Error: Command "yarn run build" exited with 1
16:47:35.695
Done with "package.json"

Edit:
@mit123suki Thanks for response. Yeah, bad of me. I noticed that I had typos in the import. Weird that it worked on localhost.

@RiatIO please open an issue at my repo. Btw I updated the repos recently. So pull the latest code if you haven't already and see if the issue still occurs. Thanks. For anyone who is having problems with the repos, please file an issue there, not here please. Keep this thread clean, Thanks.

My solution:

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

this works!!

@mcyleung mind sharing your config?
I'm using with-ant-design-less example config and @i-tengfei solution but I still have the same problem

@xedef which problem?

I've tried the https://github.com/vercel/next.js/tree/canary/examples/with-ant-design-less as a boilerplate and pushed it to Heroku. I got some pretty low Lighthouse scores and two of the recommended solutions were pretty much leading to the CSS.

Recommended solutions:

  • Removed Unused CSS (which i think comes from the fact that the whole CSS of antd was imported)
  • Minify CSS (Here's what i'm unsure about)

Could anyone help me out?

@raindecastro Ant-design works by importing all necessary CSS when importing the component. Therefore, if you pass in an option that alters its appearance -- like adding the mode="multiple" option to Select -- then the CSS will already be included. Unfortunately, this has the sideEffect of importing other CSS that may not be in use.

The larger problem is that ant-design isn't a small library (48.3 MB unpacked and about 1.5MB+ packed) and with it are a lot of dependencies. Therefore, lower lighthouse scores are kind of expected when using it. This is one of the main reasons why I've slowly migrated away from ant-design to either directly using their react component (rc) dependencies or more recently designing my own UI components.


Take a look at these chunk graphs of with-ant-design-less out-of-the-box:
Ant-design makes up 2.13MB of 3.11MB (parsed)


However... there are two things you can do to reduce the bundle size:

1.) Remove moment locales:
config.plugins.push(new IgnorePlugin(/^\.\/locale$/, /moment$/));

2.) Only export icons from @ant-design/icons/dist that you need:

config.resolve.alias = {
  ...config.resolve.alias,
  "@ant-design/icons/lib/dist$": path.resolve(`./icons/index.js`),
};

icons/index.js (if you import other components that require icons, then they'll need to be manually added to this file)

/**
 * Exports only required ant-design icons (otherwise the entire 500kb library is included)
 *
 */
export { default as CalendarOutline } from "@ant-design/icons/lib/outline/CalendarOutline";
export { default as CloseCircleFill } from "@ant-design/icons/lib/fill/CloseCircleFill";
export { default as DownOutline } from "@ant-design/icons/lib/outline/DownOutline";
export { default as LeftOutline } from "@ant-design/icons/lib/outline/LeftOutline";
export { default as RightOutline } from "@ant-design/icons/lib/outline/RightOutline";

next.config.js

/* eslint-disable */
const { IgnorePlugin } = require("webpack");
const withLess = require("@zeit/next-less");
const lessToJS = require("less-vars-to-js");
const fs = require("fs");
const path = require("path");

// Where your antd-custom.less file lives
const themeVariables = lessToJS(
  fs.readFileSync(path.resolve(__dirname, "./assets/antd-custom.less"), "utf8")
);

module.exports = withLess({
  lessLoaderOptions: {
    javascriptEnabled: true,
    modifyVars: themeVariables, // make your antd custom effective
  },
  webpack: (config, { isServer }) => {
    if (isServer) {
      const antStyles = /antd\/.*?\/style.*?/;
      const origExternals = [...config.externals];
      config.externals = [
        (context, request, callback) => {
          if (request.match(antStyles)) return callback();
          if (typeof origExternals[0] === "function") {
            origExternals[0](context, request, callback);
          } else {
            callback();
          }
        },
        ...(typeof origExternals[0] === "function" ? [] : origExternals),
      ];

      config.module.rules.unshift({
        test: antStyles,
        use: "null-loader",
      });
    } else {
      /* aliases ant icon imports to user-defined icons folder */
      config.resolve.alias = {
        ...config.resolve.alias,
        "@ant-design/icons/lib/dist$": path.resolve(`./icons/index.js`),
      };
      /* strips out moment locales */
      config.plugins.push(new IgnorePlugin(/^\.\/locale$/, /moment$/));
    }
    return config;
  },
});

Take a look at these chunk graphs:
Ant-design still makes up 1.2MB of 2.11MB (parsed)

@mattcarlotta First of all, thank you! That was one of the most in-depth answers i've ever gotten from issues like this! With that being said, even though antd is one of my favourite component libraries, optimizations out of the box seem to be a pretty big downside. I'll first try out two of your recos to reduce bundle size then check out the performance scores from there hoping it would budge a little. Though if it still feels pretty slow, I guess it's time to look for another option. Do you mind if I send you an email? There's something I want to verify and I don't want to overuse this thread.

i just use rsuite now

Was this page helpful?
0 / 5 - 0 ratings