全部源代码、文档和图片都在 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" ] }