Skip to content
Kevin Wolf

AUTHOR

Kevin Wolf

Senior Software Engineer

Select...
Select...
Let’s build an Events website with Next.js: Intro to Next.js cover image

Let’s build an Events website with Next.js: Intro to Next.js

Let’s build an Events website with Next.js: Intro to Next.js This is the first article of a series of posts where I will write about Next.js, the most complete framework for writing React.js applications. Through this guide, you will learn the basics of Next.js, as well as how to integrate it with GraphCMS, the GraphQL native headless CMS. What is Next.js? Next.js is a web framework for React.js, built and maintained by the Vercel team. With Next.js, you can create both server-rendered and statically-generated websites, with out-of-the-box support for internationalization, image optimization, routing, TypeScript support, CSS and Sass support, code splitting, Serverless API Routes, and more. All of the above is offered out-of-the-box, with no further config needed. Core concepts File-system Routing Unlike other React applications, where you may need to import a routing library, and write a routes config file associating each component with a route path, in Next.js it is a simple as adding files to the pages directory and defaultly exporting a React component. There, the route path will be the filename. (i.e. pages/index.js, pages/about.js pages/blog/index.js) Matching dynamic parameterized routes is also possible by wrapping the filename with a bracket syntax (i.e. pages/blog/[slug].js) and *catch-all* routes, which allows it to have as many subpaths as possible (i.e. pages/parametrized/[...paths].js). The following file structure: ` Will match the following paths: - pages/about.js => https://my-website.com/about - pages/blog/index.js => https://my-website.com/blog - pages/blog/[slug].js => https://my-website.com/blog/hello-world, https://my-website.com/blog/my-first-post, https://my-website.com/blog/hello-world - pages/index.js => https://my-website.com - pages/parametrized/[...paths].js => https://my-website.com/parametrized/a, https://my-website.com/parametrized/a/b, https://my-website.com/parametrized/a/b/c ... and so on. Data fetching There is two ways to fetch data from a Next.js application. You can either generate static pages at build time, or fetch data from the server at run time. 1. Static pages generation It is the recommended way to fetch public data coming from any data source. This can be a CMS, a database, or even a local or remote JSON file. One of the benefits of generating pages at build time is that you can put a CDN in front of it, and serve the already generated assets to the user. To set up a page to be statically generated, export an asynchronous getStaticProps function from it, returning an object with a nested props object, which will be passed to the route component. pages/blog/index.js ` When working with dynamic routes, an extra asynchronous function getStaticPaths needs to be exported, which needs to return an object with a fallback property (this will be explained later), and a nested paths array. Each item of the array needs to be an object with a nested params object, which will be received by getStaticProps to know which object to fetch. pages/blog/[slug].js ` Note: the above will generate all blog posts at build time. If you don't want to generate *all* blog post static pages at build time, you can opt-in to Incremental Static Regeneration, which will be explained later on this article. 2. Server-side rendering The other technique to hydrate a page with dynamic data is to render it from the server. This can be useful when working with private pages that can't be put on a CDN, and the data will change according to the request context. For that, an asynchronous function called getServerSideProps will need to be exported from the route component, returning an object with a nested props object. pages/profile.js ` Note: one of the caveats of server-side rendering is a page using it can't be cached by a CDN without additional configuration, and your page relies on a long-life server to be running. A workaround for this is to just export a component from the page route file, and do the fetching client-side using fetch either on a useEffect hook, or using a data fetching library such as SWR. API Routes If you want to create serverless API endpoints for external consumers, or for client-side fetching, you can add API routes files to an api directory within the pages directory exporting a handler that receives a req and a res argument. It can also receive dynamic and catch-all parameters, just like a regular app route. pages/api/profile.js ` The above will create an API endpoint at https:my-website.com/api/profile that can be consumed from anywhere. ` Moving forward The above core concepts are just a small taste of what Next.js can offer. In the upcoming articles in this series, you will continue learning how to use more techniques like image optimization, Incremental Static Regeneration, and Internationalization. Stay tuned!...

What's New in Next.js cover image

What's New in Next.js

What's new in Next.js On October 27th 2020, the first ever Next.js Conf streamed to an audience of more than 34K. Let's go over the most important highlights! Next.js v10 The new version of Vercel's framework was released, boasting exciting new features that directly affect website performance and Web Vitals Metrics, allowing developers to have a better impact in search results. So what are these features? New Image Component One of the core metrics of the Web Vitals is the Largest Contentful Paint (LCP), and it directly affects user experience as a web application loads. Often, images are not properly optimized to have different behaviour based on the visitor device. For example, you may be downloading a 1000x1000 pixels image and only rendering a 200x200 pixels image on mobile devices. Luckily, this new version introduces a new Image component that acts as a drop-in replacement for the HTML element, with the advantage that comes with built-in optimization for different devices. Under the hood, images rendered with the new Image compoonent will be lazy-loaded, and will only render when they are within the viewport. Migration Integrating the new Image component is as easy as replacing all img elements with the new component: *Before* ` *After* ` One important thing to note is that the width and height props are required. Although one may think it will affect responsive layouts, this is not the case, because the image will be automatically made responsive based on the aspect ratio from the provided dimensions. Internationalization After 2 months of gathering feedback from the community, in an RFC, the ability to add i18n to a Next.js application is now built into the framework. Before this release, it was only possible through a custom server, which is not encouraged anymore by the Vercel team. Instead, you can now easily configure a Next.js application to have i18n capabilities by just adding some extra parameters to the configuration file: next.config.js ` The routing can happen at two different levels; subpath routing (adds the locale as an URL path, i.e. https://miwebsite.com/es/about) and domain routing (reads the locale from an absolute URL, i.e https://mywebsite.es). To enable domain routing, the configuration file will need to be slightly different: next.config.js ` This new version also has automatic language detection on the / route by checking the Accept-Language header, which will be matched against the provided configuration. Improved Link component Trying to create a link to a dynamic route by using a combination of the href and as props was somewhat confusing before. However, now the next/link component only needs the href prop. *Before:* ` *After:* ` This is not a breaking change so you can still continue using both props. However, now it is more developer-friendly. Blocking fallback for getStaticPaths What makes Next.js stands over other frameworks is the ability to incrementally generate static pages. This means, if you are building an e-commerce platform with *lots* of products, you won't need to statically generate all pages at build time. Instead, you can opt in to incrementally generate the pages in getStaticPaths. Starting in Next.js 9.3, you could opt-in to this by adding a fallback property in getStaticPaths. At build time, a static fallback page was generated so the first time a user visited a given URL, it would be served, and once the data was fetched, a new page would be served, and pushed to the CDN for subsequent loads. However, now we have the ability to avoid showing a fallback page at all and instead blocking the render until the data has been fetched by just adding fallback: 'blocking' to the returned object from getStaticPaths. *Before:* ` *After:* ` notFound support for getStaticProps and getServerSideProps The getStaticProps and getServerSideProps methods implemented a new boolean property: notFound. By adding it, your users will be redirected to your 404 page. ` redirect support for getStaticProps and getServerSideProps A redirect property was also added to both methods. Allowing you to redirect to either an internal or an external page, with the ability to also mark the redirect as permanent. ` Vercel's Next.js Analytics Although this is not related only with the framework, Vercel released Next.js Analytics, a new feature of the platform that collects analytics from real users by measuring Core Web Vitals and generating reports. Next.js Commerce If you are planning to spin up an e-commerce functionality on top of Next.js, you can just clone an all-in-one starter kit that includes all of the previously mentioned new features. Moving forward We are planning to release a series of Next.js articles in the upcoming weeks, including in-depth guides on how to create a Next.js application using all of the new features, including best practices and tips from the community. Stay tuned!...

Taming Forms With react-hook-form cover image

Taming Forms With react-hook-form

Taming Forms With react-hook-form After some time of doing repetitive tasks like handling forms in React.js, you will notice that there is a lot of boilerplate code that can be abstracted into reusable custom hooks. Luckily, there is plenty of existing Open Source solutions. In this case, we will be using react-hook-form. What is react-hook-form react-hook-form is a performant, flexible, and extensible form handling library built for React. It exports a custom hook that you can call within your Functional Components, and returns both a register function that you pass as a ref to your input components, and a handleSubmit function to wrap your submit callback. By returning a register function that will be added to the input component, we can leverage the Uncontrolled Component pattern to make our application faster and more performant, by avoiding unnecessary re-renders. What are we going to build? To get a better understanding of what react-hook-form can do, we will build a simple application showing a list of characters and a form to add them to our list. Application Setup Before going right into react-hook-form, we will need to prepare our application with the basic file structure and functionality. For this, we will create a new react application (you can either use your preferred starter or cloud IDE). _If you want to skip the application setup, you can go ahead and fork this CodeSandbox, but I highly recommend you at least read this section to have a better understanding of what the app does._ 1. Characters List Let's start by creating a new component where we will display our characters. character-list.js ` If you have a basic understanding of React, you will notice our CharacterList component will receive a characters prop, which is an array of objects with the properties name and species. If the array is empty, we will render a placeholder. Elsewhere, we will render the list. 2. Add Character Form The second step is to create a component that will render the form to add a new character to our list. character-form.js ` By itself, this component won't do anything because we are not doing anything with the collected data, nor validating our fields. This will be the component where we will be working on the next section of this tutorial. 3. The App Now, let's just create the App component where we will render CharacterList and CharacterForm. app.js ` We will be saving our character list in characters by using the React.useState hook, and passing them down to CharacterList. Also, we created an addCharacter function that will just add a new character at the end of the characters list, and pass it to CharacterForm via prop. Let's get to it! Now that we have our application setup, let's see how can we leverage react-hook-form to take our forms to the next level. Install react-hook-form ` Add react-hook-form to your CharacterForm Here comes the fun. First, let's import useForm from react-hook-form, call the hook in our component, destructure register and handleSubmit methods out of it (don't worry, I will explain what they do just in a while), wrap our onSubmit function with handleSubmit, and pass register as the ref for each one of our form controls. character-form.js ` The register method By attaching the register ref to our form controls, we can start tracking some stuff like the field value, its validation status, and even if the field had been touched or not. Important: the name prop is required when passing the register ref, and it should be unique. This way, react-hook-form will know where to assign the field value. For more information, check out the register documentation. The handleSubmit method This is a function that wraps our submit callback, and passes the actual form values to it. Under the hood, it also calls preventDefault on the form event to avoid full page reloads. It can also be an asynchronous function. For more information, check out the handleSubmit documentation. Add some validations At this point, we have a working form that is able to add characters to our list. However, we are not checking if the field is filled, in order to avoid empty submissions. With react-hook-form, it is as simple as calling the register function with a configuration object defining the validation rules. For our case, we will make the name field required. Also, we can extract errors from useForm to show the user if the field has errors. ` Reset the form status The final step is to clear our form after successfully adding a character to our character list. For that, we will destructure a new method from the useForm hook: reset, and call it after addCharacter. ` For more information, check out the reset documentation. Moving forward Now that you have a better sense of how to manage your React forms, you have unlocked a new world of possibilities by using battle-tested and community-validated libraries like react-hook-form. You can take a look at more advanced use cases, additional resources or even take a look at the full API. If you want a finished code sample, you can check out this CodeSandbox....

React.js 17: No New Features and New JSX Transform cover image

React.js 17: No New Features and New JSX Transform

React.js 17: No New Features and New JSX Transform When React.js 17 became available on October 20th, it generated some confusion because it has no new developer-facing features. Instead, the React Core team focused on making the React library easier to self-upgrade in the future. This means, that if your app is running React 17 and you need to upgrade some features to React 18, you can move your application core to React 18 and lazily load the legacy code without any issues. Of course, you can still upgrade your entire app the new version at once, which is the recommended version by the React team. Installation To install React 17 with npm, run: ` To install React 17 with Yarn, run: ` Internal improvements New JSX Transform One of the greatest internal improvements React 17 has is the new JSX transform. Prior to React 17, when you write JSX code, it was transformed to a React.createElement call. So, it looked something like this: ` Was transformed to this: ` Starting on React 17, you don't need to import React from 'react' anymore. Instead, two new entry points were added to the React package that are intended to be used only by compilers like Babel or TypeScript. So for the above JSX code, the output will be slightly different: ` So, your app won't need to import React from 'react' anymore. Instead, you can directly write your JSX code: ` Next.js was known to allow the above because under the hood, it imported React. However, they changed this in their 9.5.3 release in order to use the new transform. Updating ESlint rules If you are using the eslint-plugin-react package, you may notice not importing React will generate an issue. For that, you can just disable those rules while they remove those rules. eslintrc.json ` Removing Unused React Imports Luckily, the React team has created a codemod you can run to remove your old React imports. To run it, just open a new terminal on your project directory, and run the following script: ` A new Event Delegation System To enable gradual updates, the React team changed its internal *Event Delegation System*, which works like this: Before React 17, all event handlers were attached at the document level under the hood, so it ran document.addEventListener() for most events. After React 17, it attached all event handlers to the root element where you render your app, which calls rootNode.addEventListener() instead. To better understand how the new *Event Delegation System* works, take a look at this diagram: You can take a look at a demo of gradual updates on an example repository put together by the React team. Other Breaking Changes There are other minor breaking changes that hopefully won't affect your application. They are mostly internal changes, like the onScroll event no longer bubbling, onFocus and onBlur events switching to use the native focusin and focusout under the hood, removing the old event pooling optimization, and making the effect cleanup timing more consistent. To go deeper into these other breaking changes, you can take a look at the React v17 RC Breaking Changes....

Supercharging Next.js Development with Tailwind CSS cover image

Supercharging Next.js Development with Tailwind CSS

Supercharging Next.js Development with Tailwind CSS When creating a new Next.js project (and in general, any React.js application), choosing a styling solution can be a time-consuming part of the process. While there are plenty of approaches to styling a React.js application, in this case, we are going to use TailwindCSS. Unlike CSS-in-JS solutions that only provide the styling system or component libraries that give you opinionated component styles, TailwindCSS provides you with a set of unopinionated utility CSS classes that your components can leverage to build your User Interface, with the chance of extending them via configuration files. Scaffolding our application > Note: We will use yarn across this guide, but feel free to use npm if that is your personal choice. Let's create a new Next.js application. While there is an official create-next-app CLI tool, we will manually scaffold our project to avoid removing unnecessary files created by it. Create a new directory and cd into it. ` Initialize an empty package.json ` Install required dependencies ` Create a homepage in pages/index.js By default, the Next.js filesystem router will pick all pages created in the pages directory and make them available as routes. pages/index.js ` Add dev, build and start scripts to our package.json package.json ` Now, let's run yarn dev to start your development server and navigate to http://localhost:3000 to preview your unstyled Home page. Configuring TailwindCSS We have a basic web application now, but its lack of styling, colors, and a nice font makes it look boring and lifeless. Install TailwindCSS as a devDependency ` Generate a TailwindCSS config file Run yarn tailwindcss init to create a tailwind.config.js file if you want to later customize the default configuration or add more plugins. Additionally, if you are using the TailwindCSS VSCode Extension, you will get intellisense completions for your class names. Create a Global Stylesheet In order to import TailwindCSS utility classes, we need to create a stylesheet in styles/main.css, where we will use the @tailwind directive to import all the required classes and set up some global styles. ` Import the Global Stylesheet To add a Global Stylesheet, we need to create a custom App and import it there. pages/_app.js ` Configure PostCSS If you run yarn dev and navigate to http://localhost:3000, you will see an unstyled page like the following: This is happening because Next.js doesn't know (_yet!_) what to do with the @tailwind and @apply directives. For that, we will leverage Next.js's built-in PostCSS support to parse our CSS file. Create a postcss.config.js file in your project root with the following code: postcss.config.js ` Now, let's restart our development server to see it working: Adding More Styles Now that our TailwindCSS config is working and PostCSS is compiling, we can start consuming those rules in our app routes. Let's edit our Home Page to make it look better. pages/index.js ` It should look like this: Optimizing Build Result Our Next.js project is successfuly set up to use TailwindCSS 🎉. However, we can still run some optimizations to make it work with all browsers and reduce final CSS file size. Polyfill modern CSS Most modern webapps use modern CSS features that old browsers does not support, and manually covering all cases can be frustrating, time-consuming and pointless since we have tools like PostCSS Preset Env that can automate the process. Install postcss-preset-env ` Add postcss-preset-env as a plugin to postcss.config.js postcss.config.js ` Refer to the postcss-preset-env documentation for more details on how it works and what it solves. Purge unused utility classes If we run the yarn build command, we will notice some warnings from the PostCSS step: ` This is happening because the final build is including all of the TailwindCSS utility classes, which will create a *huge* StyleSheet and we don't want to slow down the page load for our users. Luckily, TailwindCSS config has an option to control the file size that we can leverage by configuring the purge property of our tailwind.config.js file. tailwind.config.js ` By using that configuration, PostCSS will analyze the code within components and pages directories, extract class names and match them with our generated TailwindCSS utility classes. This means the final CSS file will only have the neccessary classes to work and no dead code ✨. Moving forward We have concluded our mini guide on how to Supercharge your Next.js Development with TailwindCSS. Pretty easy, right? I personally think the folks at Vercel have been really working hard to make integrations like this as seamless as possible. If you want to keep digging into the available utility classes, how to customize your configuration, add more variants or even create your own plugins, refer to the TailwindCSS documentation. Also, if you just want a sneak peak on what you can do with TailwindCSS without creating a new project, go to the Tailwind Play tool where you will be able to try it in your browser. If you want a finished code sample, refer to this GitHub repository....