Universal React
这是一个react脚手架项目,汇聚了一些平时自己用到的库,github地址,欢迎共同改进。
启动开发服务器
npm run dev
打包整个项目
npm run build
项目中集成的库
-
React
-
Redux
-
Redux Dev Tools
-
Redux Saga
-
React Router
-
Ant-UI
-
Babel
-
Webpack2
解释
执行npm run dev后,webpack将会建立build文件夹生成server.js,在启动服务器(node ./build/server.js)后会启动webpack-dev-middleware支持HMR。
服务器渲染SSR
match({ routes }, (error, redirectLocation, renderProps) => {
if (error) {
res.status(500).send(error.message);
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search)
} else if (renderProps) {
res.status(200);
ReactDOMServer.renderToStaticMarkup(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
);
store.closeSagas();
store.rootTask.done.then(() => {
const component = ReactDOMServer.renderToStaticMarkup(
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
);
const helmet = Helmet.rewind();
res.send(`<!DOCTYPE html>${ReactDOMServer.renderToStaticMarkup(<Html store={store} component={component} manifest={manifest} helmet={helmet} />)}`);
}).catch(error => {
next(error);
});
} else {
res.status(404).send('404');
}
});
store中集成了redux-saga,如果组件中有需要在页面加载前抓取的api数据,rootTask会在服务器端率先完成数据抓取,并传递给Html。前端入口client.js会将数据在store创建的过程中加载。
const preloadedState = window.__PRELOADED_STATE__;
const store = crete(browserHistory, preloadedState);
如何抓取api数据
创建相对应的Action
export const DATA_FETCH = createRequestAction(Types.DATA_FETCH);
当Request Action触发后,通过redux-saga来处理action, redux-saga 是一个用于管理 Redux 应用异步操作, 更多内容,请阅读Redux-Saga
当数据抓取完成后, redux-saga会通知reducer来处理state的变化
function* dataFetchSaga() {
while (true) {
const { payload } = yield take(`${Types.DATA_FETCH}_REQUEST`);
const { res, error } = yield call(api.get, '/discover/movie', payload);
if (res) {
yield put(dataFetch.receive({ res }));
} else {
yield put(dataFetch.failure(error));
}
}
};
css样式加载
无论是npm run dev或是npm run build都会建立一个manifest文件, 记录了js和css文件中,服务器端会通过该文件来导入js和css。支持css和scss, scss文件中的样式会添加hash后缀避免重复,localIdentName: [local]___[hash:base64:5]