淘先锋技术网

首页 1 2 3 4 5 6 7

1. 建立项目

安装 create-next-app 脚手架

npm i -g create-next-app

用脚手架简历next项目

create-next-app nextjs_react

创建完成后项目目录

├─ /.next              <-- 用于SSR运行的工程,执行yarn dev或yarn build后才会出现
├─ /node_modules
├─ /pages              <-- Next.js指定的页面目录
|  ├─ /api             <-- Next.js指定的API服务目录,可以删除
|  |  └─ hello.js      <-- API服务的hello接口
|  ├─ _app.js          <-- Next.js指定的项目入口文件
|  └─ index.js         <-- 项目首页
├─ /public             <-- 静态目录,放在这里的文件可通过"/"直接访问(没有public这一层级)
|  ├─ favicon.ico
|  └─ vercel.svg
├─ /styles             <-- 项目全局样式
|  ├─ globals.css
|  └─ Home.module.css  <-- Home组件样式
├─ .eslintrc.json
├─ .gitignore
├─ next.config.js      <-- Next.js配置文件
├─ package.json
├─ README.md
└─ yarn.lock

2. 更改项目目录结构

  1. 根目录下新增 src 目录
  2. 把 pages 目录放到 src 目录里
  3. 在 src 目录下新建 common 目录
  4. 将 styles 目录放到 common 目录下

最终初始目录结构如下:

/src
├─ /common            <-- 公用目录
|  ├─ /images         <-- 公用图片目录
|  └─ /styles         <-- 公用样式目录
├─ /components		  <-- 公用组件目录
└─ /pages             <-- Next.js指定的页面目录
   ├─ /api            <-- Next.js指定的API服务目录(不会生成api页面目录)
   ├─ _app.js         <-- Next.js指定的项目入口文件(不会生成_app.html)
   └─ index.js        <-- index页面(会生成index.html)

3. 配置项目

tsconfig.json文件中添加如下配置:

"compilerOptions": {
    "baseUrl": ".",
    "paths": {
        "@/*": [
            "src/*"
        ]
    }
}

src/pages/_app.js修改页面title:

import '@/common/styles/globals.scss'
import type { AppProps } from 'next/app'
import Head from 'next/head'

export default function App ({ Component, pageProps }: AppProps) {
    return (
        <>
            <Head>
                <title>nextjs_react</title>
            </Head>
            <Component {...pageProps} />
        </>
    )
}

4. 集成Sass/Scss

安装sass

npm i sass --save

nextjs有内置sass,在配置next.config,js里面打开

const path = require('path')
module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
}

5. 配置axios

安装axios:

npm i axios --save

在src目录下新建utils/axios.ts

import axios from 'axios'
import qs from "qs"

axios.defaults.timeout = 30000
axios.defaults.withCredentials = true // 跨域设置
axios.defaults.baseURL = ''

const cancelArr: Array<any> = [];
export { cancelArr }

// 请求拦截器
axios.interceptors.request.use(
    (config: any) => {
        // 一些请求拦截操作
        
        return config;
    },
    (error: any) => {
        return Promise.reject(error);
    }
)

// 响应拦截器
axios.interceptors.response.use(
    (response: any) => {
        return response
    },
    (error: any) => {
        return Promise.reject(error)
    }
)

export default axios

/**
 * post 请求方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function post (url: string, data = {}, responseType: any) {
    return new Promise((resolve, reject) => {
        axios.post(url, data, {
            responseType,
            cancelToken: new axios.CancelToken(function executor (cancel) {
                cancelArr.push({
                    cancel
                })
            })
        }).then(
            response => {
                if (response) {
                    resolve(response.data);
                } else {
                    console.log("取消了")
                }
            },
            err => {
                reject(err);
            }
        );
    });
}

/**
 * get 请求方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function get (url: string, data = {}) {
    return new Promise((resolve, reject) => {
        axios.get(url, data).then(
            response => {
                resolve(response.data);
            },
            err => {
                reject(err);
            }
        );
    });
}

解决跨域问题:

  1. 安装插件:
    npm i express http-proxy-middleware

  2. 在项目根目录中新建 server.js

const express = require('express')
const next = require('next')
const { createProxyMiddleware } = require('http-proxy-middleware')

// 配置代理
const devProxy = {
    '/api': {
        target: 'http://192.168.xx.xx:8000', // 端口自己配置合适的
        pathRewrite: {
            '^/api': '/api'
        },
        changeOrigin: true
    }
}

// 运行端口
const port = parseInt(process.env.PORT, 10) || 3000
// 判断是否为开发环境
const dev = process.env.NODE_ENV !== 'production'
// 初始化app
const app = next({
    dev
})
const handle = app.getRequestHandler()

app.prepare()
    .then(() => {
        const server = express()

        // 开发环境下使用代理接口
        if (dev && devProxy) {
            Object.keys(devProxy).forEach(function (context) {
                server.use(createProxyMiddleware(context, devProxy[context]))
            })
        }

        server.all('*', (req, res) => {
            return handle(req, res)
        })

        server.listen(port, err => {
            if (err) {
                throw err
            }
            console.log(`> Ready on http://localhost:${port}`)
        })
    })
    .catch(err => {
        console.log(err, 'error')
    })

  1. 修改package.json
"scripts": {
  "dev": "node server.js",
  "build": "next build",
  "start": "NODE_ENV=production node server.js",
  "lint": "next lint"
},

参考文章