先说说先要搭建这个工具的原由吧!最近这段时间分别了学习Typescript和react服务端渲染,可是苦于没有没有实际使用端场景,我就忽然想起了将Typescript与Next结合起来搭建一个服务端渲染端工具,一是这样便可以起到练手的做用,二是若是之后有相应业务需求能够直接拿来用。话很少说,咱们开始吧!javascript
next.js做为一款轻量级的应用框架,主要用于构建静态网站和后端渲染网站,为何选Next呢?,只因Next有以下几个优势:前端
这里就很少说了,相信你们都很熟练了java
mkdir TAN
cd TAN
npm init -y
复制代码
npm install react react-dom express next --save
npm install @types/{react,react-dom} --save-dev
复制代码
export default () => <div>Welcome to next.js!</div>
复制代码
{
...
"scripts": {
"dev": "next"
}
...
}
复制代码
运行npm run dev命令打开 http://localhost:3000便可查看初始页面。node
npm install typescript --save
复制代码
@zeit/next-typescript 再也不须要,由于Next.js已内置支持Typescriptreact
{
"presets": [
"next/babel"
]
}
复制代码
{
"compileOnSave": false,
"compilerOptions": {
"strict": true,
"target": "esnext",
"module": "esnext",
"jsx": "preserve",
"allowJs": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": false,
"preserveConstEnums": true,
"sourceMap": true,
"skipLibCheck": true,
"baseUrl": ".",
"typeRoots": [
"./node_modules/@types/",
],
"lib": [
"dom",
"es2015",
"es2016"
]
},
"exclude": ["node_modules"]
}
复制代码
在上面的配置中,请注意: 使用“jsx”:“preserve”而不是react-native,由于Next.js在5.0.0以后支持.jsx文件扩展名,以前它只识别.js文件。webpack
{
"extends": ["tslint:latest"],
"rules": {
"arrow-parens": false,
"interface-name": [true, "never-prefix"],
"no-object-literal-type-assertion": false,
"no-submodule-imports": false,
"semicolon": [true, "never"],
"trailing-comma": [true, {"multiline": "nerver", "singleline": "never"}]
}
}
复制代码
将page/index.js修改成index.tsx,并作以下修改git
interface Person {
name: String;
}
const Rashomon: Person = {
name: 'rashomon',
}
export default () => <div>{Rashomon.name}!</div>
复制代码
const next = require('next');
const { createServer } = require('http');
const { parse } = require('url')
const dev = process.env.NODE_ENV !== 'production';
const port = parseInt(process.env.PORT, 10) || 3000;
const app = next({dev})
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true)
handle(req, res, parsedUrl)
}).listen(port, err => {
console.log(err, port)
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
复制代码
更改package.json启动命令 "dev": "node server.js", 运行npm run dev,你会发现提示一行错误:It looks like you're trying to use TypeScript but do not have the required package(s) installed.意思是试图使用TypeScript,但没有安装所需的包。咱们只需运行下列命令便可github
npm install --save-dev @types/node
复制代码
再次运行命令打开http://localhost:3000便可看到咱们的页面。web
npm install antd --save
npm install babel-plugin-import --save-dev
复制代码
{
"presets": [
"next/babel"
],
"plugins": [
["import", { "libraryName": "antd", "style": false }]
]
}
复制代码
npm install less @zeit/next-less null-loader --save
复制代码
const withLess = require('@zeit/next-less');
module.exports = withLess({
lessLoaderOptions: {
javascriptEnabled: true,
},
webpack: (config, { isServer }) => {
if (isServer) {
const antStyles = /antd\/.*?\/style.*?/
const origExternals = [...config.externals]
config.externals = [
(context, request, callback) => {
if (request.match(antStyles)) return callback()
if (typeof origExternals[0] === 'function') {
origExternals[0](context, request, callback)
} else {
callback()
}
},
...(typeof origExternals[0] === 'function' ? [] : origExternals),
]
config.module.rules.unshift({
test: antStyles,
use: 'null-loader',
})
}
return config
},
})
复制代码
3.引入antd样式
在page文件夹下新建index.less文件,引入antd样式,并在index.tsx中引入,typescript
@import '~antd/dist/antd.less';
复制代码
并在index.tsx中作以下修改
import {Button} from 'antd';
import './index.less'
interface Person {
name: String;
}
const Rashomon: Person = {
name: 'rashomon',
}
export default () => <Button type='primary'>{Rashomon.name}!</Button>
复制代码
npm install less-vars-to-js --save
复制代码
根目录下新建assets文件并新建antd-custom.less
@primary-color: #08979c;
复制代码
在next.config.js中读取该样式文件,通过less-vars-to-js将less文件的内容做为字符串接收,并返回一个包含全部变量的对象。
next.config.js添加以下内容:
... // 添加内容
const lessToJS = require('less-vars-to-js');
const fs = require('fs');
const path = require('path');
// Where your antd-custom.less file lives
const themeVariables = lessToJS(
fs.readFileSync(path.resolve(__dirname, './assets/antd-custom.less'), 'utf8')
)
...
lessLoaderOptions: {
javascriptEnabled: true,
modifyVars: themeVariables,
},
···
复制代码
运行启动命令,页面以下图:
npm install redux react-redux next-redux-wrapper @types/react-redux --save
npm install redux-saga next-redux-saga @types/next-redux-saga --save
复制代码
因为篇幅关系建立store、reducers、saga、action的过程咱们就再也不这里缀述,感兴趣的同窗能够查看github上的代码。咱们在这里着重讲一下如何引入store,为了在页面初始化时引入store,须要自定义,在pages文件夹下新建_app.tsx.
_app.tsx帮咱们作以下几件事:
所以,在pages文件下新建_app.tsx,引入store,代码以下
import React from 'react'
import App from 'next/app';
import { Provider } from 'react-redux';
import Head from 'next/head'
import withRedux from 'next-redux-wrapper'
import withReduxSaga from 'next-redux-saga'
import Layout from '../components/Layout' // 页面基础布局
import initStore from '../redux/store' // store
import '../static/style/index.less' // antd样式
class MyApp extends App {
// next.js提供了一个标准的获取远程数据的接口:getInitialProps,经过getInitialProps咱们能够获取到远程数据并赋值给页面的props。
// getInitialProps便可以用在服务端也能够用在前端
static async getInitialProps({ Component, ctx }: any) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ ctx });
}
return { pageProps };
}
render() {
const { Component, pageProps, store }: any = this.props
return (
<Provider store={store}> <Head> <title>Tarn</title> </Head> <Layout> <Component {...pageProps} /> </Layout> </Provider> ) } } export default withRedux(initStore)(withReduxSaga(MyApp)) 复制代码
最终实现一个计数器与列表,以下图:
404和500错误客户端和服务端都会经过error.js组件处理。若是你想改写它,则在pages文件下新建_error.js,当用户访问错误路由时会访问_error页面
import React from 'react'
export default class Error extends React.Component {
static getInitialProps({ res, err }) {
const statusCode = res ? res.statusCode : err ? err.statusCode : null;
return { statusCode }
}
render() {
return (
<p>
{this.props.statusCode
? `An error ${this.props.statusCode} occurred on server`
: 'An error occurred on client'}
</p>
)
}
}
复制代码
到此为止,咱们已经基本实现了一个基于Typescript+Ant-Design + Redux+Next.js的服务端渲染框架,也熟悉了一部分next的用法,想要了解更多能够前往官网地址为next.js。但愿你们能够有所收获,想要了解更多不一样技术实现的服务端渲染框架的同窗能够看这里github.com/zeit/next.j…
原文在这里:gitHub 若有遗漏,还请指正!!
若是以为对您有帮助!请别忘记点个赞或者关注哦!您的关注将是我前进的动力!!冲鸭!!!
「无畏前端」不定时更新社区优秀技术文章!