[Next] has shown signs of next.js

next Introduction

Next.js is a lightweight server-side rendering application framework React

next Features

  • By default rendered by the server
  • Automatic code split can speed up page loading
  • Simple client routing (based on the page)
  • Webpack-based development environment, supports hot module replacement (HMR)
  • Can be achieved with the Express or any other Node.js HTTP server
  • Babel can use your own custom configuration and Webpack

system requirement

Next.js can be used with Windows, Mac and Linux use together. You only need to install Node.js on the system to start building Next.js application. If there is a better editor

Initialize the project

mkdir next-demo
cd next-demo
npm init -y // 快速创建package.json而不用进行一些选择
npm install --save react react-dom next
mkdir pages

mkdir pages This step is necessary to create a file folder called pages, because the next generation is to be routed according to the following pages js jsx tsx file

Then open the next-demo file package.json directory and replace scripts for the following:

"scripts": {
  "dev": "next",
  "build": "next build",
  "start": "next start"
}

Run the following command to start the development server:

npm run dev

You can now open localhost: 3000 to see the results page, if you do not like 3000 or port conflicts, execute the following command

npm run dev -p 6688(你喜欢的端口)

This time we can in localhost: see the page on 6688 results

hello world

At this point we create a index.js as home pages in the folder

const Index = () => (
  <div>
    <p>Hello Next.js</p>
  </div>
);

export default Index;

Check again localhost: 6688 you can see the current page shows hello world

Navigation between pages

next routing implemented in a very simple, the new pages / about.js

export default function About() {
  return (
    <div>
      <p>This is the about page</p>
    </div>
  );
}

At this visit localhost: 6688 / about, you can see the corresponding results page (the file name in the pages routing and exact match)

Navigation between pages, we can navigate to a label, but it does not execute client-side navigation. In addition, server-per-click browser will request the next page, refresh the page at the same time. Therefore, in order to support the client navigation, we need to use Next.js of Link API, the API by exporting the next / link. Link will prefetch pages, and navigation will be carried out without refreshing the page.

Modify pages / index.js

import Link from 'next/link';

const Index = () => (
  <div>
    <Link href="/about">
      <a>About Page</a>
    </Link>
    <p>Hello Next.js</p>
  </div>
);

export default Index;

Visit again localhost: 6688, and then click on the About Page after page jump to about click your browser's back button to return to the page index..

Because the next / link is only one higher order components (higher-order components), the props disposed next / link assembly invalid. Href only accept props and the like. If you need to add props, it is necessary to add the subordinate components. next / props link assembly that does not pass to the sub-assembly, and will give you a warning error. in this case, next / subassembly link assembly / receiving elements are preferably styles and other props carrier which can be any component or label, the only requirement is that they be able to accept onClick event.

   <Link href="/about">
      <a className="redLink">About Page</a>
    </Link>

    <Link href="/show">
      <div>Show Page</div>
    </Link>

This is a client navigation; the operation is carried out in the browser, without having to make a request to the server to open the developer tools networks for viewing.

More routing content

Package

Currently Next.js code is on the page. We can and will by exporting React components of the assembly into pages directory to create the page. Then, it will have a fixed URL based on file names, but at the same time a number of shared components must also project we will create a common Header and components for multiple pages.

New components / Header.js

import Link from "next/link";

const linkStyle = {
  marginRight: 15
};

const Header = () => (
  <div>
    <Link href="/">
      <a style={linkStyle}>Home</a>
    </Link>
    <Link href="/about">
      <a style={linkStyle}>About</a>
    </Link>
    <Link href="/show">
      <a style={linkStyle}>Show</a>
    </Link>
  </div>
);

export default Header;

Index.js then modify the pages directory under / about.js / show.js

import Header from '../components/Header';

export default function Index() {
  return (
    <div>
      <Header />
      <p>Hello Next.js</p>
    </div>
  );
}

Open localhost: 6688 Click 3 link button to jump back and forth between the pages

We do not need our components in a directory named components. The directory can be named any names. Only / pages and / static is special, but do not create shared components inside pages, generate many invalid route navigation.

layout components

In our application, we will use a generic style on each page. To do this, we can create a generic Layout component and for each of our pages.

components/MyLayout.js

import Header from './Header';

const layoutStyle = {
  margin: 20,
  padding: 20,
  border: '1px solid #DDD'
};

const Layout = props => (
  <div style={layoutStyle}>
    <Header />
    {props.children}
  </div>
);

export default Layout;

Index.js then modify the pages directory under / about.js / show.js

import Layout from '../components/MyLayout';

export default function Index() {
  return (
    <Layout>
      <p>Hello Next.js</p>
    </Layout>
  );
}

Further components may also be used hoc acquired content delivery attributes transmitted using props

Dynamic page

In practical applications, we need to create dynamic pages to display dynamic content.

First modify pages / about.js file

import Layout from "../components/MyLayout";
import Link from "next/link";

const PostLink = props => (
  <li>
    <Link href={`/post?title=${props.title}`}>
      <a>{props.title}</a>
    </Link>
  </li>
);

export default function About() {
  return (
    <Layout>
      <h1>My Blog</h1>
      <ul>
        <PostLink title="Hello Next.js" />
        <PostLink title="Learn Next.js is awesome" />
        <PostLink title="Deploy apps with Zeit" />
      </ul>
    </Layout>
  );
}

Creating pages / post.js

import { useRouter } from 'next/router';
import Layout from '../components/MyLayout';

const Page = () => {
  const router = useRouter();

  return (
    <Layout>
      <h1>{router.query.title}</h1>
      <p>This is the blog post content.</p>
    </Layout>
  );
};

export default Page;

Open localhost: 6688 to see the results page, click on the following three posts about, there will be corresponding to the title page

  • It passes data through a query string parameter (query parameters), any type of data passed through the query string.
  • We import and use useRouter function, next / router function returns Next.js router object.
  • We use the query to obtain the query string parameters
  • Obtain the required parameters router.query.title title.

post page can also add generic header

import { useRouter } from "next/router";
import Layout from "../components/MyLayout";

const Content = () => {
  const router = useRouter();

  return (
    <Layout>
      <h1>{router.query.title}</h1>
      <p>This is the blog post content.</p>
    </Layout>
  );
};

const Page = () => (
  <Layout>
    <Content />
  </Layout>
);

export default Page;

Check again localhost: 6688 to see different

Dynamic Routing

At present, our route is so http: // localhost: 6688 / post title = Hello% 20Next.js, now need more clean routing http:? // localhost:. 6688 / p / 10 add a new page to create our a first dynamic routing p / [id] .js

New pages / p / [id] .js

import { useRouter } from 'next/router';
import Layout from '../../components/MyLayout';

export default function Post() {
  const router = useRouter();

  return (
    <Layout>
      <h1>{router.query.id}</h1>
      <p>This is the blog post content.</p>
    </Layout>
  );
}
  • subsequent processing will next routing / p /. For example, / p / hello-nextjs the process whereby the page. Although, / p / post-1 / another not.
  • Square brackets make it dynamic routing. And you must use the full name when matching dynamic routing. For example, / pages / p / [id] .js supported, but not /pages/p/post-[id].js stand by.
  • When creating a dynamic routing, we id placed between square brackets is the name of a query parameter to the received page, so / p / hello-nextjs the query object is the {id: 'hello-nextjs'}., We can use useRouter () to access it.

Link multiple pages, the new pages / page.js

import Layout from '../components/MyLayout';
import Link from 'next/link';

const PostLink = props => (
  <li>
    <Link href="/p/[id]" as={`/p/${props.id}`}>
      <a>{props.id}</a>
    </Link>
  </li>
);

export default function Blog() {
  return (
    <Layout>
      <h1>My Blog</h1>
      <ul>
        <PostLink id="hello-nextjs" />
        <PostLink id="learn-nextjs" />
        <PostLink id="deploy-nextjs" />
      </ul>
    </Layout>
  );
}

In this page we look at the elements, the path of the page href attribute p folder, URL.as as is to be displayed in the URL bar of your browser and is used in conjunction with the browser history.

Remote data acquisition

In fact, we often need to get data from a remote data source .Next.js they have a standard API to get the page data. We typically use asynchronous functions getInitialProps to do this so that we can get the data to a remote data source on the page, and pass it as props to our page .getInitialProps end can be used on the server and client.

We first need to get a library data

npm install --save isomorphic-unfetch

Then modify pages / index.js

import Layout from '../components/MyLayout';
import Link from 'next/link';
import fetch from 'isomorphic-unfetch';

const Index = props => (
  <Layout>
    <h1>Batman TV Shows</h1>
    <ul>
      {props.shows.map(show => (
        <li key={show.id}>
          <Link href="/detail/[id]" as={`/detail/${show.id}`}>
            <a>{show.name}</a>
          </Link>
        </li>
      ))}
    </ul>
  </Layout>
);

Index.getInitialProps = async function() {
  const res = await fetch('https://api.tvmaze.com/search/shows?q=batman');
  const data = await res.json();

  console.log(`Show data fetched. Count: ${data.length}`);

  return {
    shows: data.map(entry => entry.show)
  };
};

export default Index;

The present circumstances, we will only get the data on the server, because we are rendered on the server.

Then create a details page, here we use dynamic routing

New pages / detail / [id] .js

import Layout from "../../components/MyLayout";
import fetch from "isomorphic-unfetch";
import Markdown from "react-markdown";

const Post = props => (
  <Layout>
    <h1>{props.show.name}</h1>
    <div className="markdown">
      <Markdown source={props.show.summary.replace(/<[/]?p>/g, "")} />
    </div>
    <img src={props.show.image.medium} />
    <style jsx global>{`
     .markdown {
        font-family: "Arial";
      }

     .markdown a {
        text-decoration: none;
        color: blue;
      }

     .markdown a:hover {
        opacity: 0.6;
      }

     .markdown h3 {
        margin: 0;
        padding: 0;
        text-transform: uppercase;
      }
    `}</style>
  </Layout>
);

Post.getInitialProps = async function(context) {
  const { id } = context.query;
  const res = await fetch(`https://api.tvmaze.com/shows/${id}`);
  const show = await res.json();

  return { show };
};

export default Post;

Click the list in a casual and open networks console and browser, you will find this is an interface request in the browser.

Style Components

Next.js in JS framework called a pre-loaded CSS styled-jsx, which CSS makes your code easier to write. It allows you to write a component familiar CSS rules. Rules other than the component (or even sub-components) of anything no effect is simply with css scope.

Modify pages / page.js

import Layout from "../components/MyLayout";
import Link from "next/link";

function getPosts() {
  return [
    { id: "hello-nextjs", title: "Hello Next.js" },
    { id: "learn-nextjs", title: "Learn Next.js is awesome" },
    { id: "deploy-nextjs", title: "Deploy apps with ZEIT" }
  ];
}

export default function Blog() {
  return (
    <Layout>
      <h1>My Blog</h1>
      <ul>
        {getPosts().map(post => (
          <li key={post.id}>
            <Link href="/p/[id]" as={`/p/${post.id}`}>
              <a>{post.title}</a>
            </Link>
          </li>
        ))}
      </ul>
      <style jsx>{`
        h1,
        a {
          font-family: "Arial";
        }

        ul {
          padding: 0;
        }

        li {
          list-style: none;
          margin: 5px 0;
        }

        a {
          text-decoration: none;
          color: red;
        }

        a:hover {
          opacity: 0.6;
        }
      `}</style>
    </Layout>
  );
}

In the above code, we write directly in the template string, and must use the template string ( `` {}) written in CSS.

At this point modify the code

import Layout from "../components/MyLayout";
import Link from "next/link";

function getPosts() {
  return [
    { id: "hello-nextjs", title: "Hello Next.js" },
    { id: "learn-nextjs", title: "Learn Next.js is awesome" },
    { id: "deploy-nextjs", title: "Deploy apps with ZEIT" }
  ];
}

const PostLink = ({ post }) => (
  <li>
    <Link href="/p/[id]" as={`/p/${post.id}`}>
      <a>{post.title}</a>
    </Link>
  </li>
);

export default function Blog() {
  return (
    <Layout>
      <h1>My Blog</h1>
      <ul>
        {getPosts().map(post => (
          <PostLink key={post.id} post={post} />
        ))}
      </ul>
      <style jsx>{`
        h1,
        a {
          font-family: "Arial";
        }

        ul {
          padding: 0;
        }

        li {
          list-style: none;
          margin: 5px 0;
        }

        a {
          text-decoration: none;
          color: blue;
        }

        a:hover {
          opacity: 0.6;
        }
      `}</style>
    </Layout>
  );
}

This time the browser will find the open observation is not effective, because the style jsx this writing style is scope, css only apply to the current scope.

Solve 1, sub-components added to the sub-components of style

const PostLink = ({ post }) => (
  <li>
    <Link href="/p/[id]" as={`/p/${post.id}`}>
      <a>{post.title}</a>
    </Link>
    <style jsx>{`
      li {
        list-style: none;
        margin: 5px 0;
      }

      a {
        text-decoration: none;
        color: blue;
        font-family: 'Arial';
      }

      a:hover {
        opacity: 0.6;
      }
    `}</style>
  </li>
);

2 resolved, global style

 <style jsx global>{`
......css
 `}

Generally not used to solve global style

styled-jsx document

Use global style

Sometimes, we do need to change the interior of the sub-components of style, especially the use of some third-party libraries and some are not satisfied with the style of the time.

Installation react-markdown

npm install --save react-markdown

Modify pages / post.js

import { useRouter } from "next/router";
import Layout from "../components/MyLayout";
import Markdown from "react-markdown";

const Content = () => {
  const router = useRouter();

  return (
    <Layout>
      <h1>{router.query.title}</h1>
      <div className="markdown">
        <Markdown
          source={`  # Live demo

Changes are automatically rendered as you type.

## Table of Contents

* Implements [GitHub Flavored Markdown](https://github.github.com/gfm/)
* Renders actual, "native" React DOM elements
* Allows you to escape or skip HTML (try toggling the checkboxes above)
* If you escape or skip the HTML, no dangerouslySetInnerHTML is used! Yay!

## HTML block below

<blockquote>
  This blockquote will change based on the HTML settings above.
</blockquote>`}
        />
      </div>
      <style jsx global>{`
       .markdown {
          font-family: "Arial";
        }

       .markdown a {
          text-decoration: none;
          color: blue;
        }

       .markdown a:hover {
          opacity: 0.6;
        }

       .markdown h3 {
          margin: 0;
          padding: 0;
          text-transform: uppercase;
        }
      `}</style>
    </Layout>
  );
};

const Page = () => (
  <Layout>
    <Content />
  </Layout>
);

export default Page;

Open localhost: 6688 Click to view the about page style effects

[Other solutions]] (https://github.com/zeit/next.js#css-in-js)

Introduced ui library

Currently the code presented in the page style is more casual, adhering to the principle able to open the line of development to this point, we should look at a little landscaping.

Introducing less

First install the required libraries

npm install --save @zeit/next-less less

Then inline style header inside and removed mylayout

New assets / css / styles.less

.header {
  display: block;
  z-index: 500;
  width: 100%;
  height: 60px;
  font-size: 14px;
  background: #fff;
  color: rgba(0, 0, 0, 0.44);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
  letter-spacing: 0;
  font-weight: 400;
  font-style: normal;
  box-sizing: border-box;
  top: 0;

  &:after {
    box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.07);
    display: block;
    position: absolute;
    top: 60px;
    color: rgba(0, 0, 0, 0.07);
    content: "";
    width: 100%;
    height: 2px;
  }

 .header-inner {
    width: 1000px;
    margin: 0 auto;

    a {
      height: 60px;
      line-height: 60px;
      font-size: 18px;
      color: #c7c7c7;
      cursor: pointer;
      margin-right: 25px;
      &:hover {
        font-size: 18px;
        color: #2d2d2f;
      }
    }
  }
}

.content {
  width: 1000px;
  margin: 0 auto;
  padding-top: 30px;
}

Modify next.config.js

// next.config.js
const withLess = require('@zeit/next-less')
module.exports = withLess({
  /* config options here */
})

Introducing less in MyLayout inside

import "../assets/css/styles.less";

In localhost: 6688 View page appears appropriate style

next-less documentation

Introduced antd

npm install antd --save
npm install babel-plugin-import --save-dev

touch.babelrc

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd",
        "style": "less"
      }
    ]
  ]
}

After the introduction of antd style

assets/css/styles.less

@import "~antd/dist/antd.less";

This time is normally introduced into the assembly antd be using it

import { Typography, Card, Avatar } from "antd";
const { Title, Paragraph, Text } = Typography;

Error Resolution

ValidationError: Invalid options object. CSS Loader has been initialised using an options object that does not match the API schema. - options has an unknown property 'minimize'. These properties are valid: #541

The new version css-loader and webpack there such a mistake, this is the upgrade code changes led, css-loader has no minimize this option.

Solution, add the removal of the code in next.config.js

const withLess = require("@zeit/next-less");

if (typeof require !== "undefined") {
  require.extensions[".less"] = file => {};
}

function HACK_removeMinimizeOptionFromCssLoaders(config) {
  console.warn(
    "HACK: Removing `minimize` option from `css-loader` entries in Webpack config"
  );
  config.module.rules.forEach(rule => {
    if (Array.isArray(rule.use)) {
      rule.use.forEach(u => {
        if (u.loader === "css-loader" && u.options) {
          delete u.options.minimize;
        }
      });
    }
  });
}

module.exports = withLess({
  lessLoaderOptions: {
    javascriptEnabled: true
  },
  webpack(config) {
    HACK_removeMinimizeOptionFromCssLoaders(config);
    return config;
  }
});

Application deployment Next.js

Install now, a static resource server hosting

npm i -g now

now

After waiting a period of time will generate a static link, click to open the way you can see your page the https://next-demo.fuhuodemao.now.sh/

zeit now document

Packaging production environment of code

View the script package.json

    "dev": "next -p 6688",
    "build": "next build",
    "start": "next start -p 6688",

Now execute commands to generate code and preview

npm run build // 构建用于生产的Next.js应用程序
npm start // 在6688端口上启动Next.js应用程序.该服务器将进行服务器端渲染并提供静态页面

In localhost: 6688 on we can see the same effect

Open multiple ports

Modify the script command

 "start": "next start -p 6688",

Then execute npm start, we can localhost: open an application again on 8866

The need for additional tools cross-env in the window

npm install cross-env --save-dev

reference

Guess you like

Origin www.cnblogs.com/mybilibili/p/11615055.html
Recommended