当我们使用nextjs
进行前端SSR
相关开发的时候,想要选用一个UI
框架进行页面渲染的时候,就会发现服务端渲染和客户端页面渲染是如此的不通,我们国内常用的elemet-u
i, ant-design
这些框架都会出现或这样或那样的问题,究其原因主要是目前国内主流的UI框架的页面渲染采用了大量的DOM
操作,而服务端是没有document
对象的。
查阅了网络上的各类UI框架推荐,总结的服务端渲染框架推荐如下:
- MUI: Material-UI组件库,但是新版的样式貌似不支持服务端渲染
- Fluent
- Mantine
- Blueprintjs
- NextUI
- shadcn/ui
如上几个UI
框架我有测试使用的目前也就MUI
、NextUI
这两个框架,有关服务端渲染UI
框架的推荐介绍之后会在使用了解后单独做一个推荐分享,本文主要是来介绍如何在nextjs
中安装nextui
框架。
安装
NextUI
提供了两种安装方式供我们选择:一种是全量安装,一种是增量安装。可以根据需要选择更适合自己的安装方式。
环境要求
- NextJs 12或更高
- React 18或更高
- TailWind CSS 3或更高
- Framer Motion 4或更高
准备工作
在安装之前需要了解的是NextUI
的构建是基于Tailwind CSS
(一种原子类框) 框架的,所以想要能够正常使用NextUI
的话,我们需要提前先安装 Tailwind CSS
, 有关tailwindcss
的安装可参考:Tailwindcss 配置使用指南。
全量安装
1、全量安装是直接安装@nextui-org/react
、 framer-motion
两个库
# 使用npm
$ npm i @nextui-org/react framer-motion
# 使用yarn
$ yarn add @nextui-org/react framer-motion
# 使用pnpm
$ pnpm add @nextui-org/react framer-motion
2. 配置Tailwind CSS
// tailwind.config.js
const {nextui} = require("@nextui-org/react");
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}", // nextui配置
],
theme: {
extend: {},
},
darkMode: "class",
plugins: [nextui()],
};
3、全局应用
安装后配置样式后,我们需要在nextjs
的根节点添加一个全局组件NextUIProvider
来嵌套所有需要使用NextUI
的页面
import * as React from "react";
import {NextUIProvider} from "@nextui-org/react";
function Layout({ children }: { children: ReactElement }) {
// 需要在顶层嵌套
return (
<NextUIProvider>
{ children }
</NextUIProvider>
);
}
可以是在pages/_app.tsx
中使用一个外层的layout来嵌套所有待设计的页面。
增量安装
也许你只是需要使用到个别的NextUI组件,并不想要全局导入,这时我们就可以通过NextUI的增量安装来使用组件。
1、下载安装核心库:@nextui-org/theme
、 @nextui-org/system
、 framer-motion
# npm
$ npm i @nextui-org/theme @nextui-org/system framer-motion
# yarn
$ yarn add @nextui-org/theme @nextui-org/system framer-motion
# pnpm
$ pnpm add @nextui-org/theme @nextui-org/system framer-motion
2、指定组件安装
既然是增量安装,那我们只需要安装我们需要的几个组件就可以了,如我们可以只安装一个Button
组件:
# npm
$ npm i @nextui-org/button
# yarn
$ yarn add @nextui-org/button
# pnpm
$ pnpm add @nextui-org/button
3、Tailwind CSS 配置
这里我们同样的只需要配置指定组件的位置就可以了:
// tailwind.config.js
const {nextui} = require("@nextui-org/theme");
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
// 单个组件样式
"./node_modules/@nextui-org/theme/dist/components/button.js",
// 也可以使用glob的匹配规则实现多个组件的样式匹配
'./node_modules/@nextui-org/theme/dist/components/(button|snippet|code|input).js'
],
theme: {
extend: {},
},
darkMode: "class",
plugins: [nextui()],
};
4、全局应用
使用方式同上:
import * as React from "react";
import {NextUIProvider} from "@nextui-org/react";
function Layout({ children }: { children: ReactElement }) {
// 需要在顶层嵌套
return (
<NextUIProvider>
{ children }
</NextUIProvider>
);
}
注意
需要注意的是当我们使用pnpm
工具来进行库的依赖管理的话,我们需要在我们的项目根目录下的.npmrc
文件添加如下配置:
public-hoist-pattern[]=*@nextui-org/*
文件修改完成后需要使用pnpm install
重写安装依赖,确保依赖的安装正常。
使用
安装完成NextUI后,我们就可以在页面中使用NextUI
的组件了,代码如下:
// page.tsx
import {Button} from '@nextui-org/button';
import clsx from 'clsx';
import styles from './index.module.css';
const ToolkitPage = (props: any) => {
return (
<div className={clsx(styles.document, 'bg-white p-[30px]')}>
<Button color='primary'>按钮</Button>
<Button disabled className='ml-20'>禁用</Button>
</div>
);
};
export default ToolkitPage;
自定义样式
实现NextUI
的自定义样式,我们可以通过如下设置来实现。
组件自定义
在开始使用前我们需要通过NextUIProvider
组件来进行嵌套包裹,这里可以
import * as React from "react";
import {NextUIProvider} from "@nextui-org/react";
function Layout({ children }: { children: ReactElement }) {
// 需要在顶层嵌套
return (
<NextUIProvider className="dark text-foreground bg-background">
{ children }
</NextUIProvider>
);
}
Tailwind CSS配置
需要在tailwind.config.js中配置对应模式的样式格式,在如上的插件nextui():
module.exports = {
plugins: [
nextui({
prefix: "nextui", // prefix for themes variables
addCommonColors: false, // override common colors (e.g. "blue", "green", "pink").
defaultTheme: "light", // default theme from the themes object
defaultExtendTheme: "light", // default theme to extend on custom themes
layout: {}, // common layout tokens (applied to all themes)
themes: {
light: {
layout: {}, // light theme layout tokens
colors: {}, // light theme colors
},
dark: {
layout: {}, // dark theme layout tokens
colors: {}, // dark theme colors
},
// ... custom themes
},
}),
],
};
样式属性支持
themes
配置样式:
type ConfigTheme = {
extend?: "light" | "dark"; // base theme to extend
layout?: LayoutTheme; // see LayoutTheme
colors?: ThemeColors; // see ThemeColors
};
type ConfigThemes = Record<string, ConfigTheme>;
tailwindcss支持配置支持属性
type BaseThemeUnit = {
small?: string;
medium?: string;
large?: string;
};
type FontThemeUnit = {
small?: string;
medium?: string;
large?: string;
tiny?: string;
};
interface LayoutTheme {
/**
* Base unit token that defines a consistent spacing scale across
* the components.
*/
spacingUnit?: number;
/**
* The default font size applied across the components.
*/
fontSize?: FontThemeUnit;
/**
* The default line height applied across the components.
*/
lineHeight?: FontThemeUnit;
/**
* The default radius applied across the components.
* we recommend to use `rem` units.
*/
radius?: BaseThemeUnit;
/**
* A number between 0 and 1 that is applied as opacity-[value] when
* the component is disabled.
*/
disabledOpacity?: string | number;
/**
* The default height applied to the divider component.
* we recommend to use `px` units.
*/
dividerWeight?: string;
/**
* The border width applied across the components.
*/
borderWidth?: BaseThemeUnit;
/**
* The box shadow applied across the components.
*/
boxShadow?: BaseThemeUnit;
}
支持颜色配置:
type ColorScale = {
50: string;
100: string;
200: string;
300: string;
400: string;
500: string;
600: string;
700: string;
800: string;
900: string;
foreground: string; // contrast color
DEFAULT: string;
};
type BaseColors = {
background: ColorScale; // the page background color
foreground: ColorScale; // the page text color
divider: ColorScale; // used for divider and single line border
overlay: ColorScale; // used for modal, popover, etc.
focus: ColorScale; // used for focus state outline
content1: ColorScale; // used for card, modal, popover, etc.
content2: ColorScale;
content3: ColorScale;
content4: ColorScale;
};
// brand colors
type ThemeColors = BaseColors & {
default: ColorScale;
primary: ColorScale;
secondary: ColorScale;
success: ColorScale;
warning: ColorScale;
danger: ColorScale;
};