咱也不知道這會兒寫這個出來算不算過期, 反正就想寫寫. 至於有沒有人看, 看完點不點贊, 點完贊會不會實踐. 咱也不敢問呀, 隨手寫寫吧~html
到了 9102 年, 做爲前端扛把子的 React 依然煊赫一時. 周邊的各類生態更是紅的發燙. 天天應付完各類業務需求真的想舒舒坦坦躺上一波...前端
恰恰又來了互聯網寒冬的夾持, 苦逼的前端 🐶只能把這句不怎麼當講的話埋在心底了~node
這一期, 和你們一同窗習 React + Koa 的服務端渲染知識. 文中難免疏漏, 望大佬斧正. 廢話很少說, 搞起來~react
配置開發環境參考這裏, 因爲我們建立的是 React 項目, 因此按照這篇文章配置到 eslint 就能夠了.webpack
ps: 最新版本的 eslint 更新後和那篇文章命令行步驟有點不同. 可是整體大同小異. 若是不想解決差別的同窗能夠安裝 eslint 5.9.0 這個版本, 保證和文章中一致性~git
以上幾步操做的步驟爲:es6
首先咱們建立一個基礎的 react 項目, 爲了便於理解, 這裏不用 create-react-app
, 而是直接用 webpack 手擼配置. 因此須要你們有一點點的 webpack 基礎知識. 若是實在沒有也不要緊, 我們講~github
開發環境建立完成後咱們看到的項目結構應該添加了 package.json
和 .eslintrc.js
兩個配置文件還有一個 node_modules
目錄. 接下來就是咱們大幹一場的時間啦~web
console.log('hello world')
複製代碼
node index.js
回車
恕我直言, 在座各位都已經晉級爲 node.js
開發工程師了~npm
npm i react react-dom
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div className="ssr-show"> <h1>歡迎來到澳門皇冠賭場</h1> </div>
);
}
}
複製代碼
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
// eslint-disable-next-line
ReactDOM.render(<App />, document.getElementById('app')); 複製代碼
到了這一步, 彷佛是沒有啥問題了, 可是, 這個東西跑不起來呀...
以前的步驟根本沒有 html 做爲依託, 我們的項目更本就是很差使的. 此時的代碼在 這裏 建議你們下載下來嘗試配置下 webpack
配置 webpack 其實灰常簡單, 只須要三步.
根據三步原理建立的 webpack 配置文件以下
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
// 客戶端渲染的入口文件
entry: './src/client.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
// 由於目前咱們的項目裏邊只有 js 和 jsx 文件, 因此只配這一條規則就能夠啦~
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
plugins: [
// 使用 html webpack plugin 建立 html 文件做爲項目產出的依託文件
new HtmlWebPackPlugin({
template: './index.temp.html',
}),
],
};
複製代碼
最後添加 npm script
在 package.json
的 script 字段下添加如下代碼 "build:client": "webpack --mode=production"
最後執行 npm run build:client
結束後用你喜歡的瀏覽器打開 index.html 文件.
進行到這裏的同窗, 恭喜你正在悄悄的超越大家的項目小組長了~ 此時的代碼在這裏
咱們已經能實現客戶端渲染的 React 項目, 走出了萬里長征的第一步. 接下來就是剩下的 9999 步了.
首先, 在 src 目錄下建立 server.js
文件做爲服務端渲染的入口文件. 其次, 編輯該文件內容以下:
import Koa from 'koa';
import Router from 'koa-router';
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './components/App.jsx';
const app = new Koa();
const router = new Router();
const conf = {
PORT: 9999,
};
const generateHtmlStr = reactDom => ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app">${reactDom}</div> </body> </html> `;
router.get('*', (ctx) => {
// 首先把 React 組件變成一個字符串
// eslint-disable-next-line
const rNode = renderToString(<App />); // 而後替換 template 裏邊的內容 const domString = generateHtmlStr(rNode); // 最後返回 html 字符串 ctx.body = domString; }); app.use(router.routes(), router.allowedMethods()); app.listen(conf.PORT, () => { console.log(`The Server is listening on ${conf.PORT} now, enjoy`); }); 複製代碼
代碼和客戶端渲染的入口文件 client.js
文件大同小異
再次, 改寫項目根目錄下的 index.js
文件, 導入並執行一下剛剛建立的 server.js
文件
require('./src/server')
複製代碼
最後, 命令行執行 node index.js
仔細看下報錯信息, 原來是 nodejs 不怎麼認識 es6 的模塊化語法. 給咱們的項目入口文件添加個 babel. 修改項目根目錄下的indes.js
文件以下:
require('@babel/register')({
presets: ['@babel/env', '@babel/react'],
});
require('./src/server');
複製代碼
再執行一下 node index.js
看樣子要成功了~
這個時候瀏覽器打開 localhost:9999
若是你進入了澳門皇冠, 那確定就值得信賴啦~
而後咱們鼠標右鍵 -> 查看網頁源代碼 -> 驗貨
雖然很簡單, 可是貨真價實, 正兒八經的服務端渲染. 此時代碼在 這裏
經過以前的步驟咱們已經學習了使用 koa 實現最最基礎的服務端渲染項目(僅僅用到了一個 renderToString 這個 api), 在下篇文章中咱們會一塊兒學習在項目中加入 react-router
redux
自定義 mata
等功能, 並實現其服務端渲染. 第一次接觸服務端渲染, 但願各路大佬能不吝賜教~