{"id":15207124,"url":"https://github.com/maerzhase/ssr3000","last_synced_at":"2025-10-02T23:35:43.443Z","repository":{"id":57369044,"uuid":"112119537","full_name":"maerzhase/ssr3000","owner":"maerzhase","description":"react server side rendering","archived":true,"fork":false,"pushed_at":"2018-08-12T16:39:24.000Z","size":995,"stargazers_count":2,"open_issues_count":7,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-16T08:15:55.286Z","etag":null,"topics":["babeljs","isomorphic","nodejs","react","server-side-rendering","ssr","universal","webpack","webpack-concepts"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maerzhase.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}},"created_at":"2017-11-26T21:51:53.000Z","updated_at":"2023-01-28T16:27:47.000Z","dependencies_parsed_at":"2022-09-13T02:52:42.853Z","dependency_job_id":null,"html_url":"https://github.com/maerzhase/ssr3000","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maerzhase%2Fssr3000","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maerzhase%2Fssr3000/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maerzhase%2Fssr3000/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maerzhase%2Fssr3000/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maerzhase","download_url":"https://codeload.github.com/maerzhase/ssr3000/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235051607,"owners_count":18928186,"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":["babeljs","isomorphic","nodejs","react","server-side-rendering","ssr","universal","webpack","webpack-concepts"],"created_at":"2024-09-28T06:22:15.207Z","updated_at":"2025-10-02T23:35:43.126Z","avatar_url":"https://github.com/maerzhase.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SSR3000\n\nA simple framework for server-rendered react applications. \n###### \nBuild with [express](https://github.com/expressjs/express) and [webpack \u003e= 4.0.0](https://github.com/webpack/webpack).\n\n________\n\n\n- [Getting started](#getting-started)\n- [Serving static assets](#serving-static-assets)\n- [Customizing webpack config](#ssr3000configjs)\n- [Customizing ssr3000](#ssr3000rc)\n- [The idea](#the-idea)\n- [ServerMiddleware](#servermiddleware)\n- [Node.js API](#nodejs-api)\n- [CLI – Command Line Interface](#cli)\n- [Examples](#examples)\n- [A short digression into webpack](#a-short-digression-into-webpack\n)\n\n## Getting started\n\n  1. `npm install --save ssr3000 react react-dom react-hot-loader express lodash.template `\n\n  2. add scripts to your package.json\n\n```\n{\n  ...\n  scripts: {\n    \"watch\": \"./node_modules/.bin/ssr3000-watch\",\n    \"build\": \"./node_modules/.bin/ssr3000-build\",\n    \"serve\": \"./node_modules/.bin/ssr3000-serve\"\n  },\n  ...\n}\n```\n  3. create `src`, `src/serverMiddlware` and `src/components` folders\n\n  4. create client entry: `src/main.js`\n\n```JavaScript\nimport React from 'react';\nimport { hydrate } from 'react-dom';\nimport App from './components/App';\n\nhydrate(\n  \u003cApp /\u003e,\n  document.getElementById('root'),\n);\n```\n\n  5. create html template to serve: `src/serverMiddleware/index.ejs`\n\n```\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eSSR3000 App\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cdiv id=\"root\"\u003e\u003c%= app %\u003e\u003c/div\u003e\n    \u003c% chunks.js.forEach((chunk) =\u003e { %\u003e\u003cscript src=\"\u003c%= chunk %\u003e\"\u003e\u003c/script\u003e\u003c% }); %\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n  6. create server entry: `src/serverMiddleware/index.js`\n\n```JavaScript\nimport React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport { Router } from 'express';\nimport compile from 'lodash.template';\nimport templateContent from './index.ejs';\nimport App from '../components/App';\n\nconst template = compile(templateContent);\n\nexport default (chunks) =\u003e {\n  const router = new Router();\n  router.use((req, res) =\u003e {\n    res.status(200);\n    res.send(template({\n      chunks,\n      app: renderToString(\u003cApp /\u003e),\n    }));\n  });\n  return router;\n};\n``` \n\n  7. create your app e.g. `src/components/App.js`\n\n```JavaScript\nimport React from 'react';\nimport { hot } from 'react-hot-loader';\n\nconst App = () =\u003e (\n  \u003cdiv\u003e\n    Hello World\n  \u003c/div\u003e\n);\n\nexport default hot(module)(App);\n```\n###### SSR3000 uses hot reloading by default when watching your application. See [react-hot-loader](https://github.com/gaearon/react-hot-loader) for more informations.\n\n 8. `npm run watch`\n\n## Serving static assets\n\nSSR3000 comes with a build in solution to serve your static files. Just create folder called `static` inside your project root directory. From within your components you can now reference those files with `/static/` URLs.\n\n```JavaScript\n\u003cimg src=\"/static/cat.jpg\" /\u003e\n```\n\n\n## ssr3000.config.js\n\nIn order to extends the webpack configuration you can define a `ssr3000.config.js` file that exports a function, which returns the modified webpack configuration.\n##### Warning: this file is not going to be transpiled with babel. So you need to write it in vanilla JS and/or features that are supported by your Node.js version\n\n\n```JavaScript\nconst customConfig = (config, { isServer }) =\u003e {\n  return {\n    ...config,\n  }\n}\n\nmodule.exports = customConfig;\n\n```\n\nSince we are always configuring webpack for the client and the server, this function will get called twice. Once for the server and once for the client. You can distinguish between them with the isServer parameter.\n\n\n## .ssr3000rc\n\nUse the `.ssr3000rc` to configure SSR3000 for your project. The `.ssr3000rc` files must be a valid JSON file.\n\n```\n{\n  \"host\": \"localhost\",\n  \"port\": 8000\n}\n```\n\n### Options\n\n| Option                   | Default                              | Description                                           |\n| ------------------------ | ------------------------------------ | ----------------------------------------------------  |\n| `host`                   | `\"0.0.0.0\"`                          | set the hostname for the server                       |\n| `port`                   | `9999`                               | set the port for the server                           |\n\n## The idea\n\nSSR3000 is build around the principle of having two different entry files for your application:\n- The __client entry__, which usually calls `React.render` or `React.hydrate`\n- The __server entry__, that handles requests and serves a response to the client\n\nSSR3000 comes with a default webpack configuration that takes away the pain of setting up `webpack`. \nIf you need to customize the `webpack` configuration you can do that with the [`ssr3000.config.js`](#ssr3000configjs).\n\n## ServerMiddleware\n\nIt's important to realize that you are responsible for what get's rendered to your client. Without your middleware the server is running but there is no default way of handling responses — therefore without your middleware you will see no output in the browser. It also gives you the greatest flexibilty, because you can provide additional logic e.g. handle routing, serialize inital data to the browser, etc.\n\n\n## Node.js API\n\n### ssr3000\n\n```JavaScript\nssr3000()\n```\n\nthe default export of the SSR3000 module is an ssr3000 instance ready to be initialized. \n\n```JavaScript\nimport ssr3000 from 'ssr3000';\n\nconst SSR3000 = ssr3000();\n```\n\n### watch\n\n```JavaScript\nssr3000.watch(host, port)\n```\n\nThe watch function starts the SSR3000 server for development. When the first bundle is ready it will notify that a server has been started. If no `host` and/or `port` parameters are provided it will use the default values (0.0.0.0:9999) or use the values from the [`.ssr3000rc`](#ssr3000rc).\n\n```JavaScript\nimport ssr3000 from 'ssr3000';\n\nconst SSR3000 = ssr3000();\n\nSSR3000.watch('0.0.0.0', 9999); \n```\n\n### build\n\n```JavaScript\nssr3000.build()\n```\n\nThe build function will build your application for production.\n\n```JavaScript\nimport ssr3000 from 'ssr3000';\n\nconst SSR3000 = ssr3000();\n\nSSR3000.build();\n```\n\n### serve\n\n```JavaScript\nssr3000.serve(host, port)\n```\n\nThe serve function will serve the production build of your application – make sure u have used [ssr3000.build()](#build) before. If no `host` and/or `port` parameters are provided it will use the default values (0.0.0.0:9999) or use the values from the [`.ssr3000rc`](#ssr3000rc)..\n\n```JavaScript\nimport ssr3000 from 'ssr3000';\n\nconst SSR3000 = ssr3000();\n\nSSR3000.serve('0.0.0.0', 9999);\n\n```\n\n## CLI\n\nSSR3000 comes with a built-in CLI which can be used to watch, build and serve your application from the command line.\nThere three are methods exported to the `node_modules/.bin` folder. You are free to add [npm run scripts](https://docs.npmjs.com/cli/run-script) to your `package.json` or execute the cli tools with the relative path instead. You can configure SSR3000 with the [`.ssr3000rc`](#ssr3000rc).\n\n\n### watch\n\nstart development server\n\n`./node_modules/.bin/ssr3000-watch`\n\n\n### build\n\ncreate a production build\n\n`./node_modules/.bin/ssr3000-build`\n\n\n### serve\n\nrun the production server\n\n`./node_modules/.bin/ssr3000-serve`\n\n\n## Examples\n\nsee `examples/simple/` for a simple react application setup.\nsee `examples/advanced/` for an example with modified webpack config and [`react-jss`](https://github.com/cssinjs/react-jss) for (server-side) styles\n\n\n### Usage\n\nrun `npm install` from within the _examples/simple_ folder\n\nTo demonstrate the usage of the `.ssr3000rc` the example comes with commands to use the Node.js API and the CLI (npm commands have `cli:` prefix). You could run both at the same time because CLI and Node.js API start on different ports.\n\n#### Start development server\n\nTo start the dev server, run `npm run watch` or `npm run cli:watch`\n\n\n#### Build for production\n\nTo create a production build run `npm run build` or `npm run cli:build`\n\n\n#### Serve production build\n\nTo start the production server, run `npm run serve` or `npm run cli:serve`\n\n\n## A brief digression into webpack\nSSR3000 uses weback in the background to bundle your application. You no longer need to provide your own webpack configuration. SSR3000 aims to have a fully functional configuration made for all purpose. If you want to customize the webpack configuration anyway you can do that with the [`ssr3000.config.js`](#ssr3000configjs). \nThis section is meant to give you an overview of the most important parts of a webpack configuration. If u want to undestand how webpack works in detail please visit the [webpack-website](https://webpack.js.org).\n\n#### Entry\nSet the entry points of your application\n###### For full documentation see [Webpack Concepts: Entry](https://webpack.js.org/concepts/#entry)\n```\n{\n  target: 'web',\n  entry: [\n    './src/clientEntry.js',\n  ],\n  ...\n}\n```\n\n```\n{\n  target: 'node',\n  entry: [\n    './src/serverEntry.js',\n  ],\n  ...\n}\n```\n\n\n\n#### Output\nSet the output settings for your appliation.\n###### For full documentation see [Webpack Concepts: Output](https://webpack.js.org/concepts/#output)\n```\n{\n  target: 'web',\n  output: {\n    path: './build/client',\n    filename: '[name].[hash:8].js',\n    publicPath: '/assets/',\n  },\n  ...\n}\n```\n\n\n```\n{\n  target: 'node',\n  output: {\n    path: './build/server',\n    filename: 'bundle.js',\n    publicPath: '/assets/',\n    libraryTarget: 'commonjs2',\n  },\n  ...\n}\n```\n\n#### Loaders\nDecide how different file types should be loaded. This is done so u can require any file type in your code.\n###### For full documentation see [Webpack Concepts: Loaders](https://webpack.js.org/concepts/#loaders)\n```\n{\n  ...\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        include: JS_INCLUDES,\n        loader: 'babel-loader',\n      },\n    ],\n  },\n  ...\n}\n```\n\n#### Plugins (optional)\nWhile loaders are mandatory for all the file types that you use within your application, plugins are totally optional. \n\"Plugins range from bundle optimization and minification all the way to defining environment-like variables\", the webpack docs.\n###### For full documentation see [Webpack Concepts: Plugins](https://webpack.js.org/concepts/#plugins)\n```\n{\n  plugins: [\n    new webpack.optimize.UglifyJsPlugin(),\n  ],\n}\n```\n\n##### Target\nBecause our application is getting bundled for the client and for the server the webpack configs need to set the target option accordingly. \n`target: 'node'` or `target: 'web'`\n###### For full documentation see [Webpack Concepts: Target](https://webpack.js.org/concepts/targets/)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaerzhase%2Fssr3000","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaerzhase%2Fssr3000","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaerzhase%2Fssr3000/lists"}