当今快速发展的网站开发领域,Next.js以其独特的优势和便捷的功能,成为了前端开发者的新宠。Next.js是一个开源的JavaScript框架,它建立在流行的JavaScript库React之上,专为构建用户界面而设计。作为一个专门用于构建网络应用程序的框架,Next.js被广泛描述为一个用于服务端渲染或静态生成应用程序的React框架。通过提供一系列工具和约定,Next.js极大地简化了基于React的网络应用程序的开发过程,使得构建快速、高性能且可扩展的网站变得更加容易。
Next.js提供的附加功能能够让你构建生产就绪的应用程序,这些功能包括路由、优化渲染、数据获取、打包、编译等等。最吸引人的一点是,使用Next.js时,你不需要安装额外的包,因为Next.js提供了你所需的一切。要实现这些功能,只需遵循Next.js的观点和约定即可。
通过这些特性,Next.js为开发者提供了一个功能丰富、灵活且高效的平台,用于构建各种规模和复杂度的Web应用。无论是企业级应用、电商网站还是个人博客,Next.js都能够提供强大的支持,使得Web开发更加简单、快捷,并且能够达到高性能的要求。学习和掌握Next.js,无疑会让你在现代Web开发的道路上更加得心应手。
打开你的命令行工具(如终端、命令提示符或PowerShell),并执行以下命令,记得将<app-name>替换为你的项目名称:
npx create-next-app@latest <app-name>
这个命令会自动从npm下载并执行create-next-app脚本,创建一个使用最新版本的Next.js的新项目。在这个过程中,脚本可能会询问你是否想要配置TypeScript、ESLint或Tailwind CSS等选项。根据你的项目需求,跟随提示进行选择。
项目创建完成后,通过以下命令切换到项目目录:
cd <app-name>
然后,启动开发服务器:
npm run dev
执行此命令后,Next.js会启动一个本地开发服务器,并且通常会自动打开你的默认网页浏览器显示你的新Next.js应用。如果没有自动打开,你可以手动访问http://localhost:3000来查看你的应用。
在Next.js中,路由是构建Web应用程序的基础之一,其独特的基于文件系统的路由机制为开发者提供了高效且直观的页面管理方式。通过简单地在代码库中添加文件和文件夹,你可以定义用户可以在浏览器中访问的URL路径。下面是几个关于Next.js路由的学习场景,让我们更深入地了解如何在Next.js应用中实现和管理路由。
场景1:访问根目录
当用户访问根目录(即localhost:3000)时,显示主页。你可以通过在src/app目录下创建page.tsx文件来实现这一点。
// src/app/page.tsx
export default function Home() {
return <h1>Home Page</h1>;
}
这段代码定义了一个简单的React组件,当用户访问应用的根目录时,将展示“Home Page”。
场景2:访问/about页面
当用户访问localhost:3000/about时,显示关于页面。在src/app/about目录下创建page.tsx文件来实现。
// src/app/about/page.tsx
export default function About() {
return <h1>About Page</h1>;
}
场景3:嵌套路由
Next.js允许通过在文件夹内创建文件夹来创建路由层次结构。
// src/app/blog/page.tsx
export default function Blog() {
return <h1>Blog Page</h1>;
}
// src/app/blog/first/page.tsx
export default function FirstBlog() {
return <h1>First Blog Page</h1>;
}
这种方式适用于简单的应用程序结构,但对于复杂的应用程序可能不是最佳选择。
场景4:动态路由
动态路由允许基于URL中提供的参数动态生成页面。这意味着,你无需为每个可能的路由创建单独的静态页面,而是可以使用动态路由来处理URL中的模式或参数。
// src/app/products/[productId]/page.tsx
export default function ProductDetails({ params }: { params: { productId: string }; }) {
return (
<>
<h1>Details about product {params.productId}</h1>
</>
);
}
在Next.js中,"Catch all"路由是一种强大的路由特性,它允许你匹配包括零个、一个或多个路径段的路由。这种方式非常适用于当你需要构建像文档页面这样的复杂和灵活的路由结构时。通过使用双括号[[...slug]]语法,你可以创建一个能够捕获所有传入请求的动态路由,并且根据URL的不同部分呈现不同的内容。
示例解读
在提供的示例中,我们创建了一个Docs组件,它利用"catch all"路由来展示文档页面。这个组件能够根据URL中slug参数的不同,渲染出不同的文档内容。这里的slug是一个数组,它包含了URL中捕获的所有动态段。
// src/app/docs/[[...slug]]/page.tsx
export default function Docs({params}: {
params: {
slug: string[];
};
}) {
// 检查slug参数的长度,以决定渲染哪种内容
if (params.slug?.length===2) {
return <h1>Viewing docs for feature {params.slug[0]} and concept {params.slug[1]}</h1>;
} else if (params.slug?.length===1) {
return <h1>Viewing docs for feature {params.slug[0]}</h1>;
}
// 如果没有提供slug参数,渲染默认的文档页面
return <h1>Docs Page</h1>;
}
优势
使用"catch all"路由的优势在于,它为构建具有灵活路由需求的应用程序(如文档网站、博客平台等)提供了简单而强大的解决方案。开发者可以轻松地管理和展示变化多端的内容,而无需为每个可能的URL变体单独设置路由规则。这不仅提高了开发效率,也使得应用架构更加清晰和易于维护。
在Next.js中处理404错误页面是一个简单而直接的过程,通过定义一个特定的组件,你可以为用户提供一个更友好的错误提示页面,而不是默认的浏览器错误页面。这对于改善用户体验和维持网站的专业形象非常重要。
通过在src/app目录下创建一个not-found.tsx文件,你可以定义一个NotFound组件,当用户尝试访问一个不存在的页面时,将显示该组件。
// src/app/not-found.tsx
export default function NotFound() {
return (
<>
<h2>Page not found</h2>
<p>Could not find requested resource</p>
</>
);
}
在Next.js中,当用户尝试访问一个不存在的路由时,Next.js会自动查找并渲染pages/404.js或src/pages/404.js文件(取决于你的项目结构)。如果你在这些位置定义了自定义404页面,Next.js将渲染你定义的页面而不是默认的404页面。
在Next.js中使用私有文件夹是管理项目文件结构的一个高效方式,尤其适合于那些想要将UI逻辑与路由逻辑分离、维护项目内部文件组织一致性、在代码编辑器中排序和分组文件、以及避免未来Next.js文件命名规范可能带来的命名冲突的开发者。通过简单地在文件夹名称前加上下划线_,你可以轻松地创建私有文件夹,这些文件夹及其所有子文件夹都会被Next.js的路由系统自动忽略。
假设你有一些库文件或者一些只供内部使用的组件,你不希望这些文件或组件被当作页面对外提供服务。你可以将这些文件放在一个前缀为下划线的文件夹中,比如_lib。
// src/app/_lib/page.tsx
export default function PrivateRoute() {
return <h1>You can't view this in the browser</h1>;
}
在上面的例子中,尽管我们创建了page.tsx文件,由于它位于_lib文件夹下,访问localhost:3000/_lib将会显示404错误,因为Next.js自动将_lib及其子文件夹从路由系统中排除了。
在Next.js中组织和管理路由时,有时候我们需要逻辑上对路由进行分组,而又不希望这种分组影响到URL路径结构。这种需求在实际开发中非常常见,例如,你可能想要将所有与身份验证相关的页面(如登录、注册、忘记密码等)放在同一个文件夹下以提高开发体验,但又不想在URL中体现这种文件结构。
使用路由分组解决问题
Next.js提供了一种简便的方法来实现这一点:路由分组。通过在文件夹名周围添加括号,你可以告诉Next.js这个文件夹是用于逻辑分组的,并且不应该影响到URL的结构。
例如,如果不使用路由分组,你可能会将登录页面放在/pages/auth/login.tsx,这将导致页面的URL为localhost:3000/auth/login。但是,如果你想要保持login页面的URL为localhost:3000/login,同时又想在项目文件中将这个页面放在auth分组下,你可以通过路由分组来实现。
实现路由分组
要实现路由分组,只需要将相关的文件夹用括号括起来。以下是具体操作步骤:
通过这种方式,login页面的物理路径可能是/pages/(auth)/login.tsx,但是在浏览器中访问这个页面的URL将会是localhost:3000/login,而不是localhost:3000/auth/login。
路由分组的好处
通过利用Next.js的路由分组功能,你可以在确保URL路径简洁的同时,对项目中的文件和路由进行有效的逻辑分组,这对于大型项目的开发和维护来说尤为重要。
在构建Web应用时,常常需要某些UI元素(如头部导航和底部信息)在多个页面间共享。这种需求通过使用布局(Layouts)来实现最为高效。布局允许开发者定义一个组件作为页面的共享结构,然后将特定的页面内容注入到这个结构中。Next.js通过支持布局,使得管理和重用页面结构变得简单。
根布局(Root Layout)
根布局是应用于所有路由的布局。你可以创建一个layout.js或layout.tsx文件来定义根布局,然后在其中包括所有页面共享的元素,如头部和底部。根布局组件应该接受一个children属性,这个属性在渲染时会被填充为子页面。
// 示例:定义根布局
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<header>
<p>Header</p>
</header>
{children}
<footer>
<p>Footer</p>
</footer>
</body>
</html>
);
}
嵌套布局(Nested Layout)
嵌套布局用于特定的路由段,只有当这些路由段处于活动状态时,定义在内部的布局才会被渲染。通过在特定文件夹下定义layout.js(例如app/dashboard/layout.js),你可以为那个路由段及其子路由提供专用的布局。
// 示例:定义特定路由段的嵌套布局
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div>
<nav>
<p>Dashboard Navigation</p>
</nav>
{children}
</div>
);
}
这种方式允许你为应用中的不同部分定义不同的布局结构,如仪表板、博客部分等,每个部分都可以有自己的头部导航、侧边栏或其他共享元素。
使用布局的好处
使用根布局和嵌套布局,你可以灵活地定义应用的页面结构,同时保持代码的清晰和组织性。这是构建大型应用时管理页面布局的一种高效方法。
在今天的文章中,我们一起探索了Next.js这个强大的JavaScript框架,从基本概念到路由、布局以及私有文件夹的高级特性,每一点都旨在帮助你更好地理解如何利用Next.js构建高性能、易于维护的现代Web应用。无论你是刚开始接触Web开发的新手,还是希望提升项目质量的资深开发者,Next.js都提供了丰富的功能和灵活性,以满足不同的开发需求。
我们的探索之旅还远没有结束。在下篇文章中,我将继续深入分享Next.js的更多精彩内容,每一篇文章都旨在为你揭开Next.js高效开发的更多秘密,助你在Web开发的道路上更加得心应手。
别忘了关注「前端达人」,这里不仅有深入浅出的技术文章,还有最新的前端趋势解读,帮助你保持技术的前瞻性和竞争力。你的关注、点赞和转发是对我最大的支持,也是我持续分享高质量内容的动力。
着现代Web应用的发展,用户界面变得越来越复杂,同时用户对应用的响应速度和互动性有着更高的期待。在这样的背景下,Next.js 作为一个前沿的React框架,提供了一系列高级功能来满足开发者的需求,今天我们来介绍 Next.js 14 的第二部分。
Next.js 14 初学者指南 (一)
在当今这个信息爆炸的时代,拥有一个高可见度的网站已成为许多企业和个人的追求。搜索引擎优化(SEO)是实现这一目标的重要手段。为了让你的Next.js应用更好地被搜索引擎发现,Next.js引入了一个非常实用的功能——元数据API。通过这个API,你可以为每个页面定义元数据,确保当你的页面被分享或索引时显示准确、相关的信息。
1. 静态元数据的配置
静态元数据是指在构建时确定的有关页面的信息,并且在运行时不会改变。这些元数据与特定页面相关联,可以包括标题和描述等数据。例如,如果你有一个关于页面,你可以这样配置它的静态元数据:
//src/app/about/page.tsx
export const metadata={
title: "关于我",
};
export default function About() {
return <h1>关于我</h1>;
}
通过这种方式,当你的“关于我”页面被搜索引擎索引或被分享到社交媒体时,其标题会正确地显示为“关于我”。
2. 动态生成的元数据
与静态元数据不同,动态元数据允许你根据运行时的动态数据或条件生成页面的元数据。这对于那些内容经常变化或依赖于用户输入的页面非常有用。比如,你有一个展示产品详情的页面,可以这样配置其元数据:
import { Metadata } from "next";
type Props={
params: {
productId: string;
};
};
export const generateMetadata=({ params }: Props ): Metadata=> {
return {
title: `产品 ${params.productId} 的详情`,
};
};
export default function ProductDetails({ params }: Props) {
return <h1>产品 {params.productId} 的详情</h1>;
}
甚至,你可以使用异步函数来生成元数据,这在你需要从数据库或API获取数据时特别有用:
export const generateMetadata=async ({ params }: Props): Promise<Metadata>=> {
const title=await new Promise((resolve)=> {
setTimeout(()=> {
resolve(`产品 ${params.productId}`);
}, 100);
});
return { title: `产品 ${title} 的详情`, };
};
3、元数据规则
4、title metadata
关于元数据中的title属性,这是一个非常关键的部分,它直接影响到你的页面在搜索引擎中的显示标题以及用户在浏览器标签页中看到的内容。title可以是一个字符串或者是一个对象,这取决于你想如何控制标题的显示。
当你在layout.tsx文件中定义元数据时,title字段提供了几个有趣的选项来增加灵活性:
//layout.tsx
export const metadata: Metadata={
title: {
absolute: "",
default: "",
template: "%s | 网站名称",
},
description: "",
};
这个功能特别适合那些页面结构复杂、需要精细控制每个页面标题的网站。通过在不同级别(全局布局、页面布局、单独页面)精心设计title的设置,可以确保无论用户进入网站的哪个部分,都能通过标题快速了解内容,并通过模板确保网站的整体品牌一致性得到维护。
举个例子,如果你的一个页面没有指定特定的标题,那么它就会使用default中的值。而当页面指定了自己的标题时,template中定义的模式就会发挥作用,自动将页面的标题和网站名称进行组合,形成一个既清晰又具有品牌特色的标题展示。
这种灵活性和自动化的结合,不仅使得SEO优化变得简单,而且还能在提升用户体验的同时,加强网站品牌的影响力。
通过精心设计每个页面的元数据,不仅可以提高网站的搜索引擎排名,还能提升用户体验,增加点击率。在社交媒体时代,一个吸引人的页面标题和描述可以大大增加内容的分享率。而Next.js提供的元数据API,让这一切变得简单而直接。
在构建一个动态且互动性强的网站时,页面间的导航是不可或缺的一环。Next.js 为此提供了非常便利的解决方案——Link 组件和 useRouter 钩子,让客户端导航变得既简单又高效。
Link 组件是 Next.js 中用于实现路由跳转的主要方式,它基于 HTML 的 <a> 元素进行了扩展,使得在 Next.js 应用中的路由之间进行导航变得非常简便。使用 Link 组件时,你只需要导入它并指定 href 属性为目标路径即可:
import Link from "next/link";
<Link href="/blog">博客</Link>
有时候,我们需要在代码中根据某些条件或逻辑来动态导航到不同的页面,这时就可以使用 Next.js 提供的 useRouter 钩子。useRouter 允许你访问路由对象,通过这个对象,你可以控制应用的路由行为,例如进行页面跳转。
以下是一个使用 useRouter 进行程序化导航的示例:
import { useRouter } from "next/router";
const MyComponent=()=> {
const router=useRouter();
const handleClick=()=> {
console.log("下单");
router.push("/"); // 使用 router.push 方法跳转到首页
};
return (
<button onClick={handleClick}>下单</button>
);
}
在这个例子中,当用户点击“下单”按钮时,handleClick 函数会被触发,然后应用会使用 router.push("/") 代码来跳转到首页。这种方式非常适合在用户完成某些操作后需要自动跳转页面的场景。
无论是通过 Link 组件还是 useRouter 钩子进行导航,Next.js 都为开发者提供了极大的便利和灵活性。通过这些工具,你可以轻松地在你的应用中实现复杂的导航逻辑,为用户提供流畅且富有互动性的网页体验。
在构建现代Web应用时,开发者常常需要在多个页面之间共享某些布局或样式。Next.js的模板(Templates)功能就是为此而生。模板类似于布局(Layouts),它们都可以包裹每个子布局或页面。但模板和布局在功能上有一定的差异,特别是在处理页面导航时。
模板的特性
当用户在共享同一模板的不同路由之间导航时,模板会呈现一些独特的行为:
定义模板
定义模板非常简单,你只需要创建一个默认导出的React组件,这个组件可以从template.js或template.tsx文件中导出。这个组件通常会接受children作为其属性,并在其内部渲染这些子元素:
export default function Template({ children }: { children: React.ReactNode }) {
return <div>{children}</div>
}
模板使用场景
模板特别适合于那些需要在多个页面之间共享相同布局,但又希望在每次页面跳转时能够完全重置状态和DOM的场景。这可以确保用户在不同页面间导航时,能够获得一致且干净的体验,而不必担心前一个页面的状态影响到当前页面。
通过明智地使用模板,你可以在保持代码组织和复用性的同时,为用户提供流畅且一致的浏览体验。
loading.tsx 文件在 Next.js 应用中扮演着特别的角色,它允许开发者为特定路由段创建加载状态,这些加载状态在内容加载时展示给用户。使用 loading.tsx 可以有效地提升用户体验,特别是在网络环境较差或内容较多需要较长时间加载的场景下。
创建加载状态
在 loading.tsx 文件中,你可以定义一个或多个加载状态的 React 组件。这些组件可以是简单的动画,如旋转的加载指示器,或者更复杂的占位符布局,如骨架屏。
// loading.tsx
export default function Loading() {
return (
<div className="loading-container">
<p>内容加载中,请稍候...</p>
{/* 这里可以添加加载动画或图标 */}
</div>
);
}
使用加载状态
当用户导航到一个新的路由段,而这个路由段的内容还在加载时,你定义的加载状态会立即显示给用户。这提供了一个视觉反馈,让用户知道应用正在响应其操作,并且内容正在积极加载中。这样可以避免用户在看到空白页面时感到困惑或者认为应用出现了问题。
提升用户体验
利用 loading.tsx 实现的加载状态可以大大提升应用的用户体验:
在设计加载状态时,重要的是要保持它的简洁和与应用整体风格的一致性。加载状态不仅是一种功能性需求,也是提升品牌体验和应用专业度的机会。
在构建现代web应用时,有效地管理和响应错误是至关重要的。Next.js 通过文件系统层次结构中的 error.tsx 文件,为开发者提供了一种灵活而强大的方式来创建和管理错误UI,以及处理特定路由段的错误。
创建针对性的错误UI
通过在应用的不同路由级别添加 error.tsx 文件,你可以为这些路由定制特定的错误处理UI。这种方法使得在用户遇到错误时,能够展示更具体、更友好的错误消息和恢复选项,而不是一个通用的错误页面。
// 使用 'use client' 来指明这些错误组件必须是客户端组件
'use client';
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: ()=> void;
}) {
useEffect(()=> {
// 将错误记录到错误报告服务中
console.error(error);
}, [error]);
return (
<div>
<h2>出错了!</h2>
<button onClick={()=> reset()}>
重试
</button>
</div>
);
}
隔离错误影响
将 error.tsx 文件放置于应用的不同级别,能够帮助你更精确地控制错误的影响范围。例如,在特定的路由段出现错误时,只有那部分内容会展示错误信息,应用的其他部分仍然可以正常工作。这样既提高了应用的鲁棒性,也优化了用户体验。
错误恢复功能
在 error.tsx 中,你可以提供恢复功能,如重试按钮,允许用户尝试从错误中恢复,而无需重新加载整个页面。这种快速响应错误并尝试恢复的能力,对于保持应用的交互性和用户满意度至关重要。
嵌套路由中的错误处理
通过在嵌套的文件夹结构中不同级别放置 error.tsx 文件,你可以实现更细粒度的错误处理。这意味着,你可以为应用中的不同部分定制不同的错误处理策略和UI,使错误处理更加灵活和用户友好。
这种方法利用了Next.js的文件系统路由和组件模型,提供了一种既简洁又强大的错误处理机制,帮助开发者构建更加可靠和用户友好的应用。
Next.js 的并行路由是一种高级路由机制,允许在同一布局中同时渲染多个页面,极大地增强了页面布局和内容管理的灵活性。通过使用名为“插槽(slots)”的功能,开发者可以以模块化的方式组织内容。
定义插槽
要定义一个插槽,我们使用 @folder 命名约定。然后,每个插槽作为属性传递给其对应的 layout.tsx 文件。
以仪表盘为例,你可以使用并行路由同时渲染用户、收入和通知页面:
// dashboard/layout.tsx
export default function DashboardLayout({
children,
users,
revenue,
notifications
}: {
children: React.ReactNode;
users: React.ReactNode;
revenue: React.ReactNode;
notifications: React.ReactNode;
}) {
return (
<>
<div>{children}</div>
<div>{users}</div>
<div>{revenue}</div>
<div>{notifications}</div>
</>
);
}
并行路由的一个优势是它们能够将单个布局划分为各种插槽,使代码更易于管理。
独立的路由处理
布局的每个插槽,例如用户分析或收入指标,都可以有自己的加载和错误状态。在不同页面部分以不同速度加载或遇到独特错误的场景中,这种细粒度的控制尤其有益。
路由内的子导航
你的仪表盘的每个插槽都可以实质上作为一个小应用程序运行,完备自己的导航和状态管理。这在诸如仪表盘这样的复杂应用中特别有用,不同部分服务于不同的目的。
//dashboard/@notifications/page.tsx
export default function Notifications() {
return (
<div>通知</div>
<Link href="/dashboard/">归档</Link>
);
};
//dashboard/@notifications/archieved/page.tsx
export default function ArchivedNotifications() {
return (
<div>归档通知</div>
<Link href="/dashboard/">默认</Link>
);
};
这种结构不仅提升了代码的模块化和可读性,而且还增强了用户界面的交互性,使用户能够在仪表盘的不同部分之间流畅地导航,同时各部分能够独立地加载和处理数据。这样的设计思想,为构建复杂且高效的Web应用提供了新的可能性。
通过今天的分享,我们了解了Next.js并行路由的强大之处,以及它如何使我们能够构建更加动态和响应式的Web应用。这项技术不仅提高了应用的性能和用户体验,还让代码的组织和维护变得更加高效。
在这信息爆炸的时代,我始终致力于探索前端技术的最新动态,为你带来更多的技术干货。如果你对今天的内容感兴趣,不妨点赞、关注、转发,并在评论区留下你的看法和问题。我非常期待你的反馈和互动!
此外,不要忘了关注「前端达人」,我将不定期分享更多关于前端开发的技术文章、教程和最佳实践。让我们一起在前端的道路上不断进步,探索更多可能性!
者|Next.js 团队
译者|无明
出处丨前端之巅
在经过 26 次金丝雀发布和 340 万次下载之后,近日,我们正式发布了 Next.js 7.0,新功能包括:
Next.js 的主要目标之一是提供最佳的性能和开发者体验。最新版本为构建和调试管道带来了很多重大改进。
得益于 Webpack 4 和 Babel 7,以及我们对代码库做出的很多改进和优化,Next.js 现在在开发过程中的启动速度提高了 57%。
我们新增了增量编译缓存,让变更代码的构建速度快了 40%。
以下是我们收集的一些示例数据:
因为使用了 webpackbar,在开发和构建的同时可以看到更好的实时反馈:
使用 react-error-overlay 更好地报告错误
准确地渲染错误对于良好的开发和调试体验来说是至关重要的。到目前为止,我们可以渲染错误消息和堆栈跟踪信息。我们在此基础上更进一步,我们使用 react-error-overlay 来丰富堆栈跟踪信息:
这是之前和之后的错误显示比较:
另外,借助 react-error-overlay,你只需单击特定代码块就可以轻松打开文本编辑器。
从发布第一个版本以来,Next.js 一直使用 Webpack 来打包代码和重用丰富的插件。Next.js 现在使用了最新的 Webpack 4,其中包含很多改进和 bug 修复。
另一个新功能是支持 WebAssembly,Next.js 甚至可以进行 WebAssembly 服务器渲染。
这里有一个例子:
https://github.com/zeit/next.js/tree/canary/examples/with-webassembly
因为使用了 Webpack 4,我们引入了一种从捆绑包中提取 CSS 的新方法,这个插件叫作 mini-extract-css-plugin(https://github.com/webpack-contrib/mini-css-extract-plugin)。
mini-extract-css-plugin 提供了 @zeit/next-css、@zeit/next-less、@zeit/next-sass 和 @zeit/next-stylus。
这些 Next.js 插件的新版本解决了与 CSS 导入相关的 20 个问题,例如,现在支持 import() 动态导入 CSS:
// components/my-dynamic-component.js import './my-dynamic-component.css' export default ()=> <h1>My dynamic component</h1> // pages/index.js import dynamic from 'next/dynamic' const MyDynamicComponent=dynamic(import('../components/my-dynamic-component')) export default ()=> <div> <MyDynamicComponent/> </div>
一个重大改进是现在不再需要在 pages/_document.js 中添加一下内容:
<link rel="stylesheet" href="/_next/static/style.css" />
Next.js 会自动注入这个 CSS 文件。在生产环境中,Next.js 还会自动向 CSS URL 中添加内容哈希,当文件发生变更时,最终用户就不会得到旧文件,并且能够获得不可变的永久缓存。
简而言之,要在 Next.js 项目中支持导入.css 文件,只需要在 next.config.js 中注册 withCSS 插件:
const withCSS=require('@zeit/next-css') module.exports=withCSS({/* my next config */})
从版本 3 开始,Next.js 就通过 next/dynamic 来支持动态导入。
作为这项技术的早期采用者,我们必须自己编写解决方案来处理 import()。
因此,Next.js 逐渐缺失 Webpack 后来引入的一些功能,包括 import()。
例如,无法手动命名和捆绑某些文件:
import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library')
另一个例子是在 next/dyanmic 模块之外使用 import()。
从 Next.js 7 开始,我们不再直接使用默认的 import(),Next.js 为我们提供了开箱即用的 import() 支持。
这个变更也是完全向后兼容的。使用动态组件非常简单:
import dynamic from 'next/dynamic' const MyComponent=dynamic(import('../components/my-component')) export default ()=> { return <div> <MyComponent /> </div> }
这段代码的作用是为 my-component 创建一个新的 JavaScript 文件,并只在渲染< MyComponent/>时加载它。
最重要的是,如果没有进行渲染,< script>标记就不会出现在初始 HTML 文档中。
为了进一步简化我们的代码库并利用优秀的 React 生态系统,在 Next.js 7 中,我们使用 react-loadable 重写了 next/dynamic 模块。这为动态组件引入了两个很棒的新特性:
Next.js 6 中就已经引入了 Babel 7 测试版。后来 Babel 7 稳定版本发布,现在,Next.js 7 正在使用这个新发布的稳定版 Babel 7。
一些主要特性:
如果你的 Next.js 项目中没有自定义 Babel 配置,那么就不存在重大变更。
但如果你具有自定义 Babel 配置,则必须将相应的自定义插件 / 预设升级到最新版本。
如果你从 Next.js 6 以下的版本升级,可以使用 babel-upgrade 工具。
除了升级到 Babel 7 之外,当 NODE_ENV 被设置为 test 时,Next.js Babel 预设(next/babel)现在默认将 modules 选项设置为 commonjs。
这个配置选项通常是在 Next.js 项目中创建自定义.babelrc 的唯一理由:
{ "env": { "development": { "presets": ["next/babel"] }, "production": { "presets": ["next/babel"] }, "test": { "presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]] } } }
使用 Next.js 7,这将变成:
{ "presets": ["next/babel"] }
现在可以删除.babelrc,因为在没有 Babel 配置时,Next.js 将自动使用 next/babel。
Next.js 在预渲染 HTML 时会将页面内容放在< html>、< head>、< body>结构中,并包含页面所需的 JavaScript 文件。
这个初始载荷之前约为 1.62kB。在 Next.js 7 中,我们优化了初始 HTML 载荷,现在为 1.5kB,减少了 7.4%,让页面变得更加精简。
我们主要通过以下几种方式来缩小文件:
在 Next.js 5 中,我们引入了 assetPrefix 支持,让 Next.js 可以自动从某个位置(通常是 CDN)加载资源。如果你的 CDN 支持代理,可以使用这种办法。你可以像这样请求资源:
https://cdn.example.com/_next/static/<buildid>/pages/index.js
通常,CDN 先检查缓存中是否包含这个文件,否则直接从源中请求文件。
不过,某些解决方案需要将目录直接预先上传到 CDN 中。这样做的问题在于 Next.js 的 URL 结构与.next 文件夹中的文件夹结构不匹配。例如我们之前的例子:
https://cdn.example.com/_next/static/<buildid>/pages/index.js // 映射到: .next/page/index.js
在 Next.js 7 中,我们改变了.next 的目录结构,让它与 URL 结构相匹配:
https://cdn.example.com/_next/static/<buildid>/pages/index.js // 映射到: .next/static/<buildid>/pages/index.js
尽管我们建议使用代理类型的 CDN,但新结构也允许不同类型 CDN 的用户将.next 目录上传到 CDN。
我们也引入了 styled-jsx 3,Next.js 的默认 CSS-in-JS 解决方案,现在已经为 React Suspense 做好了准备。
如果一个组件不属于当前组件作用域的一部分,那么该如何设置这个子组件的样式呢?例如,如果你将一个组件包含在父组件中,并只有当它被用在父组件中时才需要特定的样式:
const ChildComponent=()=> <div> <p>some text</p> </div> export default ()=> <div> <ChildComponent /> <style jsx>{` p { color: black } `}</style> </div>
上面的代码试图选择 p 标签,但其实不起作用,因为 styled-jsx 样式被限定在当前组件,并没有泄漏到子组件中。解决这个问题的一种方法是使用:global 方法,将 p 标记的前缀移除。但这样又引入了一个新问题,即样式泄露到了整个页面中。
在 styled-jsx 3 中,通过引入一个新的 API css.resolve 解决了这个问题,它将为给定的 syled-jsx 字符串生成 className 和< style>标签(styles 属性):
import css from 'styled-jsx/css' const ChildComponent=({className})=> <div> <p className={className}>some text</p> </div> const { className, styles }=css.resolve`p { color: black }` export default ()=> <div> <ChildComponent className={className} /> {styles} </div>
这个新 API 可以将自定义样式传给子组件。
由于这是 styled-jsx 的主要版本,如果你使用了 styles-jsx/css,那么在捆绑包大小方面有一个重大变化。在 styled-jsx 2 中,我们将生成外部样式的“scoped”和“global”版本,即使只使用“scoped”版本,我们也会将“global”版本包含在内。
使用 styled-jsx 3 时,全局样式必须使用 css.global 而不是 css,这样 styled-jsx 才能对包大小进行优化。
App 和 Page 之间的 React Context(服务器端渲染)
从 Next.js 7 开始,我们支持 pages/_app.js 和页面组件之间的 React Context API。
以前,我们无法在服务器端的页面之间使用 React 上下文。原因是 Webpack 保留了内部缓存模块而不是使用 require.cache,我们开发了一个自定义 Webpack 插件来改变这种行为,以便在页面之间共享模块实例。
这样我们不仅可以使用新的 React 上下文,在页面之间共享代码时还能减少 Next.js 的内存占用。
从 Next.js 首次发布以来,就已获得相当多的用户,从财富 500 强公司到个人博客。我们非常高兴看到 Next.js 的采用量一直在增长。
目前,超过 12,500 个被公开索引的域名在使用 Next.js。我们有超过 500 名贡献者,他们至少提交过一次代码。在 GitHub 上,这个项目已经有 29,000 个 star。自首次发布以来,已提交了大约 2200 个拉取请求。
Next.js 社区在 spectrum.chat/next-js 上拥有近 2000 名成员。
英文原文
https://nextjs.org/blog/next-7
*请认真填写需求信息,我们会在24小时内与您取得联系。