全部源代碼、文檔和圖片都在 github 的倉庫裏,點擊進入倉庫javascript
<div id="root"></div>
或<div id="app"></div>
客戶端渲染的特色前端
服務端渲染的特色java
npm init
初始化項目下載 webpack 的依賴包 npm i webpack webpack-cli -D
node
下載 Babel 的依賴包 npm i @babel/core @babel/preset-env @babel/preset-react babel-loader @babel/plugin-proposal-class-properties -D
react
npm i react react-dom react-router-dom -S
npm i express -S
,咱們採用 express 作後端服務,也能夠採用 koa,hapi,egg 等├── node_modules/ 第三方依賴包 |── build/ 服務端打包後生成的代碼 | └── server.js ├── public/ 客戶端打包後生成的代碼 │ └── client.js ├── src │ ├── client/ 客戶端源代碼 │ ├── components/ React 組件 │ ├── containers/ React 容器組件 │ ├── server/ 服務端源代碼 │ ├── store/ redux | └── routes.js 路由 ├── .babelrc babel 編譯 ├── .gitignore git 忽略文件 ├── package.json ├── webpack.base.js webpack 基礎配置 ├── webpack.client.js webpack 客戶端配置 └── webpack.server.js webpack 服務端配置
// webpack.server.js const path = require('path'); // webpack-node-externals 模塊是爲了避免打包 node 的模塊,好比 path, fs 等。由於咱們的 Node 已經內置了這些模塊,因此沒有必要打包 const WebpackNodeExternals = require('webpack-node-externals'); module.exports = { target: 'node', // 服務端的入口文件,是 src/server/index.js mode: 'development', entry: './src/server/index.js', output: { // 打包後生成的文件的路徑與文件名 filename: 'server.js', path: path.resolve(__dirname, 'build/') }, externals: [nodeExternals()], module: { rules: [ { test: /\.js?$/, // 能夠在這裏經過 option 配置 Babel,也可使用 .babelrc 文件配置 Babel loader: 'babel-loader', exclude: /node_modules/ } ] } };
因此咱們先下載兩個全局的包,npm-run-all 和 nodemonwebpack
npm i npm-run-all -g
,這個工具能夠在一個 Terminal 裏同時啓動多個服務,便於咱們開發npm i nodemon -g
,熱重啓 Node 服務,nodemon 的使用方法和 Node 是同樣的,nodemon 監聽到 build/server.js 文件的變更,就會自動重啓服務命令1 dev:build:server
,這個命令是調用 webpack.server.js 進行打包git
"dev:build:server": "webpack --config webpack.server.js --watch"
--config
參數的意思是指定 webpack.server.js
爲配置文件,若是沒有 --config
參數,那麼 webpack 會默認調用 webpack.config.js
配置文件,若是沒有指定配置文件,也沒有 webpack.config.js
文件,那麼會報錯--watch
參數的意思是開啓監聽,每次修改代碼,都會自動打包命令2 dev:start
,這個命令是使用打包後代碼開啓服務github
"dev:start": "nodemon build/server.js"
dev:build:server
打包後,都會生成新的 build/server.js 文件咱們使用 npm-run-all 再添加一條命令,用來啓動這兩個服務web
"dev": "npm-run-all --parallel dev:**"
dev
命令是使用 npm-run-all
工具開啓多個服務,--parallel
參數的意思是並行開啓服務,dev:**
的意思是 npm-run-all
會啓動 scripts
裏全部的以 dev:
開頭的命令。 dev
只是一個代稱,也可使用其餘的字符{ "dev": "npm-run-all --parallel dev:**", "dev:build:server": "webpack --config webpack.server.js --watch", "dev:start": "nodemon build/server.js" }
{ "name": "react-ssr-docs", "version": "1.0.0", "description": "徹底解讀 react 服務端渲染", "main": "index.js", "scripts": { "dev": "npm-run-all --parallel dev:**", "dev:build:server": "webpack --config webpack.server.js --watch", "dev:start": "nodemon build/server.js" }, "repository": { "type": "git", "url": "git+https://github.com/dawnight/react-ssr-docs.git" }, "keywords": [ "react", "redux", "react-ssr" ], "author": "dawnight", "license": "MIT", "bugs": { "url": "https://github.com/dawnight/react-ssr-docs/issues" }, "homepage": "https://github.com/dawnight/react-ssr-docs#readme", "devDependencies": { "@babel/core": "^7.4.3", "@babel/plugin-proposal-class-properties": "^7.4.0", "@babel/preset-env": "^7.4.3", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.5", "webpack": "^4.30.0", "webpack-cli": "^3.3.1", "webpack-node-externals": "^1.7.2" }, "dependencies": { "express": "^4.16.4", "react": "^16.8.6", "react-dom": "^16.8.6", "react-redux": "^7.0.2", "react-router-dom": "^5.0.0", "redux": "^4.0.1", "redux-logger": "^3.0.6", "redux-thunk": "^2.3.0" } }
{ "presets": [ "@babel/preset-env", "@babel/preset-react" ], "plugins": [ "@babel/plugin-proposal-class-properties" ] }