SolidZORO / next-plugin-antd-less

🎩 Use Antd (Less) with Next.js v12, Zero Dependency on other Next-Plugins.
MIT License
345 stars 48 forks source link

withAntdLess pluginOptions override withPlugins nextConfig #84

Closed krmao closed 2 years ago

krmao commented 2 years ago

the code bellow webpack config not work, don't recognize the webpack alias config , if move in withAntdLess is ok, this is confict

node server error

error - ./src/pages/_app.js:3:0
Module not found: Can't resolve '@styles/basic-global-vars.css'
  1 | //region 全局样式一次引入
  2 | import 'antd/dist/antd.css'
> 3 | import '@styles/basic-global-vars.css'
  4 | import '@styles/basic-global.css'
  5 | //endregion

next.config.js

const path = require('path')
const webpackRules = require("./webpack.config.js");
const withPlugins = require("next-compose-plugins");
const withBundleAnalyzer = require('@next/bundle-analyzer')({enabled: process.env.ANALYZE === 'true'})
const withAntdLess = require('next-plugin-antd-less');

const IS_PRODUCTION_ENV = process.env.NODE_ENV === "production";
console.log("\n[ ENV  ]  NODE_ENV:'" + process.env.NODE_ENV + "',", "IS_PRODUCTION_ENV:" + IS_PRODUCTION_ENV + "\n");

const lessPlugin = withAntdLess({
    // optional
    modifyVars: {'@primary-color': '#f74a49'},
    // optional
    lessVarsFilePathAppendToEndOfContent: false,
    cssModules: true,
    // optional https://github.com/webpack-contrib/css-loader#object
    cssLoaderOptions: {
        // https://github.com/webpack-contrib/css-loader#object
        sourceMap: true,
        // Other Config Here...
    },
    webpack: (config) => config,
});

module.exports = withPlugins([withBundleAnalyzer, lessPlugin],
    {
        distDir: "./build/.next",                                       // 编译文件的输出目录
        generateEtags: true,                                            // 是否给每个路由生成Etag
        pageExtensions: ['jsx', 'js'],                                  // 在pages目录下那种后缀的文件会被认为是页面
        useFileSystemPublicRoutes: true,                                // https://nextjs.frontendx.cn/docs/#%E7%A6%81%E6%AD%A2%E6%96%87%E4%BB%B6%E8%B7%AF%E7%94%B1
        generateBuildId: async () => process.env.BUILD_ID ? process.env.BUILD_ID : new Date().toDateString(), // 返回 null 使用默认的 unique id
        webpackDevMiddleware: config => config,                         // 修改webpackDevMiddleware配置
        exportPathMap: function () {                                    // https://nextjs.org/docs/api-reference/next.config.js/exportPathMap
            return {
                "/": {page: "/"}
            };
        },
        onDemandEntries: {                                              // 页面内容缓存配置
            maxInactiveAge: 25 * 1000,                                  // 内容在内存中缓存的时长(ms)
            pagesBufferLength: 2,                                       // 同时缓存多少个页面
        },
        env: {                                                          // 可以在页面上通过 process.env.testEnv 获取 value
            testEnv: 'testEnv',
        },
        sassOptions: {
            includePaths: [path.join(__dirname, 'styles')],             // https://github.com/YutHelloWorld/Blog/issues/12#issue-254066318
        },
        serverRuntimeConfig: {                                          // 通过 'next/config' 来读取, 只有在服务端渲染时才会获取的配置
            testServerRuntimeConfig: 'testServerRuntimeConfig'
        },
        publicRuntimeConfig: {                                          // 在服务端渲染和客户端渲染都可获取的配置
            testPublicRuntimeConfig: 'testPublicRuntimeConfig',
        },
        webpack(config, {buildId, dev, isServer, defaultLoaders}) {     // 手动修改webpack config
            console.log("webpack config buildId:", buildId, "dev:", dev, "isServer:", isServer, "defaultLoaders:", defaultLoaders);
            config.module.rules.push({
                ...webpackRules,
            });
            return config;
        },
        webpack5: true,
    })

webpack.config.js

// https://juejin.cn/post/6850418109484892168
// https://webpack.docschina.org/configuration/resolve/
// https://www.jetbrains.com/help/idea/2021.1/using-webpack.html#specify_webpack_configuration_file

const path = require('path');

module.exports = {
    resolve: {
        alias: {
            '@': path.resolve(__dirname),
            '@public': path.resolve(__dirname, './public'),
            '@basic': path.resolve(__dirname, './src/basic'),
            '@styles': path.resolve(__dirname, './src/basic/styles'),
            '@utils': path.resolve(__dirname, './src/basic/utils'),
            '@components': path.resolve(__dirname, './src/components'),
        }
    }
};
SolidZORO commented 2 years ago
// babel.config.js

// eslint-disable-next-line func-names
module.exports = function (api) {
  api.cache(true);

  return {
    presets: [['next/babel']],
    plugins: [
      ['import', { libraryName: 'antd', style: true }],
      ['module-resolver', { alias: { '@': './src' } }],  <--- add this plugin? `babel-plugin-module-resolver`
      ['inline-react-svg'],
      ['add-react-displayname'],
    ],
  };
};
krmao commented 2 years ago

this will build sucess but render error

wait  - compiling...
event - build page: /
event - compiled successfully
Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check your code at index.jsx:110.
    at BasicLayout (webpack-internal:///./src/components/basic-layout/index.jsx:57:5)
    at div
    at FormProvider (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/rc-field-form/lib/FormContext.js:26:31)
    at LocaleProvider (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/antd/lib/locale-provider/index.js:45:37)
    at ProviderChildren (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/antd/lib/config-provider/index.js:103:24)
    at LocaleReceiver (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/antd/lib/locale-provider/LocaleReceiver.js:39:37)
    at ConfigProvider (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/antd/lib/config-provider/index.js:210:13)
    at MyApp (webpack-internal:///./src/pages/_app.js:51:16)
    at AppContainer (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/next/dist/server/render.js:293:27)
[LIFECYCLE](Document) constructor
[LIFECYCLE](Document) render
error - Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
    at ReactDOMServerRenderer.render (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/react-dom/cjs/react-dom-server.node.development.js:4053:17)
    at ReactDOMServerRenderer.read (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/react-dom/cjs/react-dom-server.node.development.js:3690:29)
    at Object.renderToString (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/react-dom/cjs/react-dom-server.node.development.js:4298:27)
    at Object.renderPage (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/next/dist/server/render.js:596:45)
    at Function.getInitialProps (webpack-internal:///./node_modules/next/dist/pages/_document.js:194:19)
    at Function.getInitialProps (webpack-internal:///./src/pages/_document.js:33:85)
    at Object.loadGetInitialProps (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/next/dist/shared/lib/utils.js:69:29)
    at renderDocument (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/next/dist/server/render.js:609:48)
    at Object.renderToHTML (/Users/krmao/workspace/template/pc/nextjs-v11-antd-pc/node_modules/next/dist/server/render.js:647:34)
    at runMicrotasks (<anonymous>) {
  page: '/'
}

image

const webpackRules = require("./webpack.config.js");
const path = require("path");

module.exports = function (api) {
    api.cache(true);

    const presets = [["next/babel"]];
    const plugins = [
        ["import", {libraryName: "antd", libraryDirectory: "lib", style: true}, "antd"],
        [
            "import",
            {
                libraryName: "@ant-design/icons",
                libraryDirectory: "lib/icons",
                camel2DashComponentName: false,
                style: false
            },
            "@ant-design/icons"
        ],
        [
            require.resolve("babel-plugin-module-resolver"),
            {
                root: ["./src/"],
                alias: {
                    "@public": path.resolve(__dirname, "./public"),
                    "@basic": path.resolve(__dirname, "./src/basic"),
                    "@styles": path.resolve(__dirname, "./src/basic/styles"),
                    "@utils": path.resolve(__dirname, "./src/basic/utils"),
                    "@components": path.resolve(__dirname, "./src/components")
                }
            }
        ]
    ];

    return {
        presets,
        plugins
    };
};
krmao commented 2 years ago

and find another import bug, npm run analyze not work, no output and no open browser

module.exports = withBundleAnalyzer;// npm run analyze ok
module.exports = withPlugins([withBundleAnalyzer, lessPlugin], nextConfig); // npm run analyze failure no output
module.exports = withPlugins([withBundleAnalyzer], nextConfig); // npm run analyze ok

my config

both the withAntdLess and withPlugins with the same next config the bable will find the alias


const path = require("path");
const webpackRules = require("./webpack.config.js");
const withPlugins = require("next-compose-plugins");
const withBundleAnalyzer = require("@next/bundle-analyzer")({enabled: process.env.ANALYZE === "true"});
const withAntdLess = require("next-plugin-antd-less");

const IS_PRODUCTION_ENV = process.env.NODE_ENV === "production"; console.log( "\n[ ENV ] NODE_ENV:'" + process.env.NODE_ENV + "',", "APP_ENV:'" + process.env.APP_ENV + "',", "IS_PRODUCTION_ENV:'" + IS_PRODUCTION_ENV + "'\n" );

const nextConfig = { distDir: "./build/.next", // 编译文件的输出目录 generateEtags: true, // 是否给每个路由生成Etag pageExtensions: ["jsx", "js"], // 在pages目录下那种后缀的文件会被认为是页面 useFileSystemPublicRoutes: true, // https://nextjs.frontendx.cn/docs/#%E7%A6%81%E6%AD%A2%E6%96%87%E4%BB%B6%E8%B7%AF%E7%94%B1 generateBuildId: async () => (process.env.BUILD_ID ? process.env.BUILD_ID : new Date().toDateString()), // 返回 null 使用默认的 unique id webpackDevMiddleware: (config) => config, // 修改webpackDevMiddleware配置 exportPathMap: function () { // https://nextjs.org/docs/api-reference/next.config.js/exportPathMap return { "/": {page: "/"} }; }, onDemandEntries: { // 页面内容缓存配置 maxInactiveAge: 25 * 1000, // 内容在内存中缓存的时长(ms) pagesBufferLength: 2 // 同时缓存多少个页面 }, env: { // 可以在页面上通过 process.env.testEnv 获取 value testEnv: "testEnv" }, sassOptions: { includePaths: [path.join(__dirname, "src/basic/styles")] // https://github.com/YutHelloWorld/Blog/issues/12#issue-254066318 }, serverRuntimeConfig: { // 通过 'next/config' 来读取, 只有在服务端渲染时才会获取的配置 testServerRuntimeConfig: "testServerRuntimeConfig" }, publicRuntimeConfig: { // 在服务端渲染和客户端渲染都可获取的配置 testPublicRuntimeConfig: "testPublicRuntimeConfig" }, webpack(config, {buildId, dev, isServer, defaultLoaders}) { // 手动修改webpack config // console.log("webpack config buildId:", buildId, "dev:", dev, "isServer:", isServer, "defaultLoaders:", defaultLoaders);

    config.module.rules.push({
        ...webpackRules
    });

    // https://react-svgr.com/docs/webpack/
    // https://ant.design/components/icon-cn/#%E8%87%AA%E5%AE%9A%E4%B9%89-SVG-%E5%9B%BE%E6%A0%87
    config.module.rules.push({
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: [
            {
                loader: "babel-loader"
            },
            {
                loader: "@svgr/webpack",
                options: {
                    babel: false,
                    icon: true
                }
            }
        ]
    });
    return config;
},
webpack5: true

};

const lessPlugin = withAntdLess({ modifyVars: {"@primary-color": "#f74a49"}, // optional lessVarsFilePathAppendToEndOfContent: false, // optional cssModules: true, // optional https://github.com/webpack-contrib/css-loader#object cssLoaderOptions: {sourceMap: true}, // https://github.com/webpack-contrib/css-loader#object ...nextConfig });

module.exports = withPlugins([withBundleAnalyzer, lessPlugin], nextConfig); // npm run analyze failure no output

SolidZORO commented 2 years ago

Sorry, your question is too complex for me to answer, so I'll close this issue.