出发点缘由:
需实:码字一切的根源来源于寂寞孤独,为什么YOU不给我介绍OBJECT
实:目前需求不太饱和,自娱自乐,牛马命😭
效果图
一、项目初始化
首先创建项目:
npx create-next-app@latest
会提示你一堆问题,全都用推荐配置就好👇
Next.js 官方模板已经帮你装好 TypeScript、ESLint、Tailwind、App Router 了。
剩下的依赖库我们后面慢慢加。然后目前项目基本情况就是无需任何配置,即可使用tailwindcss来快速构建你心心念念的页面了🍭。
二、先搞个 favicon 图标
网站没图标那肯定不得行。
可以上 realfavicongenerator.net
把你的 logo 转成 favicon.ico。
然后把它丢到 app/ 下。
浏览器自动识别。
浏览器在标签页上显示网站的小图标(favicon),无需在head进行配置
三、安装运行依赖 & 配置环境变量
说白了就是:
开发依赖 (-D) 是你写代码时用的,
运行依赖 是线上跑项目时用的。
npm install -D cross-env
我没选 dotenv / dotenv-cli(ps:我觉得安装两个包不如安装一个包🤣),
因为 cross-env 已经够用了。
新建环境变量文件
在根目录新建:
.env.development
.env.production
文件名nextjs文档有说这个它的环境变量规范
内容如下:
NEXT_PUBLIC_APP_ENV=
NEXT_PUBLIC_PACKAGE_NAME=
NEXT_PUBLIC_EMAIL=
NEXT_PUBLIC_CDN=/
NEXT_PUBLIC_BASE_URL=
NEXT_PUBLIC_GOOGLE_URL=
四、修改 package.json 脚本
改成下面这样:
"scripts": {
"clean": "rmdir /s /q .next || rm -rf .next",
"dev:dev": "cross-env NODE_ENV=development npm run clean && next dev",
"dev:prod": "cross-env NODE_ENV=production npm run clean && next dev",
"build:dev": "cross-env NODE_ENV=development npm run clean && next build",
"build:prod": "cross-env NODE_ENV=production npm run clean && next build",
"start": "next start",
"lint": "eslint"
}
"clean": "rmdir /s /q .next || rm -rf .next",运行项目的时候next缓存报错,进行一个clean清除next缓存异常问题。
五、工具函数 utils/env.ts
把环境变量统一导出:
export const ENV = process.env.NEXT_PUBLIC_APP_ENV;
export const PACKAGE_NAME = process.env.NEXT_PUBLIC_PACKAGE_NAME;
export const EMAIL = process.env.NEXT_PUBLIC_EMAIL;
export const CDN = process.env.NEXT_PUBLIC_CDN;
export const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
export const GOOGLE_URL = process.env.NEXT_PUBLIC_GOOGLE_URL;
六、验证环境变量
在 app/page.tsx 中写个简单页面:
import Image from "next/image";
import { PACKAGE_NAME, EMAIL } from "@/utils/env";
export default function Home() {
return (
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
<Image
className="dark:invert"
src="/images/logo.png"
alt="Next.js logo"
width={100}
height={100}
priority
/>
<h1 className="text-4xl font-bold text-zinc-900 dark:text-white">
{PACKAGE_NAME}
</h1>
<p className="text-lg text-zinc-700 dark:text-zinc-300">{EMAIL}</p>
</main>
</div>
);
}
打开页面 → 能正常显示出变量值说明环境变量配置成功!
恭喜,你也太棒了,孩纸 👏👏👏
七、开整首页轮播
一个像样的官网首页,少不了轮播图,用来播放美女😘。
我选的是 Swiper —— 稳健。
npm i swiper
八、目录结构 & Header 组件
项目结构如图:
Header
用 Tailwind 写得干净利落,天然响应式支持:
"use client";
import { CDN, PACKAGE_NAME } from "@/utils/env";
import { useState } from "react";
import { useRouter, usePathname } from "next/navigation";
export default function Header() {
const [open, setOpen] = useState(false);
const router = useRouter();
const pathname = usePathname();
return (
<>
<div className="h-[64px]" />
<header
className={`flex justify-between fixed left-0 top-0 w-full h-[64px] px-[20px] z-10 lg:px-[60px] ${
["/protocol", "/contact"].includes(pathname) &&
"bg-slate-950 lg:bg-white"
}`}
>
<span className="flex items-center">
<img src={`${CDN}images/logo.png`} className="w-[32px] h-[32px]" />
<span
className={`text-white font-[700] text-[15px] ml-[5px] ${
["/protocol", "/contact"].includes(pathname) && "lg:text-black"
}`}
>
{PACKAGE_NAME}
</span>
</span>
{open ? (
<img
src={`${CDN}images/close.svg`}
className="w-[30px] lg:hidden"
onClick={() => setOpen(false)}
/>
) : (
<img
src={`${CDN}images/menu.svg`}
className="w-[30px] lg:hidden"
onClick={() => setOpen(true)}
/>
)}
{/* 菜单 */}
<ul
className={`absolute left-0 w-full top-[64px] bg-white shadow-lg rounded-b-[10px] ${
open ? "block" : "hidden"
} lg:static lg:bg-transparent lg:inline-flex lg:items-center`}
>
{[
{ path: "/", label: "Home" },
{ path: "/protocol", label: "Privacy Policy" },
{ path: "/contact", label: "Contact us" },
].map((item) => (
<li
key={item.path}
onClick={() => router.push(item.path)}
className={`px-[20px] py-[10px] text-[15px] cursor-pointer ${
pathname === item.path && "text-black"
}`}
>
{item.label}
</li>
))}
</ul>
</header>
</>
);
}
九、Home 页面布局
home/Panel.tsx:
import { CDN } from "@/utils/env";
import Header from "../../Header";
import Main from "../Main";
export default function Panel() {
return (
<main
style={{ "--bg": `url('${CDN}images/bg.png')` } as React.CSSProperties}
className="w-screen h-screen overflow-auto bg-no-repeat bg-cover bg-[image:--bg] font-[Roboto]"
>
<Header />
<Main />
</main>
);
}
十、Swiper 主内容
home/Main.tsx:
"use client";
import { CDN, PACKAGE_NAME, GOOGLE_URL } from "@/utils/env";
import { Swiper, SwiperSlide } from "swiper/react";
import { Navigation, Autoplay, Pagination } from "swiper/modules";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
export default function Main() {
return (
<main className="lg:flex lg:flex-row-reverse lg:items-center lg:justify-center lg:h-[calc(100%-64px)] px-4 lg:px-0">
<div className="relative mt-[20px] max-w-[700px] w-full mx-auto lg:w-[700px]">
<Swiper
className="w-full"
loop
slidesPerView={1}
modules={[Navigation, Autoplay, Pagination]}
autoplay={{ delay: 2000 }}
pagination={{ clickable: true }}
navigation
autoHeight
>
{[1, 2, 3, 4, 5].map((i) => (
<SwiperSlide key={i} className="flex justify-center items-center py-4">
<img
src={`${CDN}images/swiper${i}.png`}
className="w-[60%] h-full object-contain rounded-[10px] mx-auto mb-[10px]"
/>
</SwiperSlide>
))}
</Swiper>
</div>
<div className="text-center mt-[20px] lg:text-left lg:mr-[20px] lg:mt-0 xl:mr-[40px] lg:pl-[20px]">
<img
src={`${CDN}images/logo.png`}
className="w-[72px] h-[72px] inline-block rounded-[10px]"
/>
<h2 className="text-white text-[30px] font-[900] my-[10px] lg:text-[64px] max-w-[600px] mx-auto lg:mx-0">
{PACKAGE_NAME}
</h2>
<img
src={`${CDN}images/google.png`}
className="w-[194px] inline-block active:scale-95 mt-4 cursor-pointer"
onClick={() => (window.location.href = `${GOOGLE_URL}`)}
/>
</div>
</main>
);
}
Swiper 轮播 + 响应式布局,官网质感直接拉满。
到这里,你的官网首页就 **基本完工 **。\
去动物园玩,猴哥问我说香蕉哪去了,我给猴哥一耳屎,我TM装起来了🤦♂️🤦♂️🤦♂️🤦♂️。
十一、几点踩坑分享
- Next.js 的
<Image fill>虽然自动拉伸很好用,但有时会因为父容器没设置 position 导致错位;
所以我还是倾向自己给宽高。 - Swiper 的样式记得全局引入,否则分页点和箭头样式不生效。
- 线上要用 CDN 时,
NEXT_PUBLIC_CDN改为你自己的资源地址。
✨ 写在最后
至此,我们的 Next.js 官网首页已经跑起来了。
从环境变量到轮播图,全程无黑魔法,纯手工搭建。
这样一个轻量级,落落大方,seo完美,性能优秀,天然无添加的nextjs官网,难道你就没有一丝丝行动?
不心动,自行捏爆魔丸。