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

Work with antd? #484

Closed
thebetterjort opened this issue Dec 22, 2016 · 44 comments
Closed

Work with antd? #484

thebetterjort opened this issue Dec 22, 2016 · 44 comments

Comments

@thebetterjort
Copy link

I'm trying to get nextjs to work with antd but get

"You may need an appropriate loader to handle this file type."

What do I need to do in order to get these things working together? Thanks.

@arunoda
Copy link
Contributor

arunoda commented Dec 22, 2016

May be that's related to importing .css files.
Currently, we don't support importing custom modules.

Even if you've added a correct webpack-loader, it won't work since SSR env cannot import that.

@thebetterjort
Copy link
Author

https://github.com/ant-design/babel-plugin-import#via-babelrc

This is no help then. Is custom modules on the map, or not so much because of SSR?

@arunoda
Copy link
Contributor

arunoda commented Dec 22, 2016

We wanted to support it.
But I think we need to work a bit harder for that.
So, that's after a priority after 2.0

@thebetterjort
Copy link
Author

Thanks Arunoda! I seem to have followed you from meteor. Nice to see you around.

@sedubois
Copy link
Contributor

Is is still planned for after 2.0? Should this be reopened then?

@soulmachine
Copy link
Contributor

+1 for antd

@liadbiz
Copy link

liadbiz commented Feb 10, 2017

feature supported now? I am tring to use antd with nextjs

@timneutkens
Copy link
Member

@liadbiz have a look here #544

@liadbiz
Copy link

liadbiz commented Feb 11, 2017

@timneutkens thanks. I will give feedback after tring.

@jozanza
Copy link

jozanza commented Feb 16, 2017

Just thought I'd chime in since this seems to be a bit of a tricky issue in next.js.
Anyhow here's how I'm able to use antd's css imports in my project: #544 (comment)

@AugustinLF
Copy link
Contributor

@jozanza do you have a working example of this? Where you render an antd component? And how you then import the css? Because I can't make it work :'(

@blakedietz
Copy link

blakedietz commented Mar 18, 2017

@AugustinLF I've figured out an example if you're interested. I haven't made a really in depth application so I don't know if any other problems exist yet, but I've been able to import a Button component and have it display.

If you clone this example: https://github.com/zeit/next.js/tree/master/examples/with-global-stylesheet

Then import that antd styling like so in an app level component.

components/App.js

import styles from 'antd/dist/antd.css';

export default ({ children }) => (
  <main>
    <style dangerouslySetInnerHTML={{ __html: styles}} />
    {children}
  </main>
)

Then in any of your pages, I'm using index.js as an example:

import App from '../components/App'
import Header from '../components/Header'
import withData from '../lib/withData'

import { Button } from 'antd';

export default withData((props) => (
  <App >
    <Header pathname={props.url.pathname} />
    <Button>Test</Button>
  </App>
))

And voila you have an antd styled button. Again, I'm still learning to see if this works without issue, so I'm going to continue playing with this solution. Unfortunately I haven't found a solution for importing a single component's set of styles at a time so this will be kind of expensive over the network.

@AugustinLF
Copy link
Contributor

Yes, thank you, it worked out for me!

@MrLoh
Copy link

MrLoh commented Apr 9, 2017

Yeah, that works pretty well. You can also enable global imports like this import { Button, Input, Form } from 'antd' by using the babel-plugin-import. Loading all the CSS is not such a big issue, since it is just 43 KB gzipped.

@PhanXuanThuan
Copy link

#484

@rdewolff
Copy link

rdewolff commented Apr 11, 2017

Do you recommend the approach from @blakedietz ?

@MrLoh
Copy link

MrLoh commented Apr 11, 2017

I compiled the less files in the static folder, since I needed my own theming and then just added a style tag, but the end result is about the same I think

@ouxu
Copy link

ouxu commented May 6, 2017

OK, I solved it, but you must to import the whole css, such as me, I import the css file in Head. Just see the code:

layout/index.js

import Head from 'next/head'
export default ({children}) => (
  <div>
    <Head>
      <link rel='stylesheet' href='http://cdn.bootcss.com/antd/2.9.3/antd.css' />
    </Head>
    {children}
  </div>
)

pages/index.js

import React from 'react'
import Layout from '../layout'
import { Button } from 'antd'
export default () => (
  <Layout>
    <Button type="primary">Primary</Button>
  </Layout>
)

And to import on demand, we should add babel plugins, please run npm install -D babel-plugin-import at first.

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
  	["import", {
           "libraryName": "antd",
           "style": false
        }]
  ]
}

That's all, good luck to you!

@viztor
Copy link
Contributor

viztor commented Jul 2, 2017

This issue still exists today.
it seems SSR just won't support global css import.

@Ikhan
Copy link

Ikhan commented Jul 2, 2017

I'm also having this issue. I'm trying to import semantic.min.css but couldn't. Throws me an error.

@thebetterjort
Copy link
Author

Next.JS with Ant design example

@tconroy
Copy link

tconroy commented Aug 5, 2017

any way to do it without linking to an external stylesheet? Would like to keep everything in JS if possible..

@kriscarle
Copy link

I was able to theme antd by using https://github.com/erasmo-marin/styled-jsx-plugin-less

couple of caveats:

  1. It forces you to use less in all of your styled jsx. I'm new to less and discovered there are a few gotchas like needing to wrap certain css lines like height: ~"calc(100% - 50px)"
  2. you still have to load the entire style (Possibly there is a way to deconstruct antd's less and only import what you need, maybe following how they do it in babel-import-plugin)

Here is my .babelrc

{
  "presets": [
    [
      "next/babel",
      {
        "styled-jsx": {
          "plugins": [
            "styled-jsx-plugin-less"
          ]
        }
      }
    ]
  ],
  "plugins": [
    "transform-decorators-legacy",
    [
      "import",
      {
        "libraryName": "antd",
        "style": false
      }
    ]
  ]
}

Then in my layout component below the next.js <Head></Head> tag I have

<style jsx global>{`
  @import "./node_modules/antd/dist/antd.less";
  @primary-color: red;
 `}
</style>

@truca
Copy link

truca commented Feb 19, 2018

this works as a charm:
https://github.com/hanpama/next-with-antd

  1. add packages
yarn add antd babel-plugin-inline-import
  1. configure babelrc: add the .babelrc file from that project

  2. copy the pages/index.js file to that same path in your project

  3. restart next

  4. reopen localhost:3000

@ghost
Copy link

ghost commented Mar 9, 2018

@truca why didn't you make use of this? isn't this possible in latest next?
https://ant.design/docs/react/getting-started#Import-on-Demand

I suppose that inline approach imports entire ant stylesheet, will that not affect loading performance?

@kriscarle
Copy link

Just tested antd with the new next-less plugin for next v5.x and it works great when pointing it directly to antd/dist/antd.less

Only note is that antd isn't compatible with the new less v3.x yet, had to revert to v2.7

This is still including the entire style. @crushy26 yes, since the latest next now runs webpack on the server side, it should be possible to use babel-plugin-import I'll try that next.

@amrdraz
Copy link

amrdraz commented Mar 26, 2018

@kriscarle do you have an example of what you did?

@and3rsonsousa
Copy link

Look at the of this example and you can make it work.

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

@kriscarle
Copy link

@amrdraz here is a Gist with my current config, it supports a custom theme, but still includes the entire style: https://gist.github.com/kriscarle/d3136e9b15634846036397409bf98214

@and3rsonsousa thanks! I hadn't noticed that the example was updated.

It is still using the css option in babel-plugin-import not the less option, so won't support custom themes but I think it is getting close. When I get a chance, I'll look into whether I can get the less theming working using the new example.

@and3rsonsousa
Copy link

You just have to see the example on Ant site abou using less. I did it and it was very easy to configure.

@brandonmp
Copy link
Contributor

brandonmp commented Apr 11, 2018

i've tried a dozen different ways of achieving antd + next without requiring the entire css file. the only way i've managed to make it work so far is (might require styled-components or similar):

  1. enable inline css imports w/ the babel-plugin-inline-import:
 [
            "inline-import",
            {
                "extensions": [".css"]
            }
        ],
  1. Create a new directory with 1 file for each antd component, eg components/antd/Table.js

  2. import (a) the JS imported from antd/lib/*, (b) the css from the components style folder, and (c) injectGlobal from styled-components

  3. Inject the css into the global scope and export. so this is what table looks like:

import Table from 'antd/lib/table';
import Styles from 'antd/lib/table/style/index.css';
import { injectGlobal } from 'styled-components';

injectGlobal`${Styles}`;
export default Table;

Now, ideally, we could do this:

import Table from 'antd/lib/table';
import Styles from 'antd/lib/table/style/index.css';
import styled from 'styled-components';

export default styled(Table)`${Styles}`;

... which would scope styles locally, which is great. but as of next 3/4 (when I set this up), something was stopping that from working. So, I used injectGlobal.

The big pro with this approach is that all the CSS is inlined, so it lands in the client rendered and ready (also helps w/ page speed, per google pagespeed insights).

The cons are that it's a pain in the ass to set up, plus a few gotchas:

  1. some components call for styles from some other components. eg Slider uses styles from lib/slider and lib/tooltip, and Form requires grid/style, so in each case you've gotta import both (protip: Transfer uses styles from 5 diff't components)

  2. some stuff, like animations, doesn't live in any specific component's css, so i had to extract those and import them separately (also using injectGlobal). here's a gist with all the animations, etc.

  3. You probably want to import the antd icon font separately as well, since a lot of components rely on it

Oh, and if you're using typescript, don't forget to declare .css imports:

declare module '*.css' {
    const styles: string;
    export default styles;
}

@delikat
Copy link

delikat commented Jun 11, 2018

i got modular antd imports working with babel-plugin-import and less themes: https://gist.github.com/delikat/d50cf9c8bce8b8f469a8eaacab170ac3

so far i've been seeing decent size improvements vs. including the entire antd less file (especially minified). you can configure theme overrides with modifyVars, though note that you lose css HMR this way. if you want HMR while developing a theme you could import a simple less file like:

@import "~antd/dist/antd.less";
@primary-color: #E27AD3;

then remove it and move your overrides over to modifyVars when you're ready to deploy.

@giautm
Copy link
Contributor

giautm commented Jun 11, 2018

@delikat :Hi, There is an example with Antd + LESS. 😄
https://github.com/zeit/next.js/blob/canary/examples/with-ant-design-less/next.config.js

@kriscarle
Copy link

@delikat Awesome, thank you for figuring it out! I was completely defeated by this, too much Webpack magic required :)

@giautm in your example, it looks like the next-less plugin is still importing the entire style file? Probably fine for most people and definitely is a much cleaner config in Next. The babel-plugin-import + modifyVars config is the one we've been trying to crack. It filters the built css to only what is needed for the imported components. Though looks like it requires a lot more hacking of the default webpack config, so probably much more likely to break in future versions.

@delikat
Copy link

delikat commented Jun 11, 2018

Actually it looks like we can simplify the required custom config by following the with-ant-design example's lead and overriding require's loader for .less files when running on the server. I've updated the gist above as well 🐱

@giautm
Copy link
Contributor

giautm commented Jun 13, 2018

@delikat hi, your gist ran into this error on Production start, look like it was not processed by less-loader in build steps.

{ /Users/admin/xxxx/node_modules/antd/lib/style/index.less:1
(function (exports, require, module, __filename, __dirname) { @import "./themes/default";
                                                              ^

SyntaxError: Invalid or unexpected token
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:152:10)
    at Module._compile (module.js:624:28)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/admin/xxxx/node_modules/antd/lib/button/style/index.js:3:1) sourceMapsApplied: true }

@delikat
Copy link

delikat commented Jun 13, 2018

hi @giautm, yes it looks like overriding require.extensions doesn't work in prod. I did a quick test and the original solution I posted, excluding antd files from webpack externals, seems to work fine after build and start. I've updated the gist to reflect that.

@giautm
Copy link
Contributor

giautm commented Jun 13, 2018

@delikat It's still not working. dir was not defined in your gist.

Update: Yah, I found it in the first version of your gist. It's worked

@tanint
Copy link
Contributor

tanint commented Jun 14, 2018

@delikat It work, big thank 👍

@Vi-jay
Copy link

Vi-jay commented Jul 27, 2018

@delikat It work,thx,but cssModules can't work again !

@Enalmada
Copy link
Contributor

Enalmada commented Sep 8, 2018

I tried creating a few more pages following the with-ant-design/index.js pattern and the css fails to load when you click the new pages. (with-ant-design-less didn't seem to have this problem) Could someone confirm I am not crazy that the with-ant-design example pattern has css loading issues if add new antd components to new pages and click around? I don't want new users to hit a brick wall when they try to scale out the example to more pages.

I assume the "transform-decorators-legacy" stuff in package.js and .babelrc is no longer necessary with next6 because next6 uses babel7? I would appreciate if someone who knows can confirm/deny that before I do push request to remove something I don't understand.

The example code would be better starting point for new users if it was using modular imports...antd css is just too big for production. Just adding antd dependency made my release zip go from 20m to 50m (insert swearing here). The example from @delikat seems to work...anyone object to it being part of the example? Note that I had some trouble using it with next 6 so my fixes are here with notes in comments: https://gist.github.com/Enalmada/c0a83bbc639aae5d4504527a0fe18f41
@timneutkens Can next.js provide a better more programatic way to get "antd" into the config.externals.push section? It is extremely brittle the way it has to be done now. Could next.js provide a way we can call the webpack.js/externalsConfig function with an argument list containing "antd"?

So why does HMR not work with this solution? Could someone elaborate on that please? I am curious if it is a solvable problem?
Until then, to get modular import performance and have hot reloading in dev...is there a better solution than this:
assets/styles.less (explicit reminder here to remove antd.less from the styles.less file)
@import "./antd-custom.less";
asserts/antd.less
@import "~antd/dist/antd.less";
index.js (load the full css in development to get HMR)
... if (process.env.NODE_ENV === 'development') { require('./asserts/antd.less') } ...

@chen900112
Copy link

I asked for more help #5180

@tavurth
Copy link

tavurth commented Jul 26, 2019

Look at the of this example and you can make it work.

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

Thank you, this helped me get it working!

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 31, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests