NextJS基础配置详解
看到了很多Next的基础教程,但是没找到有关于next.config.js
详细讲解,这里准备把自己平常用的写下来供大家参考。
配置环境变量
一般在项目开发中会分好几个环境,最常见的比如开发环境(dev)、测试环境(test)、生产环境(prod),既然分这么多环境,一般我们就需要用到环境变量来进行区分配置,我在next
项目中区分环境变量用下面这种方式。
首先在package.json
中添加cross-env
,通过cross-env
传递不同的环境变量,配置如下:
// package.json
{
"scripts": {
"dev": "cross-env NODE_ENV_API=dev next dev -p 3000", // 配置dev环境
"test": "cross-env NODE_ENV_API=test next dev -p 3000", // 配置test环境
"prep": "cross-env NODE_ENV_API=prep next dev -p 3000", // 配置prep环境
"prod": "cross-env NODE_ENV_API=prod next dev -p 3000", // 配置prod环境
}
}
上面我们总共配置了四个环境,我们可以在next.config.js
中通过process.env.NODE_ENV_API
获取到我们设置的环境变量,然后通过next
提供的publicRuntimeConfig
对象传递到我们的项目中,代码如下:
// next.config.js
{
"publicRuntimeConfig": { //这里的配置既可以服务端获取到,也可以在浏览器端获取到
"NODE_ENV_API": process.env.NODE_ENV_API || "prod",
},
}
在项目中使用,如下:
// config.ts
import getConfig from 'next/config'
export const { NODE_ENV_API = "prod" }: { NODE_ENV_API: "dev" | "test" | "prep" | "prod" } = getConfig().publicRuntimeConfig
// 接口前缀
export const BASE_URL: string = (() => {
let BASE_URL = "http://www.api.com/api/dev"
switch (NODE_ENV_API) {
case "dev":
BASE_URL = "http://www.api.com/api/dev"
break
case "test":
BASE_URL = "http://www.api.com/api/test"
break
case "prep":
BASE_URL = "http://www.api.com/api/prep"
break
case "prod":
BASE_URL = "http://www.api.com/api/prod"
break
}
return BASE_URL
})()
sass中引入环境变量&添加全局sass文件
在next
中,next
默认支持sass,允许我们导入(import)具有 .scss
和 .sass
扩展名的 Sass
文件。
next.config.js
中提供了sassOptions
方法来配置sass
编译器。我们可以通过它提供的方法来导入全局变量与配置,比如:
// next.config.js
{
"sassOptions": {
"includePaths": [path.join(__dirname, 'styles')], // 存放 variables.module.scss 文件夹路径
},
}
/* variables.module.scss */
$primary-color: #64FF00
:export {
primaryColor: $primary-color
}
// pages/_app.js
import variables from '../styles/variables.module.scss'
export default function MyApp({ Component, pageProps }) {
return (
<Layout color={variables.primaryColor}>
<Component {...pageProps} />
</Layout>
)
}
除了上面的方法我们也可以通过additionalData
添加全局变量与scss
文件,如下:
// next.config.js
{
"sassOptions": {
additionalData(content, loaderContext) {
let $env = ""
switch (process.env.NODE_ENV_API) { // 通过环境变量来配置不同的全局变量
case "dev":
$env = "dev"
break;
case "test":
$env = "test"
break;
case "prep":
$env = "prep"
break;
case "prod":
$env = "prod"
break;
}
let config = "@import './styles/mixin.scss';"; // 添加全局sass文件,也可以通过环境变量改变引入文件,来加载不同的主题色。
if(!$env) {
config = config + `$env: "";@import './styles/var.scss';` + content;
}else {
config = config + `$env: "${$env}";@import './styles/var.scss';` + content;
}
return config
},
},
}
处理svg文件
在next
中使用svg文件非常简单,我们只需要引入@svgr/webpack
依赖,修改一下webpack
配置即可如下:
// next.config.js
{
webpack(webpackConfig) {
webpackConfig.module.rules.push({
test: /\.svg$/,
use: [ "@svgr/webpack" ]
}); // 针对 SVG 的处理规则
return webpackConfig
},
}
通过上面的配置我们就可以在项目中直接使用svg
文件了
// home.tsx
import DownIcon from "../../svg/down_icon.svg"
export default function Page() {
return (
<>
<DownIcon />
</>
)
}
路由添加后缀(.html、.htm、.php、.shtml)
我们去写next
时有的时候项目第一期写完了很有可能会碰到这种需要,xxx来说大哥这个网页地址栏(路由)后面能不加个后缀啊,加个.html
的后缀。我们去添加这个后缀的时候,大部分可能会直接选择去修改文件名称,比如把Home
目录改为Home.html
,其实我们也可以通过next.config.js
中提供的rewrites
方法去给路由添加多个映射路径,简单来说就是多个匹配地址来解决上面的需求。
比如说我们想让路由支持.html
、.htm
后缀,如下:
{
// 映射多个路径
async rewrites() {
return [
{ // 登录
source: '/login(.html|.htm)?(.*)', // 我们要支持请求的路径
destination: '/login', // next中要路由到的路径
},
{ // 详情页面
source: '/desc(.html|.htm|.php)', // 我们要支持请求的路径 /desc.html /desc.htm /desc.php
destination: '/desc', // next中要路由到的路径
},
]
}
}
通过上面的方法我们就不用修改目录或文件名称了,如果要配置动态路由也很简单,如下:
{
// 映射多个路径
async rewrites() {
return [
{ // 详情
source: '/desc/:params(\\d{1,})(.html|.htm)?(.*)', // 匹配的对应地址 /desc/123 /desc/123.html /desc/1333.htm
destination: '/desc/:params',
},
{ // 详情
source: '/desc_:params(\\d{1,})(.html|.htm)?(.*)', // 匹配的对应地址 /desc_123 /desc_123.html /desc_1333.htm
destination: '/desc/:params',
},
]
}
}
添加移动端viewport配置
我们如果要通过next
去写m站,我们可以通过postcss-px-to-viewport
,将px
单位自动转换成viewport
单位,去适配手机浏览器,我们只需要安装postcss-loader
与postcss-px-to-viewport
依赖,并且在根目录下创建postcss.config.js
即可。
// postcss.config.js
module.exports = {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px', //需要转换的单位,默认为"px"
viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度
// viewportHeight: 1334,//视窗的高度,根据375设备的宽度来指定,一般指定667,也可以不配置
unitPrecision: 13, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
propList: ['*'], // 能转化为vw的属性列表
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
fontViewportUnit: 'vw', //字体使用的视口单位
// selectorBlackList: ['.ignore-', '.hairlines'], //指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false, // 允许在媒体查询中转换`px`
replace: true, //是否直接更换属性值,而不添加备用属性
exclude: [
/RightBar/,
/gotop.vue/,
], //忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
// landscape: false, //是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: 'vw', //横屏时使用的单位
// landscapeWidth: 1134 //横屏时使用的视口宽度
}
}
}
修改UI组件的样式
修改UI库组件样式是一件挺麻烦的事情,我一般去修改UI组件样式时喜欢用下面的方法。
.page {
:global {
.antd_btn { // 组件的class
display: inline-block;
width: 5px;
height: 5px;
margin-left: 4px;
background: #FF4F74;
border-radius: 50%;
}
}
}
项目打包部署
-
自定义服务器打包部署 我们通过执行打包命令,会在目录下构建一个
.next
文件,我们只需要把.next
、public
、package.json
、next.config.js
与自定义的server.js
上传到服务器然后安装依赖启动服务即可。 -
使用
pm2
与koa
部署服务器 我比较喜欢使用pm2
加koa
部署next
,因为可以去自定义一些配置,下面是我的server.js
。
// server.js
const Koa = require('koa')
const next = require('next')
const Router = require('@koa/router')
const logger = require('koa-logger')
const port = 4050 // 服务端口号
const app = next({})
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = new Koa()
const router = new Router()
router.all('(.*)', async (ctx) => {
await handle(ctx.req, ctx.res)
ctx.respond = false
})
server.use(async (ctx, next) => {
ctx.res.statusCode = 200
await next()
})
server
.use(logger({
transporter: (str, args) => {
const arr = [ "_next/static/", "/favicon.ico", "/assets/" ]
if(typeof str === "string") {
const find = arr.find(item => str.includes(item))
if(!find) {
console.log(str)
}
}
// redirect koa logger to other output pipe
// default is process.stdout(by console.log function)
}
}))
.use(router.routes())
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`)
})
})
pm2
配置文件如下
// ecosystem.config.js
module.exports = {
apps: [
{
name: 'xxxxxx', // 项目名称
// script: './node_modules/nuxt/bin/nuxt.js', // 启动脚本
script: './server.js', // 启动脚本
args: 'start',
// cwd: './.nuxt',
watch: false, // 是否开启监听
exec_mode: 'cluster', // 分為 cluster 以及 fork 模式
instances: '4',
max_memory_restart: '400M', // 當佔用的 memory 達到 400M, 就自動重啟
// pm2 會根據此選項內的時間來判定程序是否有成功啟動
// 格式可使用 number 或 string, number 的話, 3000 代表 3000 ms。 string 的話, 可使用 '1h' 代表一個小時, '5m' 代表五分鐘, '10s' 代表十秒
min_uptime: '15s',
listen_timeout: 15000, // 單位為 ms, 如果在該時間內 app 沒有聽 port 的話,強制重啟
ignore_watch: [ // 不用监听的文件
"node_modules",
"logs"
],
autorestart: true,
log_date_format: "YYYY-MM-DD HH:mm:ss",
error_file: "./logs/app-err.log", // 错误日志文件
out_file: "./logs/app-out.log",
// 环境变量配置
env_dev: {
NODE_ENV_API: "dev",
prot: 3000,
},
env_test: {
NODE_ENV_API: "test",
prot: 3000,
},
env_prep: {
NODE_ENV_API: "prep",
prot: 3000,
},
env_prod: {
NODE_ENV_API: "prod",
prot: 3000,
},
}
],
}
创建并配置好上面的文件之后,我们把上面的文件与next
打包文件上传到服务器,执行pm2启动命令即可
// PM2常用命令
pm2 start ecosystem.config.js --env=test // 启动服务 --env=test 对应的部署环境
pm2 reload name // name 填写 ecosystem.config.js 中的name也就是项目名称,进行重启
pm2 stop name // 停止服务
pm2 del name // 删除服务
pm2 ls // 查看pm2 启动列表与状态
pm2 restart all // 重启所有应用程序
pm2 stop all // 停止所有应用程序
pm2 del all // 关闭并删除所有应用程序
pm2 ecosystem // 生成一个示例json配置文件
- 使用
outputStandalone
来进行部署 因为官方文档写的已经很详细了,这里就不再写了,具体详情可以查看官方文档