Closed poyiding closed 4 years ago
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’d 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’m 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 next@9.3 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):
With "libraryDirectory": "es"
(antd is now tree shaked not showing as the biggest chunk)
@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:
git clone git@github.com:mattcarlotta/antd-example.git
yarn
yarn outputs
to traverse through the different branches: master
, dynamic
, and unoptimized
to build production files and to display the resulting chunk graphs.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:
-----------------------------------------------------------------
| 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)
-----------------------------------------------------------------
| 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: git@github.com: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.
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 :
here is my next-config.js