Can’t help but say, when writing this, really good hungry!

Description: Bright white and dark theme switching practice for ANTD in NextJS. Online preview: The portal switches themes in a drop-down menu on the page, and is currently available in black and white, all white and Diablo. Code repository: vue3-admin

preview

Antd-theme-webpack-plugin is a webPack plugin. The following will be built step by step

This plugin is based on using the Webpack environment, so we are not looking to see if anyone has developed a plugin that supports Vite. What has been done in projects that support server-side rendering is similar in projects that apply client-side rendering on a single page.

Set up the project

Aside from adding redux, ditchingnextJS ‘own CSS and using the withCss plugin, adding less\sass, and supporting modu-style content, the content is simple enough to look at the code.

Adding topic dependencies

yarn add -D antd-theme-webpack-plugin
Copy the code

Configuration items

1. Add a custom theme

Add vars. Less to the Styles folder, something like this:

// This file will contain all varibales, our custom varibales and
//those from Ant Design which we want to override.
@import '~antd/lib/style/themes/default.less';
@primary-color: @green-6;
@select-item-selected-option-color: @primary-color;
@processing-color: @primary-color;
@select-item-selected-bg: @background-color-base;
@secondary-color: @primary-color;
@skeleton-color: @primary-color;
@btn-primary-bg: @primary-color;

:root {
  --PC: @primary-color;
}
Copy the code

This is from the Nextjs demo

2. Add the next configuration

next.config.js

const AntDesignThemePlugin = require('antd-theme-webpack-plugin');
// The antd-theme-Generator plug-in is available in the dependencies above, so it does not need to be installed
const { getLessVars } = require('antd-theme-generator');

// This step is to read the main theme variable that we preset (which is not hot updated).
const themeVariables = getLessVars(path.join(__dirname, './src/styles/vars.less'));

// Read the dark theme
constdarkVars = { ... getLessVars('./node_modules/antd/lib/style/themes/dark.less'),
  '@picker-basic-cell-active-with-range-color': 'darken(@primary-color, 20%)'
};

// Make the theme white
constlightVars = { ... getLessVars('./node_modules/antd/lib/style/themes/compact.less')};// This step generates the corresponding theme file when starting or building the project, which is used for import in the project
// Best gitignore the generated file is automatically generated each time
fs.writeFileSync('./src/config/dark.json'.JSON.stringify(darkVars));
fs.writeFileSync('./src/config/light.json'.JSON.stringify(lightVars));
fs.writeFileSync('./src/config/theme.json'.JSON.stringify(themeVariables));

// This is the theme plug-in configuration item
const themeOptions = {
  stylesDir: path.join(__dirname, './src'),
  antDir: path.join(__dirname, './node_modules/antd'),
  varFile: path.join(__dirname, './src/styles/vars.less'),
  themeVariables: Array.from(
    new Set([
      ...Object.keys(darkVars),
      ...Object.keys(lightVars),
      ...Object.keys(themeVariables)
    ])
  ),
  indexFileName: false.// We need to put the generated less file in a place where the production environment can get it directly via the link, so we put this file in public
  outputFilePath: path.join(__dirname, './public/color.less'),
  generateOnce: false
};

module.exports = withPlugins([withLess], {
  lessLoaderOptions: {
    javascriptEnabled: true.importLoaders: 1
  },
  webpack: (config, options) = > {
    // Add the theme switch WebPack plugin
    config.plugins.push(newAntDesignThemePlugin(themeOptions)); }}Copy the code

Even though this is the most important part of the configuration, you’ll start using the content generated by the configuration later

3. Add switching topics

Since there are no HTML files in Nextjs, we can’t add tags directly to the content like the NextJS demo, but we can work around it a bit.

Select _app.tsx under Pages to add this content dynamically

Note: If something like github.com/zhoubangfu/… If you use cross-component state management such as Redux or Mobx, you may not be able to submit actions in the theme of the Provider. You can choose to do so in a deeper common component, such as Layout.

_app.tsx

import { useEffect } from 'react';

// Import JSON during the development phase and use it directly in the online environment
import darkVars from '.. /config/dark.json';
import lightVars from '.. /config/light.json';
// import themeVars from '.. /config/theme.json';

const Layout = ({ Component, pageProps }) = > {
  useEffect(() = > {
    window['less'] = {
      async: true.env: 'production'
    };

    const script = document.createElement('script');

    // Wait until less is loaded to avoid errors
    script.addEventListener('load'.() = > {
      window['less']
        .modifyVars(
          config.name === 'light' ? lightVars : darkVars
        )
        .catch((error) = > {
          console.error(error);
        });
    });
    
    Less version 2.7.3 will throw errors when running in the browser, so you can check it out yourself
    script.src = 'https://cdn.bootcdn.net/ajax/libs/less.js/2.7.3/less.min.js';
    document.body.appendChild(script);

    const css = document.createElement('link');
    css.href = '/color.less';
    css.rel = 'stylesheet/less';
    css.type = 'text/css';
    document.body.appendChild(css); } []);return (<Component {. pageProps} / >);
};

export default Layout;
Copy the code

As you can see from the code, the only way to switch themes is to run window.less. ModifyVars, so we just need to bind the time in the switch theme drop down box to it

4. Adapt to sASS

Instead of taking the less variable and using it directly in sass (there may be a way), the approach I took on this blog is the simplest way to switch skins: change the external className and add a dark corresponding style.

This way, after calling window.less. ModifyVars, you can submit the redux action to change the corresponding state and then switch the external class, which is a less laborious and difficult method.

Write in the end

The solution came from the Web, and the author just took the time to put it together. Again, the main content comes from the NextJS Github demo.