├── Readme.md ├── my_ssr ├── build │ └── bundle.js ├── package.json ├── public │ ├── favicon.ico │ └── index.js ├── src │ ├── App.js │ ├── Routes.js │ ├── WithStyle.js │ ├── client │ │ ├── index.js │ │ └── request.js │ ├── components │ │ └── Header.js │ ├── containers │ │ ├── Home │ │ │ ├── index.js │ │ │ ├── store │ │ │ │ ├── actions.js │ │ │ │ ├── constants.js │ │ │ │ ├── index.js │ │ │ │ └── reducer.js │ │ │ └── style.css │ │ ├── Login │ │ │ └── index.js │ │ └── NotFound │ │ │ └── index.js │ ├── server │ │ ├── index.js │ │ ├── request.js │ │ └── utils.js │ └── store │ │ └── index.js ├── webpack.base.js ├── webpack.client.js └── webpack.server.js └── node_server ├── app.js ├── package.json └── public └── api └── news.json /Readme.md: -------------------------------------------------------------------------------- 1 | React服务端渲染,使用方式: 2 | 3 | 1、到node_server文件夹下,执行npm install,然后执行node app.js,启动后端接口的服务器(端口为4000,用其他语言实现均可) 4 | 5 | 2、npm install nodemon npm-run-all -g 全局安装nodemon工具和npm-run-all,不然之后的项目命令会无法识别 6 | 7 | 3、到my_ssr文件夹下,执行npm install, 然后执行npm run dev启动项目(命令配置细节请看package.json里面的script内容),打开浏览器通过localhost:3001即可访问。 8 | 9 | 配套技术点详解文章地址: 10 | https://juejin.im/post/5d1fe6be51882579db031a6d 11 | -------------------------------------------------------------------------------- /my_ssr/build/bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = "./src/server/index.js"); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ({ 88 | 89 | /***/ "./node_modules/css-loader/dist/cjs.js?!./src/containers/Home/style.css": 90 | /*!***************************************************************************************!*\ 91 | !*** ./node_modules/css-loader/dist/cjs.js??ref--5-1!./src/containers/Home/style.css ***! 92 | \***************************************************************************************/ 93 | /*! no static exports found */ 94 | /***/ (function(module, exports, __webpack_require__) { 95 | 96 | eval("exports = module.exports = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\")(false);\n// Module\nexports.push([module.i, \"body {\\r\\n background: gray;\\r\\n}\\r\\n\\r\\n\", \"\"]);\n\n\n//# sourceURL=webpack:///./src/containers/Home/style.css?./node_modules/css-loader/dist/cjs.js??ref--5-1"); 97 | 98 | /***/ }), 99 | 100 | /***/ "./node_modules/css-loader/dist/runtime/api.js": 101 | /*!*****************************************************!*\ 102 | !*** ./node_modules/css-loader/dist/runtime/api.js ***! 103 | \*****************************************************/ 104 | /*! no static exports found */ 105 | /***/ (function(module, exports, __webpack_require__) { 106 | 107 | "use strict"; 108 | eval("\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\n// eslint-disable-next-line func-names\nmodule.exports = function (useSourceMap) {\n var list = []; // return the list of modules as css string\n\n list.toString = function toString() {\n return this.map(function (item) {\n var content = cssWithMappingToString(item, useSourceMap);\n\n if (item[2]) {\n return \"@media \".concat(item[2], \"{\").concat(content, \"}\");\n }\n\n return content;\n }).join('');\n }; // import a list of modules into the list\n // eslint-disable-next-line func-names\n\n\n list.i = function (modules, mediaQuery) {\n if (typeof modules === 'string') {\n // eslint-disable-next-line no-param-reassign\n modules = [[null, modules, '']];\n }\n\n var alreadyImportedModules = {};\n\n for (var i = 0; i < this.length; i++) {\n // eslint-disable-next-line prefer-destructuring\n var id = this[i][0];\n\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n\n for (var _i = 0; _i < modules.length; _i++) {\n var item = modules[_i]; // skip already imported module\n // this implementation is not 100% perfect for weird media query combinations\n // when a module is imported multiple times with different media queries.\n // I hope this will never occur (Hey this way we have smaller bundles)\n\n if (item[0] == null || !alreadyImportedModules[item[0]]) {\n if (mediaQuery && !item[2]) {\n item[2] = mediaQuery;\n } else if (mediaQuery) {\n item[2] = \"(\".concat(item[2], \") and (\").concat(mediaQuery, \")\");\n }\n\n list.push(item);\n }\n }\n };\n\n return list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n var content = item[1] || ''; // eslint-disable-next-line prefer-destructuring\n\n var cssMapping = item[3];\n\n if (!cssMapping) {\n return content;\n }\n\n if (useSourceMap && typeof btoa === 'function') {\n var sourceMapping = toComment(cssMapping);\n var sourceURLs = cssMapping.sources.map(function (source) {\n return \"/*# sourceURL=\".concat(cssMapping.sourceRoot).concat(source, \" */\");\n });\n return [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n }\n\n return [content].join('\\n');\n} // Adapted from convert-source-map (MIT)\n\n\nfunction toComment(sourceMap) {\n // eslint-disable-next-line no-undef\n var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n var data = \"sourceMappingURL=data:application/json;charset=utf-8;base64,\".concat(base64);\n return \"/*# \".concat(data, \" */\");\n}\n\n//# sourceURL=webpack:///./node_modules/css-loader/dist/runtime/api.js?"); 109 | 110 | /***/ }), 111 | 112 | /***/ "./node_modules/isomorphic-style-loader/insertCss.js": 113 | /*!***********************************************************!*\ 114 | !*** ./node_modules/isomorphic-style-loader/insertCss.js ***! 115 | \***********************************************************/ 116 | /*! no static exports found */ 117 | /***/ (function(module, exports, __webpack_require__) { 118 | 119 | "use strict"; 120 | eval("/*! Isomorphic Style Loader | MIT License | https://github.com/kriasoft/isomorphic-style-loader */\n\n\n\nvar inserted = {};\n\nfunction b64EncodeUnicode(str) {\n return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {\n return String.fromCharCode(\"0x\" + p1);\n }));\n}\n\nfunction removeCss(ids) {\n ids.forEach(function (id) {\n if (--inserted[id] <= 0) {\n var elem = document.getElementById(id);\n\n if (elem) {\n elem.parentNode.removeChild(elem);\n }\n }\n });\n}\n\nfunction insertCss(styles, _temp) {\n var _ref = _temp === void 0 ? {} : _temp,\n _ref$replace = _ref.replace,\n replace = _ref$replace === void 0 ? false : _ref$replace,\n _ref$prepend = _ref.prepend,\n prepend = _ref$prepend === void 0 ? false : _ref$prepend,\n _ref$prefix = _ref.prefix,\n prefix = _ref$prefix === void 0 ? 's' : _ref$prefix;\n\n var ids = [];\n\n for (var i = 0; i < styles.length; i++) {\n var _styles$i = styles[i],\n moduleId = _styles$i[0],\n css = _styles$i[1],\n media = _styles$i[2],\n sourceMap = _styles$i[3];\n var id = \"\" + prefix + moduleId + \"-\" + i;\n ids.push(id);\n\n if (inserted[id]) {\n if (!replace) {\n inserted[id]++;\n continue;\n }\n }\n\n inserted[id] = 1;\n var elem = document.getElementById(id);\n var create = false;\n\n if (!elem) {\n create = true;\n elem = document.createElement('style');\n elem.setAttribute('type', 'text/css');\n elem.id = id;\n\n if (media) {\n elem.setAttribute('media', media);\n }\n }\n\n var cssText = css;\n\n if (sourceMap && typeof btoa === 'function') {\n cssText += \"\\n/*# sourceMappingURL=data:application/json;base64,\" + b64EncodeUnicode(JSON.stringify(sourceMap)) + \"*/\";\n cssText += \"\\n/*# sourceURL=\" + sourceMap.file + \"?\" + id + \"*/\";\n }\n\n if ('textContent' in elem) {\n elem.textContent = cssText;\n } else {\n elem.styleSheet.cssText = cssText;\n }\n\n if (create) {\n if (prepend) {\n document.head.insertBefore(elem, document.head.childNodes[0]);\n } else {\n document.head.appendChild(elem);\n }\n }\n }\n\n return removeCss.bind(null, ids);\n}\n\nmodule.exports = insertCss;\n//# sourceMappingURL=insertCss.js.map\n\n\n//# sourceURL=webpack:///./node_modules/isomorphic-style-loader/insertCss.js?"); 121 | 122 | /***/ }), 123 | 124 | /***/ "./src/App.js": 125 | /*!********************!*\ 126 | !*** ./src/App.js ***! 127 | \********************/ 128 | /*! exports provided: default */ 129 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 130 | 131 | "use strict"; 132 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _components_Header__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./components/Header */ \"./src/components/Header.js\");\n/* harmony import */ var react_router_config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-router-config */ \"react-router-config\");\n/* harmony import */ var react_router_config__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_router_config__WEBPACK_IMPORTED_MODULE_2__);\n\n\n\n\nvar App = function App(props) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_components_Header__WEBPACK_IMPORTED_MODULE_1__[\"default\"], null), Object(react_router_config__WEBPACK_IMPORTED_MODULE_2__[\"renderRoutes\"])(props.route.routes));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (App);\n\n//# sourceURL=webpack:///./src/App.js?"); 133 | 134 | /***/ }), 135 | 136 | /***/ "./src/Routes.js": 137 | /*!***********************!*\ 138 | !*** ./src/Routes.js ***! 139 | \***********************/ 140 | /*! exports provided: default */ 141 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 142 | 143 | "use strict"; 144 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _containers_Home__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./containers/Home */ \"./src/containers/Home/index.js\");\n/* harmony import */ var _containers_Login__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./containers/Login */ \"./src/containers/Login/index.js\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./App */ \"./src/App.js\");\n/* harmony import */ var _containers_NotFound__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./containers/NotFound */ \"./src/containers/NotFound/index.js\");\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ([{\n component: _App__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n routes: [{\n path: '/',\n component: _containers_Home__WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n exact: true,\n loadData: _containers_Home__WEBPACK_IMPORTED_MODULE_0__[\"default\"].loadData\n }, {\n path: '/login',\n component: _containers_Login__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n exact: true\n }, {\n path: '*',\n component: _containers_NotFound__WEBPACK_IMPORTED_MODULE_3__[\"default\"]\n }]\n}]);\n\n//# sourceURL=webpack:///./src/Routes.js?"); 145 | 146 | /***/ }), 147 | 148 | /***/ "./src/WithStyle.js": 149 | /*!**************************!*\ 150 | !*** ./src/WithStyle.js ***! 151 | \**************************/ 152 | /*! exports provided: default */ 153 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 154 | 155 | "use strict"; 156 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n //函数返回组件\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (function (DecoratedComponent, styles) {\n return (\n /*#__PURE__*/\n function (_Component) {\n _inherits(NewComponent, _Component);\n\n function NewComponent() {\n _classCallCheck(this, NewComponent);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(NewComponent).apply(this, arguments));\n }\n\n _createClass(NewComponent, [{\n key: \"componentWillMount\",\n value: function componentWillMount() {\n if (this.props.staticContext) {\n this.props.staticContext.css.push(styles._getCss());\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(DecoratedComponent, this.props);\n }\n }]);\n\n return NewComponent;\n }(react__WEBPACK_IMPORTED_MODULE_0__[\"Component\"])\n );\n});\n\n//# sourceURL=webpack:///./src/WithStyle.js?"); 157 | 158 | /***/ }), 159 | 160 | /***/ "./src/client/request.js": 161 | /*!*******************************!*\ 162 | !*** ./src/client/request.js ***! 163 | \*******************************/ 164 | /*! exports provided: default */ 165 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 166 | 167 | "use strict"; 168 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! axios */ \"axios\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(axios__WEBPACK_IMPORTED_MODULE_0__);\n\nvar instance = axios__WEBPACK_IMPORTED_MODULE_0___default.a.create({\n baseURL: '/'\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (instance);\n\n//# sourceURL=webpack:///./src/client/request.js?"); 169 | 170 | /***/ }), 171 | 172 | /***/ "./src/components/Header.js": 173 | /*!**********************************!*\ 174 | !*** ./src/components/Header.js ***! 175 | \**********************************/ 176 | /*! exports provided: default */ 177 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 178 | 179 | "use strict"; 180 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"react-router-dom\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_router_dom__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar Header = function Header() {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: '/'\n }, \"\\u9996\\u9875\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: '/login'\n }, \"\\u767B\\u9646\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: '/404'\n }, \"\\u627E\\u4E0D\\u5230\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"br\", null));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Header);\n\n//# sourceURL=webpack:///./src/components/Header.js?"); 181 | 182 | /***/ }), 183 | 184 | /***/ "./src/containers/Home/index.js": 185 | /*!**************************************!*\ 186 | !*** ./src/containers/Home/index.js ***! 187 | \**************************************/ 188 | /*! exports provided: default */ 189 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 190 | 191 | "use strict"; 192 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-redux */ \"react-redux\");\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _store_actions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./store/actions */ \"./src/containers/Home/store/actions.js\");\n/* harmony import */ var react_helmet__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-helmet */ \"react-helmet\");\n/* harmony import */ var react_helmet__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_helmet__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./style.css */ \"./src/containers/Home/style.css\");\n/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_style_css__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _WithStyle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../WithStyle */ \"./src/WithStyle.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n\n\n\n\n\n\n\nvar Home =\n/*#__PURE__*/\nfunction (_Component) {\n _inherits(Home, _Component);\n\n function Home() {\n _classCallCheck(this, Home);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(Home).apply(this, arguments));\n }\n\n _createClass(Home, [{\n key: \"getList\",\n value: function getList() {\n var list = this.props.list;\n return list.map(function (item) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n key: item.id\n }, item.title);\n });\n }\n }, {\n key: \"render\",\n value: function render() {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"Fragment\"], null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_helmet__WEBPACK_IMPORTED_MODULE_3__[\"Helmet\"], null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"title\", null, \"\\u8FD9\\u662F\\u4E09\\u5143\\u7684\\u6280\\u672F\\u535A\\u5BA2\\uFF0C\\u5206\\u4EAB\\u524D\\u7AEF\\u77E5\\u8BC6\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"meta\", {\n name: \"description\",\n content: \"\\u8FD9\\u662F\\u4E09\\u5143\\u7684\\u6280\\u672F\\u535A\\u5BA2\\uFF0C\\u5206\\u4EAB\\u524D\\u7AEF\\u77E5\\u8BC6\"\n })), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"test\"\n }, this.getList()));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n if (!this.props.list.length) {\n this.props.getHomeList();\n }\n }\n }]);\n\n return Home;\n}(react__WEBPACK_IMPORTED_MODULE_0__[\"Component\"]);\n\nvar mapStateToProps = function mapStateToProps(state) {\n return {\n list: state.home.newsList\n };\n};\n\nvar mapDispatchToProps = function mapDispatchToProps(dispatch) {\n return {\n getHomeList: function getHomeList() {\n dispatch(Object(_store_actions__WEBPACK_IMPORTED_MODULE_2__[\"getHomeList\"])());\n }\n };\n};\n\nvar exportHome = Object(react_redux__WEBPACK_IMPORTED_MODULE_1__[\"connect\"])(mapStateToProps, mapDispatchToProps)(Object(_WithStyle__WEBPACK_IMPORTED_MODULE_5__[\"default\"])(Home, _style_css__WEBPACK_IMPORTED_MODULE_4___default.a));\n\nexportHome.loadData = function (store) {\n return store.dispatch(Object(_store_actions__WEBPACK_IMPORTED_MODULE_2__[\"getHomeList\"])());\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (exportHome);\n\n//# sourceURL=webpack:///./src/containers/Home/index.js?"); 193 | 194 | /***/ }), 195 | 196 | /***/ "./src/containers/Home/store/actions.js": 197 | /*!**********************************************!*\ 198 | !*** ./src/containers/Home/store/actions.js ***! 199 | \**********************************************/ 200 | /*! exports provided: getHomeList */ 201 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 202 | 203 | "use strict"; 204 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getHomeList\", function() { return getHomeList; });\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ \"./src/containers/Home/store/constants.js\");\n\n\nvar changeList = function changeList(list) {\n return {\n type: _constants__WEBPACK_IMPORTED_MODULE_0__[\"CHANGE_LIST\"],\n list: list\n };\n};\n\nvar getHomeList = function getHomeList(server) {\n return function (dispatch, getState, axiosInstance) {\n return axiosInstance.get('/api/news.json').then(function (res) {\n var list = res.data.data;\n dispatch(changeList(list));\n });\n };\n};\n\n//# sourceURL=webpack:///./src/containers/Home/store/actions.js?"); 205 | 206 | /***/ }), 207 | 208 | /***/ "./src/containers/Home/store/constants.js": 209 | /*!************************************************!*\ 210 | !*** ./src/containers/Home/store/constants.js ***! 211 | \************************************************/ 212 | /*! exports provided: CHANGE_LIST */ 213 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 214 | 215 | "use strict"; 216 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CHANGE_LIST\", function() { return CHANGE_LIST; });\nvar CHANGE_LIST = 'HOME/CHANGE_LIST';\n\n//# sourceURL=webpack:///./src/containers/Home/store/constants.js?"); 217 | 218 | /***/ }), 219 | 220 | /***/ "./src/containers/Home/store/index.js": 221 | /*!********************************************!*\ 222 | !*** ./src/containers/Home/store/index.js ***! 223 | \********************************************/ 224 | /*! exports provided: reducer */ 225 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 226 | 227 | "use strict"; 228 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _reducer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./reducer */ \"./src/containers/Home/store/reducer.js\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"reducer\", function() { return _reducer__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; });\n\n\n\n\n//# sourceURL=webpack:///./src/containers/Home/store/index.js?"); 229 | 230 | /***/ }), 231 | 232 | /***/ "./src/containers/Home/store/reducer.js": 233 | /*!**********************************************!*\ 234 | !*** ./src/containers/Home/store/reducer.js ***! 235 | \**********************************************/ 236 | /*! exports provided: default */ 237 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 238 | 239 | "use strict"; 240 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./constants */ \"./src/containers/Home/store/constants.js\");\nfunction _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n\nvar defaultState = {\n name: 'sanyuan',\n newsList: []\n};\n/* harmony default export */ __webpack_exports__[\"default\"] = (function () {\n var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultState;\n var action = arguments.length > 1 ? arguments[1] : undefined;\n\n switch (action.type) {\n case _constants__WEBPACK_IMPORTED_MODULE_0__[\"CHANGE_LIST\"]:\n var newState = _objectSpread({}, state, {\n newsList: action.list\n });\n\n return newState;\n\n default:\n return state;\n }\n});\n\n//# sourceURL=webpack:///./src/containers/Home/store/reducer.js?"); 241 | 242 | /***/ }), 243 | 244 | /***/ "./src/containers/Home/style.css": 245 | /*!***************************************!*\ 246 | !*** ./src/containers/Home/style.css ***! 247 | \***************************************/ 248 | /*! no static exports found */ 249 | /***/ (function(module, exports, __webpack_require__) { 250 | 251 | eval("\n var refs = 0;\n var css = __webpack_require__(/*! !../../../node_modules/css-loader/dist/cjs.js??ref--5-1!./style.css */ \"./node_modules/css-loader/dist/cjs.js?!./src/containers/Home/style.css\");\n var insertCss = __webpack_require__(/*! ../../../node_modules/isomorphic-style-loader/insertCss.js */ \"./node_modules/isomorphic-style-loader/insertCss.js\");\n var content = typeof css === 'string' ? [[module.i, css, '']] : css;\n\n exports = module.exports = css.locals || {};\n exports._getContent = function() { return content; };\n exports._getCss = function() { return '' + css; };\n exports._insertCss = function(options) { return insertCss(content, options) };\n\n // Hot Module Replacement\n // https://webpack.github.io/docs/hot-module-replacement\n // Only activated in browser context\n if (false) { var removeCss; }\n \n\n//# sourceURL=webpack:///./src/containers/Home/style.css?"); 252 | 253 | /***/ }), 254 | 255 | /***/ "./src/containers/Login/index.js": 256 | /*!***************************************!*\ 257 | !*** ./src/containers/Login/index.js ***! 258 | \***************************************/ 259 | /*! exports provided: default */ 260 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 261 | 262 | "use strict"; 263 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_helmet__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-helmet */ \"react-helmet\");\n/* harmony import */ var react_helmet__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_helmet__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nvar Login = function Login(props) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_helmet__WEBPACK_IMPORTED_MODULE_1__[\"Helmet\"], null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"title\", null, \"\\u8FD9\\u662F\\u4E09\\u5143\\u7684\\u535A\\u5BA2\\uFF0C\\u65E5\\u5E38\\u5206\\u4EAB\\u524D\\u7AEF\\u6280\\u672F\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"meta\", {\n name: \"description\",\n content: \"\\u8FD9\\u662F\\u4E09\\u5143\\u7684\\u535A\\u5BA2\\uFF0C\\u4E30\\u5BCC\\u591A\\u5F69\\u7684\\u5E72\\u8D27\"\n })), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, \"Login\"));\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Login);\n\n//# sourceURL=webpack:///./src/containers/Login/index.js?"); 264 | 265 | /***/ }), 266 | 267 | /***/ "./src/containers/NotFound/index.js": 268 | /*!******************************************!*\ 269 | !*** ./src/containers/NotFound/index.js ***! 270 | \******************************************/ 271 | /*! exports provided: default */ 272 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 273 | 274 | "use strict"; 275 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n\n\nvar Notound =\n/*#__PURE__*/\nfunction (_Component) {\n _inherits(Notound, _Component);\n\n function Notound() {\n _classCallCheck(this, Notound);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(Notound).apply(this, arguments));\n }\n\n _createClass(Notound, [{\n key: \"componentWillMount\",\n value: function componentWillMount() {\n var staticContext = this.props.staticContext;\n staticContext && (staticContext.NotFound = true);\n }\n }, {\n key: \"render\",\n value: function render() {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, \"404\"));\n }\n }]);\n\n return Notound;\n}(react__WEBPACK_IMPORTED_MODULE_0__[\"Component\"]);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Notound);\n\n//# sourceURL=webpack:///./src/containers/NotFound/index.js?"); 276 | 277 | /***/ }), 278 | 279 | /***/ "./src/server/index.js": 280 | /*!*****************************!*\ 281 | !*** ./src/server/index.js ***! 282 | \*****************************/ 283 | /*! no exports provided */ 284 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 285 | 286 | "use strict"; 287 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var express__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! express */ \"express\");\n/* harmony import */ var express__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(express__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils */ \"./src/server/utils.js\");\n/* harmony import */ var react_router_config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-router-config */ \"react-router-config\");\n/* harmony import */ var react_router_config__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_router_config__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _store__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../store */ \"./src/store/index.js\");\n/* harmony import */ var _Routes__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Routes */ \"./src/Routes.js\");\n/* harmony import */ var express_http_proxy__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! express-http-proxy */ \"express-http-proxy\");\n/* harmony import */ var express_http_proxy__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(express_http_proxy__WEBPACK_IMPORTED_MODULE_5__);\n\n\n\n\n\n\nvar app = express__WEBPACK_IMPORTED_MODULE_0___default()();\napp.use(express__WEBPACK_IMPORTED_MODULE_0___default.a.static('public'));\napp.use('/api', express_http_proxy__WEBPACK_IMPORTED_MODULE_5___default()('http://localhost:4000', {\n proxyReqPathResolver: function proxyReqPathResolver(req) {\n return '/api' + req.url;\n }\n}));\napp.get('*', function (req, res) {\n var store = Object(_store__WEBPACK_IMPORTED_MODULE_3__[\"getStore\"])(); // 根据路由的路径,来往store里面加数据\n\n var matchedRoutes = Object(react_router_config__WEBPACK_IMPORTED_MODULE_2__[\"matchRoutes\"])(_Routes__WEBPACK_IMPORTED_MODULE_4__[\"default\"], req.path);\n var promises = [];\n matchedRoutes.forEach(function (item) {\n if (item.route.loadData) {\n var promise = new Promise(function (resolve, reject) {\n item.route.loadData(store).then(resolve).catch(resolve);\n });\n promises.push(promise);\n }\n\n ;\n });\n Promise.all(promises).then(function () {\n var context = {\n css: []\n };\n var html = Object(_utils__WEBPACK_IMPORTED_MODULE_1__[\"render\"])(store, _Routes__WEBPACK_IMPORTED_MODULE_4__[\"default\"], req, context);\n\n if (context.action === 'REPLACE') {\n res.redirect(301, context.url);\n } else if (context.NotFound) {\n res.status(404);\n res.send(html);\n } else {\n res.send(html);\n }\n });\n});\nvar server = app.listen(3001, function () {\n var host = server.address().address;\n var port = server.address().port;\n console.log(\"应用实例,访问地址为 http://%s:%s\", host, port);\n});\n\n//# sourceURL=webpack:///./src/server/index.js?"); 288 | 289 | /***/ }), 290 | 291 | /***/ "./src/server/request.js": 292 | /*!*******************************!*\ 293 | !*** ./src/server/request.js ***! 294 | \*******************************/ 295 | /*! exports provided: default */ 296 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 297 | 298 | "use strict"; 299 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! axios */ \"axios\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(axios__WEBPACK_IMPORTED_MODULE_0__);\n\nvar instance = axios__WEBPACK_IMPORTED_MODULE_0___default.a.create({\n baseURL: 'http://localhost:4000'\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (instance);\n\n//# sourceURL=webpack:///./src/server/request.js?"); 300 | 301 | /***/ }), 302 | 303 | /***/ "./src/server/utils.js": 304 | /*!*****************************!*\ 305 | !*** ./src/server/utils.js ***! 306 | \*****************************/ 307 | /*! exports provided: render */ 308 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 309 | 310 | "use strict"; 311 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony import */ var react_dom_server__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react-dom/server */ \"react-dom/server\");\n/* harmony import */ var react_dom_server__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_dom_server__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"react-router-dom\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_router_dom__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-redux */ \"react-redux\");\n/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var react_router_config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-config */ \"react-router-config\");\n/* harmony import */ var react_router_config__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_router_config__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var react_helmet__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react-helmet */ \"react-helmet\");\n/* harmony import */ var react_helmet__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(react_helmet__WEBPACK_IMPORTED_MODULE_5__);\n\n\n\n\n\n\nvar render = function render(store, routes, req, context) {\n var content = Object(react_dom_server__WEBPACK_IMPORTED_MODULE_0__[\"renderToString\"])(react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(react_redux__WEBPACK_IMPORTED_MODULE_3__[\"Provider\"], {\n store: store\n }, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"StaticRouter\"], {\n location: req.path,\n context: context\n }, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(\"div\", null, Object(react_router_config__WEBPACK_IMPORTED_MODULE_4__[\"renderRoutes\"])(routes)))));\n var helmet = react_helmet__WEBPACK_IMPORTED_MODULE_5__[\"Helmet\"].renderStatic();\n var cssStr = context.css.length ? context.css.join('\\n') : '';\n return \"\\n \\n \\n \\n \").concat(helmet.title.toString(), \"\\n \").concat(helmet.meta.toString(), \"\\n \\n \\n
\").concat(content, \"
\\n \\n \\n \\n \\n \");\n};\n\n//# sourceURL=webpack:///./src/server/utils.js?"); 312 | 313 | /***/ }), 314 | 315 | /***/ "./src/store/index.js": 316 | /*!****************************!*\ 317 | !*** ./src/store/index.js ***! 318 | \****************************/ 319 | /*! exports provided: getStore, getClientStore */ 320 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 321 | 322 | "use strict"; 323 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getStore\", function() { return getStore; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getClientStore\", function() { return getClientStore; });\n/* harmony import */ var redux__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! redux */ \"redux\");\n/* harmony import */ var redux__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(redux__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var redux_thunk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! redux-thunk */ \"redux-thunk\");\n/* harmony import */ var redux_thunk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(redux_thunk__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _containers_Home_store__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../containers/Home/store */ \"./src/containers/Home/store/index.js\");\n/* harmony import */ var _client_request__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../client/request */ \"./src/client/request.js\");\n/* harmony import */ var _server_request__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../server/request */ \"./src/server/request.js\");\n\n\n\n\n\nvar reducer = Object(redux__WEBPACK_IMPORTED_MODULE_0__[\"combineReducers\"])({\n home: _containers_Home_store__WEBPACK_IMPORTED_MODULE_2__[\"reducer\"]\n});\nvar getStore = function getStore() {\n return Object(redux__WEBPACK_IMPORTED_MODULE_0__[\"createStore\"])(reducer, Object(redux__WEBPACK_IMPORTED_MODULE_0__[\"applyMiddleware\"])(redux_thunk__WEBPACK_IMPORTED_MODULE_1___default.a.withExtraArgument(_server_request__WEBPACK_IMPORTED_MODULE_4__[\"default\"])));\n};\nvar getClientStore = function getClientStore() {\n var defaultState = window.context ? window.context.state : {};\n return Object(redux__WEBPACK_IMPORTED_MODULE_0__[\"createStore\"])(reducer, defaultState, Object(redux__WEBPACK_IMPORTED_MODULE_0__[\"applyMiddleware\"])(redux_thunk__WEBPACK_IMPORTED_MODULE_1___default.a.withExtraArgument(_client_request__WEBPACK_IMPORTED_MODULE_3__[\"default\"])));\n};\n\n//# sourceURL=webpack:///./src/store/index.js?"); 324 | 325 | /***/ }), 326 | 327 | /***/ "axios": 328 | /*!************************!*\ 329 | !*** external "axios" ***! 330 | \************************/ 331 | /*! no static exports found */ 332 | /***/ (function(module, exports) { 333 | 334 | eval("module.exports = require(\"axios\");\n\n//# sourceURL=webpack:///external_%22axios%22?"); 335 | 336 | /***/ }), 337 | 338 | /***/ "express": 339 | /*!**************************!*\ 340 | !*** external "express" ***! 341 | \**************************/ 342 | /*! no static exports found */ 343 | /***/ (function(module, exports) { 344 | 345 | eval("module.exports = require(\"express\");\n\n//# sourceURL=webpack:///external_%22express%22?"); 346 | 347 | /***/ }), 348 | 349 | /***/ "express-http-proxy": 350 | /*!*************************************!*\ 351 | !*** external "express-http-proxy" ***! 352 | \*************************************/ 353 | /*! no static exports found */ 354 | /***/ (function(module, exports) { 355 | 356 | eval("module.exports = require(\"express-http-proxy\");\n\n//# sourceURL=webpack:///external_%22express-http-proxy%22?"); 357 | 358 | /***/ }), 359 | 360 | /***/ "react": 361 | /*!************************!*\ 362 | !*** external "react" ***! 363 | \************************/ 364 | /*! no static exports found */ 365 | /***/ (function(module, exports) { 366 | 367 | eval("module.exports = require(\"react\");\n\n//# sourceURL=webpack:///external_%22react%22?"); 368 | 369 | /***/ }), 370 | 371 | /***/ "react-dom/server": 372 | /*!***********************************!*\ 373 | !*** external "react-dom/server" ***! 374 | \***********************************/ 375 | /*! no static exports found */ 376 | /***/ (function(module, exports) { 377 | 378 | eval("module.exports = require(\"react-dom/server\");\n\n//# sourceURL=webpack:///external_%22react-dom/server%22?"); 379 | 380 | /***/ }), 381 | 382 | /***/ "react-helmet": 383 | /*!*******************************!*\ 384 | !*** external "react-helmet" ***! 385 | \*******************************/ 386 | /*! no static exports found */ 387 | /***/ (function(module, exports) { 388 | 389 | eval("module.exports = require(\"react-helmet\");\n\n//# sourceURL=webpack:///external_%22react-helmet%22?"); 390 | 391 | /***/ }), 392 | 393 | /***/ "react-redux": 394 | /*!******************************!*\ 395 | !*** external "react-redux" ***! 396 | \******************************/ 397 | /*! no static exports found */ 398 | /***/ (function(module, exports) { 399 | 400 | eval("module.exports = require(\"react-redux\");\n\n//# sourceURL=webpack:///external_%22react-redux%22?"); 401 | 402 | /***/ }), 403 | 404 | /***/ "react-router-config": 405 | /*!**************************************!*\ 406 | !*** external "react-router-config" ***! 407 | \**************************************/ 408 | /*! no static exports found */ 409 | /***/ (function(module, exports) { 410 | 411 | eval("module.exports = require(\"react-router-config\");\n\n//# sourceURL=webpack:///external_%22react-router-config%22?"); 412 | 413 | /***/ }), 414 | 415 | /***/ "react-router-dom": 416 | /*!***********************************!*\ 417 | !*** external "react-router-dom" ***! 418 | \***********************************/ 419 | /*! no static exports found */ 420 | /***/ (function(module, exports) { 421 | 422 | eval("module.exports = require(\"react-router-dom\");\n\n//# sourceURL=webpack:///external_%22react-router-dom%22?"); 423 | 424 | /***/ }), 425 | 426 | /***/ "redux": 427 | /*!************************!*\ 428 | !*** external "redux" ***! 429 | \************************/ 430 | /*! no static exports found */ 431 | /***/ (function(module, exports) { 432 | 433 | eval("module.exports = require(\"redux\");\n\n//# sourceURL=webpack:///external_%22redux%22?"); 434 | 435 | /***/ }), 436 | 437 | /***/ "redux-thunk": 438 | /*!******************************!*\ 439 | !*** external "redux-thunk" ***! 440 | \******************************/ 441 | /*! no static exports found */ 442 | /***/ (function(module, exports) { 443 | 444 | eval("module.exports = require(\"redux-thunk\");\n\n//# sourceURL=webpack:///external_%22redux-thunk%22?"); 445 | 446 | /***/ }) 447 | 448 | /******/ }); -------------------------------------------------------------------------------- /my_ssr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "dependencies": { 7 | "@babel/core": "^7.4.5", 8 | "@babel/preset-env": "^7.4.5", 9 | "@babel/preset-react": "^7.0.0", 10 | "@babel/preset-stage-0": "^7.0.0", 11 | "axios": "^0.19.0", 12 | "babel-loader": "^8.0.6", 13 | "css-loader": "^3.0.0", 14 | "express": "^4.17.1", 15 | "express-http-proxy": "^1.5.1", 16 | "prerender": "^5.6.0", 17 | "react": "^16.8.6", 18 | "react-dom": "^16.8.6", 19 | "react-helmet": "^5.2.1", 20 | "react-redux": "^7.1.0", 21 | "react-router-config": "^5.0.1", 22 | "react-router-dom": "^5.0.1", 23 | "redux": "^4.0.1", 24 | "redux-thunk": "^2.3.0", 25 | "style-loader": "^0.23.1", 26 | "webpack": "^4.35.2", 27 | "webpack-cli": "^3.3.5", 28 | "webpack-merge": "^4.2.1", 29 | "webpack-node-externals": "^1.7.2" 30 | }, 31 | "devDependencies": { 32 | "isomorphic-style-loader": "^5.1.0" 33 | }, 34 | "scripts": { 35 | "dev": "npm-run-all --parallel dev:**", 36 | "dev:build:server": "webpack --config webpack.server.js --watch", 37 | "dev:build:client": "webpack --config webpack.client.js --watch", 38 | "dev:start": "nodemon --watch build --exec node \"./build/bundle.js\"" 39 | }, 40 | "author": "", 41 | "license": "ISC" 42 | } 43 | -------------------------------------------------------------------------------- /my_ssr/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanyuan0704/react-ssr/77fd30986a01c1802f6b1921c5ea1e47e84c162b/my_ssr/public/favicon.ico -------------------------------------------------------------------------------- /my_ssr/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './components/Header'; 3 | import { renderRoutes } from 'react-router-config'; 4 | 5 | const App = (props) => { 6 | return ( 7 |
8 |
9 | {renderRoutes(props.route.routes)} 10 |
11 | ) 12 | }; 13 | 14 | export default App; -------------------------------------------------------------------------------- /my_ssr/src/Routes.js: -------------------------------------------------------------------------------- 1 | import Home from './containers/Home'; 2 | import Login from './containers/Login'; 3 | import App from './App'; 4 | import NotFound from './containers/NotFound'; 5 | 6 | export default [{ 7 | component: App, 8 | routes: [ 9 | { 10 | path: '/', 11 | component: Home, 12 | exact: true, 13 | loadData: Home.loadData, 14 | }, 15 | { 16 | path: '/login', 17 | component: Login, 18 | exact: true, 19 | }, 20 | { 21 | path: '*', 22 | component: NotFound, 23 | } 24 | ] 25 | }]; 26 | 27 | 28 | -------------------------------------------------------------------------------- /my_ssr/src/WithStyle.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | //函数返回组件 3 | export default (DecoratedComponent, styles) => { 4 | return class NewComponent extends Component { 5 | componentWillMount() { 6 | if (this.props.staticContext) { 7 | this.props.staticContext.css.push(styles._getCss()); 8 | } 9 | } 10 | render() { 11 | return 12 | } 13 | }; 14 | } -------------------------------------------------------------------------------- /my_ssr/src/client/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDom from 'react-dom'; 3 | import {BrowserRouter, Route} from 'react-router-dom'; 4 | import routes from '../Routes'; 5 | import { renderRoutes } from 'react-router-config'; 6 | import { Provider } from 'react-redux'; 7 | import { getClientStore } from '../store'; 8 | 9 | const App = () => { 10 | return ( 11 | 12 | 13 |
14 | {renderRoutes(routes)} 15 |
16 |
17 |
18 | ) 19 | }; 20 | 21 | ReactDom.hydrate(, document.getElementById('root')); 22 | -------------------------------------------------------------------------------- /my_ssr/src/client/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const instance = axios.create({ 4 | baseURL: '/' 5 | }); 6 | 7 | export default instance; -------------------------------------------------------------------------------- /my_ssr/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | 4 | const Header = () => { 5 | return ( 6 |
7 | 首页
8 | 登陆
9 | 找不到
10 |
11 | ) 12 | } 13 | 14 | export default Header; -------------------------------------------------------------------------------- /my_ssr/src/containers/Home/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { getHomeList } from './store/actions'; 4 | import { Helmet } from 'react-helmet'; 5 | import styles from './style.css'; 6 | import WithStyle from '../../WithStyle'; 7 | 8 | class Home extends Component { 9 | getList() { 10 | const { list } = this.props 11 | return list.map(item =>
{item.title}
) 12 | } 13 | render() { 14 | return ( 15 | 16 | 17 | 这是三元的技术博客,分享前端知识 18 | 19 | 20 |
21 | { 22 | this.getList() 23 | } 24 |
25 |
26 | 27 | ) 28 | } 29 | componentDidMount() { 30 | if (!this.props.list.length) { 31 | this.props.getHomeList() 32 | } 33 | } 34 | } 35 | 36 | const mapStateToProps = state => ({ 37 | list: state.home.newsList, 38 | }); 39 | const mapDispatchToProps = dispatch => ({ 40 | getHomeList() { 41 | dispatch(getHomeList()) 42 | } 43 | }); 44 | const exportHome = connect(mapStateToProps, mapDispatchToProps)(WithStyle(Home, styles)); 45 | 46 | exportHome.loadData = (store) => { 47 | return store.dispatch(getHomeList()) 48 | }; 49 | export default exportHome; -------------------------------------------------------------------------------- /my_ssr/src/containers/Home/store/actions.js: -------------------------------------------------------------------------------- 1 | import { CHANGE_LIST } from "./constants"; 2 | 3 | const changeList = list => ({ 4 | type: CHANGE_LIST, 5 | list 6 | }); 7 | 8 | export const getHomeList = (server) => { 9 | return (dispatch, getState, axiosInstance) => { 10 | return axiosInstance.get('/api/news.json') 11 | .then((res) => { 12 | const list = res.data.data 13 | dispatch(changeList(list)) 14 | }); 15 | }; 16 | }; -------------------------------------------------------------------------------- /my_ssr/src/containers/Home/store/constants.js: -------------------------------------------------------------------------------- 1 | export const CHANGE_LIST = 'HOME/CHANGE_LIST'; -------------------------------------------------------------------------------- /my_ssr/src/containers/Home/store/index.js: -------------------------------------------------------------------------------- 1 | import reducer from "./reducer"; 2 | 3 | export {reducer}; -------------------------------------------------------------------------------- /my_ssr/src/containers/Home/store/reducer.js: -------------------------------------------------------------------------------- 1 | import { CHANGE_LIST } from "./constants"; 2 | 3 | const defaultState = { 4 | name: 'sanyuan', 5 | newsList: [] 6 | }; 7 | 8 | export default (state = defaultState, action) => { 9 | switch(action.type) { 10 | case CHANGE_LIST: 11 | const newState = { 12 | ...state, 13 | newsList: action.list 14 | }; 15 | return newState; 16 | default: 17 | return state; 18 | } 19 | } -------------------------------------------------------------------------------- /my_ssr/src/containers/Home/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: gray; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /my_ssr/src/containers/Login/index.js: -------------------------------------------------------------------------------- 1 | import React, {Fregment} from 'react'; 2 | import { Helmet } from 'react-helmet'; 3 | 4 | const Login = (props) => { 5 | return ( 6 |
7 | 8 | 这是三元的博客,日常分享前端技术 9 | 10 | 11 |
Login
12 |
13 | ) 14 | }; 15 | 16 | export default Login; -------------------------------------------------------------------------------- /my_ssr/src/containers/NotFound/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | class Notound extends Component { 4 | componentWillMount() { 5 | const { staticContext } = this.props; 6 | staticContext && (staticContext.NotFound = true) 7 | } 8 | 9 | render() { 10 | return ( 11 |
12 |
404
13 |
14 | ); 15 | } 16 | } 17 | 18 | export default Notound; -------------------------------------------------------------------------------- /my_ssr/src/server/index.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import {render} from './utils'; 3 | import { matchRoutes } from 'react-router-config'; 4 | import { getStore } from '../store'; 5 | import routes from '../Routes'; 6 | import proxy from 'express-http-proxy'; 7 | 8 | const app = express(); 9 | app.use(express.static('public')); 10 | 11 | app.use('/api', proxy('http://localhost:4000', { 12 | proxyReqPathResolver: function(req) { 13 | return '/api'+req.url 14 | } 15 | })); 16 | 17 | app.get('*', function (req, res) { 18 | const store = getStore(); 19 | // 根据路由的路径,来往store里面加数据 20 | const matchedRoutes = matchRoutes(routes, req.path); 21 | const promises = []; 22 | matchedRoutes.forEach(item => { 23 | if (item.route.loadData) { 24 | const promise = new Promise((resolve, reject) => { 25 | item.route.loadData(store).then(resolve).catch(resolve); 26 | }) 27 | promises.push(promise); 28 | }; 29 | }); 30 | Promise.all(promises).then(() => { 31 | let context = {css: []}; 32 | const html = render(store, routes, req, context); 33 | 34 | if(context.action === 'REPLACE') { 35 | res.redirect(301, context.url); 36 | } else if(context.NotFound) { 37 | res.status(404); 38 | res.send(html); 39 | } else { 40 | res.send(html); 41 | } 42 | }) 43 | }) 44 | 45 | var server = app.listen(3001, function () { 46 | var host = server.address().address; 47 | var port = server.address().port; 48 | console.log("应用实例,访问地址为 http://%s:%s", host, port); 49 | }) -------------------------------------------------------------------------------- /my_ssr/src/server/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const instance = axios.create({ 4 | baseURL: 'http://localhost:4000' 5 | }) 6 | 7 | export default instance; -------------------------------------------------------------------------------- /my_ssr/src/server/utils.js: -------------------------------------------------------------------------------- 1 | import { renderToString } from 'react-dom/server'; 2 | import { StaticRouter } from 'react-router-dom'; 3 | import React from 'react' 4 | import { Provider } from "react-redux"; 5 | import { renderRoutes } from 'react-router-config'; 6 | import { Helmet } from 'react-helmet'; 7 | 8 | export const render = (store, routes, req, context) => { 9 | const content = renderToString( 10 | 11 | 12 |
13 | {renderRoutes(routes)} 14 |
15 |
16 |
17 | ); 18 | const helmet = Helmet.renderStatic(); 19 | 20 | const cssStr = context.css.length ? context.css.join('\n') : ''; 21 | 22 | return ` 23 | 24 | 25 | 26 | ${helmet.title.toString()} 27 | ${helmet.meta.toString()} 28 | 29 | 30 |
${content}
31 | 36 | 37 | 38 | 39 | ` 40 | }; -------------------------------------------------------------------------------- /my_ssr/src/store/index.js: -------------------------------------------------------------------------------- 1 | import {createStore, applyMiddleware, combineReducers} from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import { reducer as homeReducer } from '../containers/Home/store'; 4 | import clientAxios from '../client/request'; 5 | import serverAxios from '../server/request'; 6 | 7 | const reducer = combineReducers({ 8 | home: homeReducer 9 | }); 10 | 11 | export const getStore = () => { 12 | return createStore(reducer, applyMiddleware(thunk.withExtraArgument(serverAxios))); 13 | } 14 | export const getClientStore = () => { 15 | const defaultState = window.context ? window.context.state : {}; 16 | return createStore(reducer, defaultState, applyMiddleware(thunk.withExtraArgument(clientAxios))); 17 | } 18 | -------------------------------------------------------------------------------- /my_ssr/webpack.base.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | module: { 3 | rules: [{ 4 | test: /\.js$/, 5 | loader: 'babel-loader', 6 | exclude: /node_modules/, 7 | options: { 8 | presets: ['@babel/preset-react', ['@babel/preset-env', { 9 | targets: { 10 | browsers: ['last 2 versions'] 11 | } 12 | }]] 13 | } 14 | }] 15 | } 16 | } -------------------------------------------------------------------------------- /my_ssr/webpack.client.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const merge = require('webpack-merge') 3 | const config = require('./webpack.base') 4 | 5 | const clientConfig = { 6 | mode: 'development', 7 | entry: './src/client/index.js', 8 | module: { 9 | rules: [{ 10 | test: /\.css?$/, 11 | use: ['style-loader', { 12 | loader: 'css-loader', 13 | options: { 14 | modules: true 15 | } 16 | }] 17 | }] 18 | }, 19 | output: { 20 | filename: 'index.js', 21 | path: path.resolve(__dirname, 'public') 22 | }, 23 | } 24 | 25 | module.exports = merge(config, clientConfig) -------------------------------------------------------------------------------- /my_ssr/webpack.server.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const nodeExternals = require('webpack-node-externals') 3 | const merge = require('webpack-merge') 4 | const config = require('./webpack.base') 5 | 6 | const serverConfig = { 7 | target: 'node', 8 | mode: 'development', 9 | entry: './src/server/index.js', 10 | externals: [nodeExternals()], 11 | module: { 12 | rules: [{ 13 | test: /\.css?$/, 14 | use: ['isomorphic-style-loader', { 15 | loader: 'css-loader', 16 | options: { 17 | modules: true 18 | } 19 | }] 20 | }] 21 | }, 22 | output: { 23 | filename: 'bundle.js', 24 | path: path.resolve(__dirname, 'build') 25 | } 26 | } 27 | 28 | module.exports = merge(config, serverConfig) -------------------------------------------------------------------------------- /node_server/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express") 2 | const app = express() 3 | 4 | app.use(express.static('public')) 5 | 6 | app.listen(4000, () => {console.log('running 4000')}) -------------------------------------------------------------------------------- /node_server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node_server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "express": "^4.17.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /node_server/public/api/news.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": 1, 5 | "title": "1111111" 6 | }, 7 | { 8 | "id": 2, 9 | "title": "2222222" 10 | }, 11 | { 12 | "id": 3, 13 | "title": "3333333" 14 | }, 15 | { 16 | "id": 4, 17 | "title": "4444444" 18 | }, 19 | { 20 | "id": 5, 21 | "title": "5555555" 22 | } 23 | ] 24 | } --------------------------------------------------------------------------------