默認的約定只有一個,那就是所有頁面都放在
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>