默认的约定只有一个,那就是所有页面都放在
pages
下面,静态资源放在public
下面
组件中获取router信息
import { useRouter } from 'next/router';
const Page = () => {
const router = useRouter();
return (
<Layout>
<h1>{router.query.title}</h1>
<p>This is the blog post content.</p>
</Layout>
);
};
路由
动态路由: 创建文件 /pages/p/[id].js
(不能用 /pages/p/post-[id].js
)
https://github.com/zeit/next.js/tree/canary/examples/dynamic-routing
// href后面接自己定义的路径,as接真实展示在浏览器上的URL
<Link href="/p/[id]" as={`/p/${props.id}`}>
<a>{props.id}</a>
</Link>
路由跳转
import Link from 'next/link';
import Router from 'next/router';
<Link href="/">跳转</Link>
Router.push('/')
shallow routing: 改变路由的query值而不触发getInitialProps函数, 方法为router.push(url, null, {shallow: true})
function Page() {
const router = useRouter()
useEffect(() => {
// Always do navigations after the first render
router.push('/?counter=10', null, { shallow: true })
}, [])
useEffect(() => {
// The counter changed!
}, [router.query.counter])
}
请求后端
function parseURL(ctx, s) {
if (ctx.req) {
return `http://0.0.0.0:${port}${s}`;
}
return s;
}
Page.getInitialProps = async function (context) {
const { id } = context.query;
// 注意的是这里的URL不能直接用/api/index
// 因为服务端渲染时必须要是完整的URL,例如http://0.0.0.0/api/index
const res = await fetch(parseURL(`/api/index`));
const show = await res.json();
console.log(`Fetched show: ${show.name}`);
return { show };
};
共用Layout
pages/_app.js
import Layout from "../components/layout/Layout";
export default function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
css样式
styled-jsx
: https://github.com/zeit/styled-jsx
css样式写在jsx里面, 而且这些css样式只对当前组件起作用,不会对父/子组件起作用
<style jsx>{`
h1,
a {
font-family: 'Arial';
}
`}</style>
全局作用域的css样式:在 pages/_app.js
中直接import
import '../styles.css'
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
组件级别的css:基于CSS Modules
, 命名方式为 [name].module.css
, 引入方式为import styles from 'your-css-file'
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
// Note how the "error" class is accessed as a property on the imported
// `styles` object.
className={styles.error}
>
Destroy
</button>
)
}
使用less
https://github.com/zeit/next-plugins/tree/master/packages/next-less
$ cnpm i -S less @zeit/next-less
不使用css module
// next.config.js
const withLess = require('@zeit/next-less')
module.exports = withLess({
/* config options here */
})
// 组件中使用
import './style.less';
使用css module
// next.config.js
const withLess = require('@zeit/next-less')
module.exports = withLess({
cssModules: true,
cssLoaderOptions: {
importLoaders: 1,
localIdentName: "[local]___[hash:base64:5]",
}
})
// 组件中使用
import styles from './index.less';
内置API: pages/api
pages/api/user.js
对应路由 /api/user
export default (req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify({ name: 'John Doe' }))
}
配合koajs使用
https://github.com/zeit/next.js/tree/canary/examples/custom-server-koa
const Koa = require('koa');
const next = require('next');
const Router = require('koa-router');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
router.get('/a', async ctx => {
await app.render(ctx.req, ctx.res, '/a', ctx.query);
ctx.respond = false;
})
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(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
preact
https://github.com/zeit/next.js/tree/canary/examples/using-preact
antd
https://github.com/zeit/next.js/blob/canary/examples/with-ant-design
$ npm init next-app --example with-ant-design app_name
部署
pm2部署
$ pm2 start npm --name "app_name" -- start
需要注意的坑
获取user-agent,要先判断是服务端还是客户端再获取
Page.getInitialProps = async ({ req }) => {
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
return { userAgent }
}
<Link href="/"></Link>
中必须要包含<a></a>