{"id":16193909,"url":"https://github.com/wwwy3y3/coren-example","last_synced_at":"2025-04-07T15:30:28.323Z","repository":{"id":142360313,"uuid":"93545821","full_name":"wwwy3y3/coren-example","owner":"wwwy3y3","description":"coren example","archived":false,"fork":false,"pushed_at":"2018-03-03T14:35:18.000Z","size":164,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-13T18:17:13.238Z","etag":null,"topics":["coren","react","react-server-render","redux"],"latest_commit_sha":null,"homepage":"","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wwwy3y3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2017-06-06T17:34:05.000Z","updated_at":"2019-10-22T06:26:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"940d63db-6daa-41d8-99c0-1b28ff648a15","html_url":"https://github.com/wwwy3y3/coren-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwy3y3%2Fcoren-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwy3y3%2Fcoren-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwy3y3%2Fcoren-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wwwy3y3%2Fcoren-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wwwy3y3","download_url":"https://codeload.github.com/wwwy3y3/coren-example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247679072,"owners_count":20977995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["coren","react","react-server-render","redux"],"created_at":"2024-10-10T08:17:02.536Z","updated_at":"2025-04-07T15:30:28.285Z","avatar_url":"https://github.com/wwwy3y3.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Coren-example\nThis example repo shows how to serverside render React Single Page App with `coren`\n\n[Demo](https://nameless-taiga-65782.herokuapp.com)\n\n# Usage\n\n```sh\n$ git clone git@github.com:Canner/coren-example.git\n$ yarn\n```\n\n## development\n\ntest in development mode, with hot-reload\n\n```sh\n$ npm run webpack-server\n$ node app.js\n$ open http://localhost:9393\nview source to see HTML\n```\n\n## production\n\ntest in production mode, with real ssr result\n\n```sh\n$ npm run coren\n$ npm run webpack-server\n$ COREN_ENV=pre-production node app.js\nview source to see HTML\n```\n\n# Explanation\n\n## modules used\n* react-router v4\n* redux\n* redux-api-middleware\n\n## How this example use Coren\n* use `RoutesCollector` to generate routes need to be rendered\n``` js\n// /src/Home\nstatic defineRoutes({Url}) {\n  return new Url('/');\n}\n```\n\n``` js\n// /src/User\n// server will execute db.users.find().execAsync(), get the data then generate multiple routes with path '/users/:id'\nstatic defineRoutes({ParamUrl, db}) {\n  return new ParamUrl({\n    url: '/users/:id',\n    dataProvider: () =\u003e db.users.find().execAsync()\n  });\n}\n```\n\n``` js\n// /src/UserList\nstatic defineRoutes({Url}) {\n  return new Url('/users');\n}\n```\n\n* use `HeadCollector` to get title, description\n``` js\n// /src/User\nstatic defineHead(props) {\n  const userId = props.match.params.id;\n  return {\n    title: `user ${userId}`,\n    description: `user ${userId}`\n  };\n}\n```\n\n* customized `ImmutableReduxCollector`\nas a best practice in our team, we use immutable state in redux. so we modify some part of ReduxCollector\n``` js\nclass ImmutableReduxCollector extends ReduxCollector {\n  appendToHead($head) {\n    $head.append(`\u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.min.js\"\u003e\u003c/script\u003e`);\n    // wrap state with Immutable, when rendered in HTML\n    $head.append(`\u003cscript\u003e\n      window.__PRELOADED_STATE__ = Immutable.fromJS(${JSON.stringify(this.state ? this.state.toJS() : {})})\n      \u003c/script\u003e`);\n  }\n\n  wrapApp(appElement) {\n    // if initialState collected from components is empty, we pass undefined to store , let store.getState() be the intial state in reducer \n    const store = createStore(this.reducers, isEmpty(this.initialState) ? undefined : immutable.fromJS(this.initialState));\n    const wrapedElements = react.createElement(Provider, {store}, appElement);\n    this.state = store.getState();\n    return wrapedElements;\n  }\n}\n```\n\nin Component, we use `definePreloadedState` return initialState this component need\n``` js\n// /src/UserList\n// 透過 server 傳過來的 db 做出 query\nstatic definePreloadedState({db}) {\n  return db.users.find().execAsync()\n  .then(list =\u003e ({\n    users: {\n      list,\n      fetched: true,\n      isFetching: false,\n      error: false\n    }\n  }));\n}\n```\n\n## dev server\n```\nnode devServer.js\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwwwy3y3%2Fcoren-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwwwy3y3%2Fcoren-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwwwy3y3%2Fcoren-example/lists"}