To add Next.js to your project, you will not need to load the react
and react-dom
scripts from unpkg.com anymore. Instead, you can install these packages locally using the Node Package Manager: npm
.
Note: You will need to have Node.js installed on your machine (minimum version requirement), you can download it here.
To do so, create a new file called package.json
with an empty object {}
.
// package.json
{
}
In your terminal, run npm install react react-dom next
. Once the installation is complete, you should be able to see your project dependencies listed inside your package.json
file:
// package.json
{
"dependencies": {
"next": "^12.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
You will also notice a new folder called node_modules
that contains the actual files of our dependencies.
Jumping back to the index.html
file, you can delete the following code:
react
and react-dom
scripts since you’ve installed them with NPM.<html>
and <body>
tags because Next.js will create these for you.app
element and ReactDom.render()
method.Babel
script because Next.js has a compiler that transforms JSX into valid JavaScript browsers can understand.<script type="text/jsx">
tag.React.
part of the React.useState(0)
functionAfter deleting the lines above, add import { useState } from "react"
to the top of your file. Your code should look like this:
// index.html
import { useState } from 'react';
function Header({ title }) {
return <h1>{title ? title : 'Default title'}</h1>;
}
function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
const [likes, setLikes] = useState(0);
function handleClick() {
setLikes(likes + 1);
}
return (
<div>
<Header title="Develop. Preview. Ship. 🚀" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<button onClick={handleClick}>Like ({likes})</button>
</div>
);
}
The only code left in the HTML file is JSX, so you can change the file type from .html
to .js
or .jsx
.
Now, there are three more things you need to do to fully transition to a Next.js app:
index.js
file to a new folder called pages
(more on this later). // ...
export default function HomePage() {
// ...
package.json
file to run the Next.js development server while you develop. // package.json
{
"scripts": {
"dev": "next dev"
},
// "dependencies": {
// "next": "^11.1.0",
// "react": "^17.0.2",
// "react-dom": "^17.0.2"
// }
}
To confirm everything works, you can view your app by running npm run dev
inside your terminal and navigating to localhost:3000 in the browser. Then, make a small change to the code and save it.
Once you save the file, you should notice the browser automatically updates to reflect the change.
This feature is called Fast Refresh. It gives you instantaneous feedback on any edits you make and comes pre-configured with Next.js.
To recap, your code went from this...
<html>
<body>
<div id="app"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/jsx">
const app = document.getElementById("app")
function Header({ title }) {
return <h1>{title ? title : "Default title"}</h1>
}
function HomePage() {
const names = ["Ada Lovelace", "Grace Hopper", "Margaret Hamilton"]
const [likes, setLikes] = React.useState(0)
function handleClick() {
setLikes(likes + 1)
}
return (
<div>
<Header title="Develop. Preview. Ship. 🚀" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<button onClick={handleClick}>Like ({likes})</button>
</div>
)
}
ReactDOM.render(<HomePage />, app)
</script>
</body>
</html>
...to this:
import { useState } from 'react';
function Header({ title }) {
return <h1>{title ? title : 'Default title'}</h1>;
}
export default function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
const [likes, setLikes] = useState(0);
function handleClick() {
setLikes(likes + 1);
}
return (
<div>
<Header title="Develop. Preview. Ship. 🚀" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<button onClick={handleClick}>Like ({likes})</button>
</div>
);
}
On the surface, this is a small reduction in lines of code, but it does help highlight something: React is a library that provides essential primitives for building modern interactive UI. But there is still some work involved to combine that UI you create into an application.
Looking at the migration, you may already be getting a sense of the benefits of using Next.js. You removed the babel script, a taste of the complex tooling configuration you no longer have to think about. You also saw Fast Refresh in action, just one of the many developer experience features you can expect with Next.js.