在 “NodeJS系列(8)- Next.js 框架 (一) | 安装配置、路由(Routing)、页面布局(Layout)” 里,我们简单介绍了 Next.js 的安装配置,创建了 nextjs-demo 项目,讲解和演示了 Next.js 项目的运行、路由(Routing)、页面布局(Layout)等内容。
在 “NodeJS系列(9)- Next.js 框架 (二) | 国际化 (i18n)、中间件 (Middleware)” 里,我们在 nextjs-demo 项目基础上,讲解和演示了 Next.js 项目的国际化 (i18n)、中间件 (Middleware) 等内容。
在 “NodeJS系列(10)- Next.js 框架 (三) | 渲染(Rendering)” 里,我们在 nextjs-demo 项目基础上,讲解和演示了渲染(Rendering)。
在 “NodeJS系列(11)- Next.js 框架 (四) | 数据获取(Data Fetching) ” 里,我们在 nextjs-demo 项目基础上,讲解和演示了数据获取(Data Fetching)。
本文继续在 nextjs-demo 项目(Pages Router)基础上,讲解和演示样式 (Styling) 、部署(Deploying)等内容。
NextJS: https://nextjs.org/
NextJS GitHub: https://github.com/vercel/next.js
1. 系统环境
操作系统:CentOS 7.9 (x64)
NodeJS: 16.20.0
NPM: 8.19.4
NVM: 0.39.2
NextJS: 13.4.12
2. 样式 (Styling)
Next.js 支持如下的应用程序样式设置方式:
(1) 全局 CSS:对于那些有传统 CSS 经验的人来说,使用起来很简单,也很熟悉,但随着应用程序的发展,可能会导致更大的 CSS 捆绑包和管理样式的困难。
(2) CSS 模块:创建本地作用域的 CSS 类,以避免命名冲突并提高可维护性。
(3) JS 中的 CSS:直接在 JavaScript 组件中嵌入 CSS,实现动态和范围化的样式。
(4) Sass:一个流行的 CSS 预处理器,它通过变量、嵌套规则和 mixin 等功能扩展 CSS。
(5) Tailwind CSS:一个实用程序优先的 CSS 框架,允许通过组成实用程序类来快速定制设计。
1) 全局 CSS
在 nextjs-demo 项目里有一个 src/styles/globals.css 文件,这是由 create-next-app nextjs-demo 命令自动创建的,它就是 nextjs-demo 项目的一个全局 CSS 文件。内容如下:
... html, body { max-width: 100vw; overflow-x: hidden; } ...
全局 CSS,顾名思义,就要将该文件里 CSS 能应用于 nextjs-demo 项目里的全部页面和组件。 由于这种样式表的全局性,为了避免冲突,只能在 src/pages/_app.js 中导入它们。
修改 src/pages/_app.js 文件,内容如下:
import '../styles/globals.css' export default ({ Component, pageProps }) => { return ( <Component {...pageProps} /> ) }
2) CSS 模块
Next.js 内置支持使用 *.module.CSS 扩展名的 CSS 模块。
CSS 模块通过自动创建一个唯一的类名来对 CSS 进行本地作用域。这允许您在不同的文件中使用相同的类名,而不用担心冲突。这种行为使 CSS 模块成为包含组件级 CSS 的理想方式。
示例,一个可重用按钮组件,创建 components/Button.module.css 文件,内容如下:
/* You do not need to worry about .error {} colliding with any other `.css` or `.module.css` files! */ .error { color: white; background-color: red; }
创建 components/Button.js 文件,内容如下:
import styles from './Button.module.css' export function Button() { return ( <button type="button" // Note how the "error" class is accessed as a property on the imported // `styles` object. className={styles.error} > Destroy </button> ) }
3) JS 中的 CSS
JS 解决方案中可以使用任何现有的 CSS 。最简单的是内联样式:
function Test() { return <p style={{ color: 'red' }}>Test Page</p> } export default Test
我们捆绑样式的 jsx,以提供对独立作用域 CSS 的支持。其目的是支持类似于 Web 组件的“shadow CSS”,不幸的是,Web 组件不支持服务器渲染,仅支持JS。
function HelloWorld() { return ( <div> Hello world <p>scoped!</p> <style jsx>{` p { color: blue; } div { background: red; } @media (max-width: 600px) { div { background: blue; } } `} </style> <style global jsx>{` body { background: black; } `}</style> </div> ) } export default HelloWorld
4) Sass
Next.js 内置了对 Sass 的支持,同时使用 .scs 和 .sas 扩展。可以通过 CSS 模块 和 .module.scssor.module.sess 扩展名使用组件级 Sass。
需要先安装 sass,命令如下:
$ npm install --save-dev sass
Sass 支持两种不同的语法,每种语法都有自己的扩展名。.sscs 扩展要求使用 scss 语法,而 .sass 扩展则要求使用缩进语法(“sass”)。 如果不确定该选择哪一个,可以从 .scs 扩展开始,它是 CSS 的超集,不需要学习缩进语法(“Sass”)。
(1) 自定义 Sass 选项
如果要配置 Sass 编译器,请使用 next.config.js 中的 sassOptions。格式如下:
import path from 'path' module.exports = { sassOptions: { includePaths: [path.join(__dirname, 'styles')], }, }
(2) Sass 变量
Next.js 支持从 CSS 模块文件导出的 Sass 变量。例如,使用导出的 primaryColor Sass 变量。
src/styles/variables.module.scss 文件,内容如下:
$primary-color: #64ff00; :export { primaryColor: $primary-color; }
src/pages/_app.js 文件,内容如下:
import variables from '../styles/variables.module.scss' export default function MyApp({ Component, pageProps }) { return ( <Layout color={variables.primaryColor}> <Component {...pageProps} /> </Layout> ) }
5) Tailwind CSS
Tailwind CSS 是一个实用程序优先的 CSS 框架,与 Next.js 配合得非常好。
需要先安装 Tailwind CSS,命令如下:
$ npm install -D tailwindcss postcss autoprefixer
$ npx tailwindcss init -p
(1) 配置 Tailwind
在 tailwind.config.js 中,为将使用 Tailwind CSS 类名的文件添加路径:
/** @type {import('tailwindcss').Config} */ module.exports = { content: [ './app/**/*.{js,ts,jsx,tsx,mdx}', // Note the addition of the `app` directory. './pages/**/*.{js,ts,jsx,tsx,mdx}', './components/**/*.{js,ts,jsx,tsx,mdx}', // Or if using `src` directory: './src/**/*.{js,ts,jsx,tsx,mdx}', ], theme: { extend: {}, }, plugins: [], }
不需要修改 postss.config.js。
(2) 导入样式
将 Tailwind CSS 指令添加到应用程序中的全局样式表中,修改 src/styles/globals.css 文件,添加如下内容:
@tailwind base;
@tailwind components;
@tailwind utilities;
在 src/pages/_app.js中,导入 globals.css 样式表,将样式应用于应用程序中的每个页面和组件。
(3) 使用类
在安装了 Tailwind CSS 并添加了全局样式后,可以在应用程序中使用 Tailwind 的实用程序类。示例:
export default () => {
return <h1 className="text-3xl font-bold underline">Hello, Next.js!</h1>
}
3. 部署(Deploying)
部署的含义是构建一个优化的可用于生产环境的 Web 应用程序版本,把这个版本部署实际的生成环境。这里的生产环境有如下几种:
(1) 使用 Node.js 或 Docker 自托管 Next.js,并支持所有功能。
(2) 静态导出 HTML ,部署到第三方 Web 服务器,比如 Nigix、Apache 等,这种方式有些功能不能用。
(3) 将 Next.js 应用程序部署到 Vercel (https://vercel.com/new/clone)、AWS Copilot 等云服务商。
1) 构建 (Next build)
构建生产版本,运行如下命令:
$ npm run build
标准输出包括:
(1) 使用 getStaticProps 或自动静态优化的页面的 HTML 文件
(2) 全局样式或单独作用域样式的 CSS 文件
(3) 用于从 Next.js 服务器预呈现动态内容的 JavaScript
(4) 通过 React 在客户端进行交互的 JavaScript
输出生成的文件在 .next 文件夹中:
.next/static/chunks/pages – 此文件夹中的每个 JavaScript 文件都与具有相同名称的路由相关。例如,.next/static/chunks/pages/about.js 将是在应用程序中查看 /about 路由时加载的 JavaScript 文件
.next/static/media – 从 next/image 静态导入的图像被散列并复制到此处
.next/static/css – 应用程序中所有页面的全局 css 文件
.next/server/pages – 从服务器预渲染的 HTML 和 JavaScript 入口点。.nft.json 文件是在启用输出文件跟踪时创建的,包含依赖于给定页面的所有文件路径。
.next/server/chunks – 在整个应用程序的多个位置使用的共享 JavaScript 块
.next/cache–next.js - 服务器的构建缓存和缓存图像、响应和页面的输出。使用缓存有助于减少构建时间并提高加载图像的性能
启动生产版本,运行如下命令:
$ npm run start
2) 部署生产版本到 Docker 环境
(1) Docker 环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Linux 用户: docker (非 root 用户,有 sudo 权限)
Docker 版本: 20.10.7
Docker Compose 版本: 2.6.1
注:Docker Compose 相关介绍,请参考 “Docker基础知识 (4) - Docker Compose”
NodeJS 目录:/home/docker/nodejs
将生产版本(运行过 npm run build 命令)的 nextjs-demo 目录整体复制到 /home/docker/nodejs 目录下,并修改 /home/docker/nodejs/nextjs-demo 目录及其子目录的读写权限,格式如下:
$ chmod -R 777 /home/docker/nodejs/nextjs-demo
(2) 创建 docker-compose.yml
在 /home/docker/nodejs/nextjs-demo 目录下,创建 docker-compose.yml 文件,内容如下:
version: "3.7" services: service_nodejs: image: nodejs:16.20 restart: always container_name: nodejs_service ports: - 3000:3000 networks: - service-network volumes: - /home/docker/nodejs:/home/docker/nodejs:rw working_dir: /home/docker/nodejs/nextjs-demo entrypoint: ["npm", "start"]
(3) 运行
$ cd /home/docker/nodejs/nextjs-demo # 进入 docker-compose.yml 所在目录
# 在后台运行
$ docker-compose up -d
[+] Running 2/2
⠿ Network nextjs-demo_default Created 0.0s
⠿ Container node_service Started 0.2s
$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES
507db5566b60 node:16.20 "npm start" 0.0.0.0:3000->3000/tcp, ... node_service
使用浏览器访问 http://192.168.0.10:3000, 显示 nextjs-demo 项目的 index 页面。