2019-03-17
上一篇介绍了静态网站,在本篇中我们来看系列的主角——react-static 静态网站生成器。在本文中,我们将对它进行一个全面的介绍。
react-static 是一个 React 的静态网站生成器。
通俗来说就是:
当然,不是说任何 React 网站通过它都能变静态。react-static 是一个框架,它定义了一些规则。React 应用必须按照他定义的概念、规则来编写,才能工作。
如果你对上面的过程有困惑,可以先看下上一篇。
在本文中我们就来详细介绍这些规则。
我们先来看下 react-static 所提供的特性:
特性 | 说明 |
---|---|
100% React | 原汁原味 React 开发,不会额外添加奇奇怪怪的约束 |
超快的构建速度 | 构建速度是真的快,还十分可靠 |
超快的性能 | 预加载功能开箱即用,网页秒跳 |
多样的数据来源 | 向页面传入的数据来源由自己决定(自己写 JS 脚本),API,数据库,json…… |
自动代码和数据分离 | 代码是代码,数据是数据,相互隔离,架构十分清晰 |
通过 PRPL 预加载秒跳转 | 比较新的一种 PWA 页面预加载模式,我还没有研究过,不过开箱即用,已经先用上了 🤣 |
Progressive Enhancement + Graceful Fallbacks | 框架作者本行就是搞 SPA 的 SEO 的。构建出的静态站的 SEO 完全正常 |
React-first | React 优先,类似 Python 的 Pythonic 概念,这里推崇的是 Reactic 😆 |
无痛项目设置与迁移 | 亲身经历,我将本站从一个自己写的框架迁移到 react-static,迁移成本真的很低 |
100% 支持 React 生态 | CSS-in-JS、GraphQL,连 Redux 都支持 |
开箱即用热加载 | 代码写完一保存,界面就立刻更新了,所见即所得,开发效率高 |
扩展性 | 静态生成器一个很重要的指标是网站生成时间与数据规模的关系。我之前写过一个框架放弃了,原因就是生成时间与数据规模成正比……react-static 则完全感受不到生成变慢 |
静态网站主要分为两部分:数据与模板。
以博客文章页为例:
在 react-static 中这两部分如下图:
其中:
前面说过,不是说任何 React 网站通过它都能变静态。react-static 是一个框架,它定义了一些规则。React 应用必须按照他定义的概念、规则来编写,才能工作。
下面是时候深入水下啦!
static.config.js 是基于 react-static 的静态网站的核心配置文件,各种规则大部分都在这里定义。
它位于项目的根目录。我们以 maxiee.github.io 的配置文件实例来看下它的主要内容(完整选项可参见文档):
// 博客画作板块的数据提供方法 // 画作位于 maxieePaintPath 变量对应的目录下,里面是一系列图片文件 // getMaxieePaints 方法获取这些图片的路径 const getMaxieePaints = () => { return getAllFiles(maxieePaintPath) .map(v => getFileName(v)) } export default { plugins: ['react-static-plugin-typescript'], // 开启 TypeScript 支持 entry: path.join(__dirname, 'src', 'index.tsx'),// 指定入口文件 siteRoot: "https://maxiee.github.io", // 网站域名 getSiteData: () => ({ // 网站全局数据 title: 'Maxiee Blog' // getSiteData 提供的数据 }), // 在模板中通过特定 HOC 能获取到 // getRoutes 方法最为重要,它定义了你的网站中都有哪些路径 // 这些路径使用什么组件(模板)进行展示 // 也定义了如何向模板提供数据 // 这里以博客的画作板块为例 getRoutes: async ({dev}) => { let maxieePaints = getMaxieePaints() // 获取所有画作路径 return [ // 数组,内部包含多个路径模板 { path: '/', // 定义首页 getData: () => ({ // 首页模板所传入的数据 blogList: posts // 这里传入的是所有帖子的列表 }), children: posts // children 表示首页子页面,这里是文章页 .sort((a, b) => { ... } // 按照发布时间排序 .map(post => { // 读取 markdown let content = fs.readFileSync( // 读取 markdown 文件内容 "./content/blog/posts/" + post.link, 'utf8') let retData = Object.assign(// 将文章内容放入 retData 结构 {}, post, {article: content} ) return { // 返回路由结构 path: `/post/${post.link}/`, // 路径 component: 'src/containers/Post', // 指定渲染模板组件 getData: () => ({ // 向模板提供数据 post: retData, dev: dev }) } }) }, { path: '/gallery/', // 定义路径 getData: () => ({ // getData 中定义的数据结构就是 paints: maxieePaints, // 传入模板的数据结构 dev: dev // 这里把所有画作的路径传入 }) }, ... ] } }
上面就是 react-static 核心配置文件 static.config.js 的一个实例,其中:
/
对应于网站首页,传入的数据是博客的列表,会被框架与 src/pages/index.tsx
自动关联/
下有一个子路由,即 /post/${post.link}/
这是博客文章,它的渲染组件是我们指定的,为 src/containers/Post
'/gallery/'
会被框架与 src/pages/gallery.tsx
自动关联接下来我们就进入网站的视图(模板)部分。所有视图、模板都是 React 高阶组件,下面我们以首页( src/pages/index.tsx
)为例:
import { withRouteData } from 'react-static' // 首页 export default withRouteData(({blogList} : {blogList : any[]}) => ( <Fragment> <Helmet> <meta charSet="UTF-8" /> <title>{BLOG_NAME} | Maxiee 的知识积累</title> </Helmet> <PostListView posts={blogList}/> </Fragment> ))
其中:
下面我们再来看博客的画作(/gallery/
)板块:
import { withRouteData } from 'react-static' export default withRouteData(({paints, dev} : {paints : [string], dev : boolean}) => { return <GalleryComponent paints={paints.reverse()} dev={dev}/> })
其中:
通过这两个页面我们能够感觉到,这的确是原汁原味的 React 开发体验。
也许你会有疑问,上面两个模板都只有正文部分的内容,侧边栏、顶部导航栏是在哪里定义的呢?
他们位于 src/App.tsx
下:
import React from 'react' import {Root, Routes} from 'react-static' import 'semantic-ui-css/semantic.min.css' import { Grid } from 'semantic-ui-react'; import SideBar from './components/sidebar/SideBar' import NavBar from '@components/NavBar'; function App() { return ( <Root> <Grid stackable stretched relaxed> <Grid.Column width={3} style={{paddingRight: 0}}> <SideBar /> </Grid.Column> <Grid.Column width={13} style={{paddingLeft: 0}}> <NavBar selected=''/> <Routes /> </Grid.Column> </Grid> </Root> ) } export default App
其中:
也许看了上面这些,还是会觉得认识不够透彻。这很正常,因为 react-static 这种开发方式比较新颖。
彻底认识透彻的方法也很简单,react-static 官方提供了大量示例,只需要把他们 clone 下来跑一跑看一看,getting hands dirty。
具体包括如下:
其中,在 react-static 项目首页的 Sites Built with React-Static 一节中,还有很多使用 react-static 构建的网站是提供源码的,这也是很好的学习资源。
我将 Getting Start 放在最后,因为自己当时在初学的时候,因为对理论的不熟悉,怎么都 Getting Start 不起来。
最终当我将 react-static 的概念理解透彻后(也就是前文的内容),自然而然就上手了。
react-static 自身是一个命令行工具,安装方法:
$ yarn global add react-static
# or
$ npm install -g react-static
创建项目:
$ react-static create
运行开发服务器:
$ yarn start # or react-static start
构建项目:
$ yarn build # or react-static build
本地托管:
$ yarn serve
react-static 首页中有大量的学习资源,包括框架作者的 YouTube 演讲,强烈建议观看。
如果你想搭建一个静态网站,想要自己从头搭建,同时又使用 React,那么 react-static 绝对是首选之一。
在后续的文章中,我会继续更新 react-static 更多的使用技巧。欢迎关注~