What the hell is Conformance? Highlighted in Next.js 11
Next.js 11 is the latest update to the popular React framework and it introduced a bunch of new and exciting features. Also included in the update is something known as Conformance, but what the hell is it and why do we need it?
Well, you've come to the right place!
What does it mean to conform?
Let's first ask the question, what does it mean to conform to something?
The simple answer is that it means we behave or comply with a set of rules or standards hopefully for the benefit of all involved.
So even before we take a look at Conformance in Next.js, we have this idea of what it might involve.
Conformance in Next.js
Conformance isn't necessarily a feature in itself, but a system. An overriding system of best practices that sets out to solve a particular problem. Those problems are defined below ๐
Conformance is a system that provides carefully crafted solutions and rules to support optimal loading and Core Web Vitals, with further additions coming to support other quality aspects like security and accessibility
https://nextjs.org/blog/next-11
Conformance aims to help developers achieve a strong base standard for these vital website factors without needing to be an expert in everything and keep up with all of the latest standards. This is done by adding solutions directly into the frameworks responsible for building the sites. This means we can spend more time focusing on features and less time on the rest of it without sacrificing anything.
Conformance in Next.js actually comes from the team at Google Web Platforms and Next.js is the first of the framework ecosystem to see a lot of the current optimizations available. If you would like to find out more about the larger effort which Conformance attempts to solve, check out this article web.dev - Introducing Aurora.
You may be reading this article and thinking something like this ๐
Where does conformance stand in relation to a tool like ESLint? How do they differ?
I was when I was first reading about Conformance.
Simply put, ESLint is one of the tools identified to be an important part of Conformance in frameworks.
ESLint is a tool that statically analyzes your code based on a set of defined rules which helps you maintain certain standards and consistencies across a project. It's a great tool that we should all be using in order to help maintain consistent code quality and best practices.
This is why there is out-of-the-box support for ESLint in Next.js as of this update. You can start a new project with ESLint ready to go or easily add it to an existing project. Let's check it out!
Next.js 11 - ESLint
ESLint can now easily be added to any new or existing Next.js project so let's do it. I'll create a new project with ๐
npx create-next-app next11-conformance
I'll draw your attention to two things. First of all, you will see a .eslintrc
file at the root of the project with the base configuration. This is where we configure ESLint for our project. The second point is a new "lint": "next lint"
script in the package.json
file. This is how we can lint our projects and make sure the code is up to standard.
If your existing project does not currently make use of ESlint, add this script and run it. You will be guided on which packages you need to install to get things up and running.
ESLint will also lint your project whenever you run the script next build
and errors in the linting process will stop the build.
I won't be diving into a complete set of ESLint rules for a Next.js project in this article, but I am going to explore the new Next.js specific rules that we now have available.
eslint-plugin-next
Our ESLint configuration will include a set of new rules specific to Next.js which are provided by the plugin eslint-plugin-next
included in your project when you run create-next-app
. Let's see it in action.
I will be working inside pages/index.js
for the purpose of the following examples.
Firstly, delete everything inside the return statement of the home page and add the following ๐.
// pages/index.js
export default function Home() {
return (
<div>
<a href="/">
Home
</a>
</div>
)
}
Here we are using a regular anchor tag that links to the home page. Next.js provides a built-in <Link />
component that we should utilize whenever we are routing within our own site. This is one of the things that the new ESLint configuration will catch.
Run the lint command
yarn lint
and you should see the following inside the terminal.
./pages/index.js
6:7 Error: Do not use the HTML <a> tag to navigate to /. Use Link from 'next/link' instead. See: https://nextjs.org/docs/messages/no-html-link-for-pages. @next/next/no-html-link-for-pages
Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Let's make the change it suggests and use the <Link />
component instead.
import Link from 'next/link';
export default function Home() {
return (
<div>
<Link href="/">
Home
</Link>
</div>
)
}
Now the errors have gone and we are building an app that adheres to certain standards for the benefit of our site and the users that visit it.
โ No ESLint warnings or errors
Let's take a look at one more again using the <Link />
component. When we are using this component and wrapping a child component which includes an <a>
tag, and that makes use of the href
property, we must pass the property passHref
to `. Before we do, let's see the problem in action ๐.
import Link from 'next/link';
const Component = React.forwardRef(({ href }, ref) => {
return (
<div>
<p>This is my link with some text</p>
<a href={href} ref={ref}>This is the link</a>
</div>
)
})
export default function Home() {
return (
<div>
<Link href="/">
<Component />
</Link>
</div>
)
}
If we don't use passHref
on our link then our <a>
tag will not receive it. In this case, we should also wrap the component in React.forwardRef
because this child component of <Link />
is a functional component. The following is the error we receive by not including it.
./pages/index.js
4:19 Error: Component definition is missing display name react/display-name
16:7 Warning: passHref is missing. See https://nextjs.org/docs/messages/link-passhref @next/next/link-passhref
Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules
error Command failed with exit code 1.
And if we now add passHref
to our <Link />
, everything is great again!
import Link from 'next/link';
// eslint-disable-next-line react/display-name
const Component = React.forwardRef(({ href }, ref) => {
return (
<div>
<p>This is my link with some text</p>
<a href={href} ref={ref}>This is the link</a>
</div>
)
})
export default function Home() {
return (
<div>
<Link href="/" passHref>
<Component />
</Link>
</div>
)
}
All is well again ๐.
โ No ESLint warnings or errors
Next.js specific rules
You may be wondering ๐
What are the full set of current rules pertaining to Next.js?
Here they are with a helpful overview of each rule.
Rules | What's the problem and how to deal with it? |
next/google-font-display | Error: Using either auto , block or fallback as the display prop valueSolution: Use the value optional or turn the rule off |
next/google-font-preconnect | Bad: Not including rel="preconnect" to google font <link> tagsGood: Inlcude it to establish a connection and start the process early |
next/no-page-custom-font | Error: Not adding the custom font to the global pages/_document.js Solutions: Turn it off if there is a reason to have the font only available on a single page |
next/no-html-link-for-pages | Bad: Avoid using the<a> tag for on-site linksGood: Use the built-in <Link /> component from next/link instead |
next/link-passhref | Bad: Not using the passHref prop when necessary Good: Pass it to <Link to="/" passHref /> component when it wraps a custom component that has an <a> tag using this link |
next/no-css-tags | Bad: Using a <link> tag for an external stylesheetGood: Import styling files when required |
next/no-document-import-in-page | Bad: Don't import next/component ouside of pages/_document.js Good: Only required inside pages/_document.js to override the default component |
next/no-title-in-document-head | Bad: Don't use the <title> attribute in the head imported from next/document because title is not the same on all pagesGood: Import it from next/head and define title here |
next/no-head-import-in-document | Bad: Don't import the next <Head /> component from next/head in pages/_document.js Good: Import from next/document to update head across all of the pages |
next/no-img-element | Bad: Avoid using the <img> element.Good: Use the built-in <Image /> component from next/image instead |
next/no-sync-scripts | Bad: Synchronous scripts that can harm your site's performance and load metrics Good: Use methods like defer or async loading |
next/no-unwanted-polyfillio | Bad: Using duplicate polyfills with Polyfill.io that are already built into Next.js Good: Remove the duplicates |
As is the case with ESLint rules, you can turn any of these in your ESLint config rules like this ๐.
// .eslintrc
{
"extends": ["next", "next/core-web-vitals"],
"rules": {
"@next/next/font-google-display": "off",
"@next/next/no-page-custom-font": "off"
}
}
If you're just getting started with Next.js I would recommend not turning these rules off until you understand why each rule is important and you run into a case where it is not suited to your situation. They are there to help you out.
Is there more to Conformance?
Yes there is.
ESLint is not the only tool that is considered a part of Conformance for Next.js. TypeScript is another which adds static type definitions to JavaScript and can help highlight conformance rules to the developer. If you've used TypeScript with Next.js I'm sure you will have noticed integrated type checking on built-in Next.js components. Like when you forget to add the href
property to the <Link />
component. You will be warned of the problem allowing you to quickly get rid of problems before they even exist.
Conformance is very much still evolving and I'm sure it will all become clearer in time once its ideas are implemented into other frameworks, and tools and features adapt.
To further explore Conformance I suggest checking out this article web.dev - Conformance for Frameworks by Shubhie Panicker & Houssein Djirdeh.
Conclusion
That was Conformance in its current state and how it is implemented into Next.js. I think it's an interesting topic that warranted a look at now because we are sure to hear more about it in the future. I hope you were able to learn something new!
You can reach me @Kieran6dev with any questions or concerns.
Thanks for being here and I'll see you next time ๐