Next.js踩坑入門系列
- (一) Hello Next.js
- (二) 新增Antd && CSS
- (三) 目錄重構&&再談路由
- (四) Next.js中期填坑
- (五) 引入狀態管理Redux
- (六) 再次重構目錄
- (七) 其他相關知識
個人對於腳手架的UI有一種執念,如果搭建出來就是一個首頁+a標籤跳轉,實在不是我這個處女座的風格,因此第二步我就想引用UI框架 —— ant-design,相信很多使用react的開發者用的也都是這個UI框架吧。因為以前自己在配製的時候也經常採坑,所以還是在這裡記錄一下~
安裝依賴
既然是安裝ant-design,那麼這兩個東西肯定是不能少的,一個是antd另一個就是antd官方的按需載入babel外掛babel-plugin-import。
// 安裝依賴
yarn add antd babel-plugin-import
複製程式碼
因為現在開發環境大部分過渡到ES6/ES7語法了,因此還需要安裝一個babel的裝飾器轉化外掛babel-plugin-transform-decorators-legacy,說實話這個外掛具體是幹啥的我還真沒太仔細看,不過裝上它在babel裡配置就可以使用antd了。
當然還有其他方法,我這裡只是使用了這一種方法~
// 根目錄新建.babelrc檔案
{
"presets": ["next/babel"],
"plugins": [
"transform-decorators-legacy",
[
"import",
{
"libraryName": "antd",
"style": "css"
}
]
]
}
複製程式碼
配置好了,我們來試一試,yarn dev
啟動專案,額,一大堆報錯,為啥呢?好像是服務端渲染的時候node端的問題吧,具體的我也不太清楚因為是入門有大神指導具體的可以留言教教小弟一下,不勝感激。反正查唄,因為原本在其他腳手架配置的時候需要在webpack裡配置一些東西嘛,這個怎麼可能沒有配置檔案呢?
當然有了,只不過改名了,叫做next.config.js了,上網查了一下,官方的解決方案就是引入一下next-css這個包,然後require.extensions['.css']
,還是那句話,我不理解,以後再深入研究一下,目前目的是可用~但是配置方案查到了就在這裡寫一下。
// 安裝依賴
yarn add @zeit/next-css
// 根目錄下建立next.config.js,內容如下
/* eslint-disable */
const withCss = require('@zeit/next-css');
// fix: prevents error when .css files are required by node
if (typeof require !== 'undefined') {
require.extensions['.css'] = (file) => {}
}
module.exports = withCss();
複製程式碼
好了,現在我們在啟動,就沒有報錯了,畢竟是官方解決方案,還是好使~把首頁的a標籤換成antd的button試試效果,效果是下面這樣:
額,果然沒這麼簡單,這又咋的了,也沒有任何報錯,也沒有任何提示,顯而易見就是樣式沒載入進來吧。。。繼續查,OK,明白了,其實antd的樣式已經有了,只不過在頁面上沒被引進來。為什麼這麼說呢?看下面兩幅圖: 可以看出來,第一個就是渲染出來的頁面head標籤裡沒有任何的CSS樣式,第二個就是antd的樣式檔案已經被打包放進.next資料夾的static資料夾裡面了。原因找到了,接下來就是解決問題了
Next.js Head元件
解決問題就是我們需要把那個style.css放到頁面裡,但是我翻遍了整個工程目錄,都沒有找到正常React SPA的那個index.html,尷尬了,有問題還是得找官方文件啊,查完過後發現了這個東西,Head,想看具體的可以點進去看官網,寫的挺詳細的~,就是我們可以使用這個head元件來為我們的頁面新增head資訊。
// /pages/index.js
import React, { Fragment } from 'react';
import { Button } from 'antd';
import Link from 'next/link';
import Head from 'next/head';
const Home = () => (
<Fragment>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1' />
<meta charSet='utf-8' />
<title>Next-Antd-Scafflod</title>
<link rel='stylesheet' href='/_next/static/style.css' />
</Head>
<Fragment>
<h1>我是Next的首頁</h1>
<Link href='/userList'>
<Button type='primary'>使用者列表頁</Button>
</Link>
</Fragment>
</Fragment>
);
export default Home;
複製程式碼
OK,到現在而言是不是有點NB了,O(∩_∩)O哈哈~,真的是採坑系列啊,配置一個UI元件就這麼麻煩。估計接下來有坑可踩啦!
抽離Head為Layout
一般的應用都會有個選單Menu導航條之類的嘛,所以頁面就做頁面的事情,head放裡面感覺怪怪的,還是按照習慣把Head抽離出來當成一個高階父元件吧。個人習慣,就新建了一個components資料夾,裡面新建Layout.js。
// /components/Layout.js
import Head from 'next/head';
export default ({ children }) => (
<div>
<Head>
<meta name='viewport' content='width=device-width, initial-scale=1' />
<meta charSet='utf-8' />
<title>Next-Antd-Scafflod</title>
<link rel='stylesheet' href='/_next/static/style.css' />
</Head>
<style jsx global>{`
body {
}
`}</style>
{children}
</div>
);
複製程式碼
// /pages/index.js
import React, { Fragment } from 'react';
import { Button } from 'antd';
import Link from 'next/link';
import Layout from '../components/Layout';
const Home = () => (
<Layout>
<Fragment>
<h1>Hello Next.js</h1>
<Link href='/userList'>
<Button type='primary'>使用者列表頁</Button>
</Link>
</Fragment>
</Layout>
);
export default Home;
複製程式碼
講到這裡,整個Antd的配置基本就完成了吧,哈哈,沒想到講個antd配置能寫這麼多,真實厲害了~既然UI框架嘛,順便我就把CSS也寫了吧。看Next官網可以很明確瞭解到它推崇的是css-in-js,具體連結大家請點這裡Next Css-in-Js,說白了,可以把它理解成用類Vue的形式寫React,元件內部使用下面這種形式來修改樣式
<style jsx>{`
p {
color: blue;
}
div {
background: red;
}
@media (max-width: 600px) {
div {
background: blue;
}
}
`}</style>
<style global jsx>{`
body {
background: black;
}
`}</style>
複製程式碼
這裡需要注意的是,元件內部的css並不是子元件繼承父元件,就是元件內部使用,如果想要子元件繼承父元件樣式,需要將style jsx改成style global jsx這種形式,說實話,越看越像Vue,^_^ 除了上面那種官方推薦的方法以外,還有其他很多種Css-in-Js的樣例,其中個人還是比較推薦styled-components的,大家感興趣可以去看官方文件,寫的真的很不錯。
留坑
以前我在用antd的時候,都會根據重置一下自帶配色以及一些其他的預設屬性,這裡我才用了以前的方式結果出錯了,以前的方式是依賴babel-plugin-import,在babelrc檔案裡將"style": "css"
改成"style": true
,這樣,babel-plugin-import會載入.less檔案,然後在webpack裡面配置less-loader的modifyVars變數進行覆蓋:
config.module.rules.push({
test: /\.less$/,
use: [
{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "less-loader",
options: {
sourceMap: true,
modifyVars: AntdTheme
}
}
]
})
複製程式碼
但是在next框架裡如果使用less方式引入服務端渲染會過不去,這算是一個坑?還是有解決辦法我沒查到,總之暫時這樣吧,改的話其實也可以改,用下面這種方式就好了,無關痛癢~
<style jsx global>{`
.ant-btn-primary {
background-color: #ec6a00
}
`}</style>
複製程式碼
你看,也可以改,不過個人覺得antd的配色還是挺不錯的,哈哈,就別改了。我認為官方後續會增強的吧!
可能官方早就有解決方案了吧,只不過我還是不太會用?因為我看除了next-css包以外還提供了next-less包,這個包應該就是用來載入less檔案的吧我看了一下這個包還支援css-modules,不過我配置了一下還是不太對,並且我對目前這種寫法還覺得挺舒服的,就不多浪費時間了,大家感興趣的可以攻克一下,解決了可以留言個地址給我,萬分感謝~
總結
第二篇寫完了,原本寫之前以為很簡單的兩下就完事了,沒想到中間踩了這麼多坑,因為我是一邊搭專案一邊寫的,所以個人認為還是比較詳細的,非常適合新手。像我這麼良心的寫手是不是很少了,哈哈。
程式碼地址
下一篇:準備好好講講路由然後簡單的整理一下專案骨架為了接下來的redux做準備~