├── .env ├── .eslintrc ├── .gitignore ├── README.md ├── package.json ├── public ├── favicon.ico └── robots.txt ├── src ├── application │ └── Main.js ├── client.js ├── index.js ├── server.js └── static.js └── yarn.lock /.env: -------------------------------------------------------------------------------- 1 | HOST=127.0.0.1 2 | PORT=80 -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app" 3 | , "rules": { 4 | "no-undef": 1 5 | , "eqeqeq": 0 6 | , "no-mixed-operators": 0 7 | , "no-extend-native": 0 8 | 9 | , "react/no-direct-mutation-state": 0 10 | 11 | , "no-useless-concat": 0 12 | } 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | static -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Razzle Material-UI Styled Example

2 | 3 |

4 | Node.js 5 |        Yarn 6 |        Razzle 7 |        Express 8 |

9 | 10 |

11 | React 12 |        Styled Components 13 |        Material-UI 14 |

15 | 16 |

17 |
GitPunch 18 |
⭐ Star and get notified about new releases via email. 19 |

20 | 21 | ## Features 22 | - Razzle 23 | - **S**erver **S**ide **R**endering 24 | - **H**ot **M**odule **R**eplacement for both client and server side React[React](https://facebook.github.io/react/) components 25 | - Up to date JavaScript ([**E**CMA](https://en.wikipedia.org/wiki/Ecma_International)**S**cript 6 (2015)) support 26 | - Single route static site generation 27 | - Express server with gzip [compression](https://github.com/expressjs/compression) 28 | - HTML and inline CSS and JS minification with [HTMLMinifier](https://github.com/kangax/html-minifier) 29 | - Styled Components [Styled Components](https://www.styled-components.com/) 30 | - Material-UI [Material-UI](http://www.material-ui.com/#/) 31 | 32 | ## Getting Started 33 | - Initial steps 34 | - Install Node.js and Yarn. 35 | - [Download](https://github.com/kireerik/razzle-material-ui-styled-example/archive/master.zip) or [clone](github-windows://openRepo/https://github.com/kireerik/razzle-material-ui-styled-example) this repository. 36 | - Open a command prompt in the project folder. 37 | 38 | > Install dependencies: 39 | > ```shell 40 | > yarn install 41 | > ``` 42 | 43 | Start the server: 44 | > ```shell 45 | > yarn start 46 | > ``` 47 | > This command initiates a build process and starts the server in production mode. 48 | 49 | Visit http://localhost/ to access the web application. 50 | 51 | ### Development 52 | Start the server in development mode: 53 | ```shell 54 | yarn dev 55 | ``` 56 | 57 | ### Single route static site generation 58 | Generate a static site: 59 | ```shell 60 | yarn static 61 | ``` 62 | Open the `index.html` within the `static` folder to access the web application. The folder name can be modified with the `RAZZLE_STATIC_PATH` environment variable. 63 | 64 | ## Idea behind the example 65 | This project is based on the [basic razzle example](https://github.com/jaredpalmer/razzle/tree/master/examples/basic). This repository also satisfies the following 2 entry points requred by Razzle: 66 | - `src/index.js` for the server 67 | - `src/client.js` for the browser 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "razzle build && cross-env NODE_ENV=production node build/server.js" 4 | , "dev": "razzle start" 5 | 6 | , "static": "cross-env RAZZLE_STATIC=true razzle build && cross-env NODE_ENV=production node build/server.js" 7 | } 8 | , "dependencies": { 9 | "express": "4.x" 10 | , "compression": "1.x" 11 | , "html-minifier": "3.x" 12 | 13 | , "react": "16.x" 14 | , "react-dom": "16.x" 15 | , "styled-components": "3.x" 16 | 17 | , "material-ui": "0.x" 18 | } 19 | , "devDependencies": { 20 | "cross-env": "5.x" 21 | , "razzle": "2.x" 22 | } 23 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kireerik/razzle-material-ui-styled-example/d5ea65bab29106de9d6a6be6d9ff7016f7d9445e/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | 3 | #Sitemap: -------------------------------------------------------------------------------- /src/application/Main.js: -------------------------------------------------------------------------------- 1 | // In this file, we create a React component which contains components provided by Material-UI. 2 | import React, {Component} from 'react' 3 | import styled, {injectGlobal} from 'styled-components' 4 | 5 | import {MuiThemeProvider, getMuiTheme} from 'material-ui/styles' 6 | import {deepOrange500} from 'material-ui/styles/colors' 7 | 8 | import {RaisedButton, Dialog, FlatButton} from 'material-ui' 9 | 10 | injectGlobal` 11 | h1, h2 { 12 | font-family: 'Roboto', sans-serif; 13 | } 14 | ` 15 | 16 | const Div = styled.div` 17 | text-align: center; 18 | padding-top: 200px; 19 | ` 20 | 21 | export default class Main extends Component { 22 | constructor(properties) { 23 | super(properties) 24 | 25 | this.muiTheme = getMuiTheme({ 26 | palette: { 27 | accent1Color: deepOrange500 28 | } 29 | , userAgent: properties.userAgent 30 | }) 31 | 32 | this.state = { 33 | open: false 34 | } 35 | } 36 | 37 | handleRequestClose = () => this.setState({ 38 | open: false 39 | }) 40 | 41 | handleClick = () => this.setState({ 42 | open: true 43 | }) 44 | 45 | render = () => 46 | 47 |
48 |

Material-UI

49 |

example project

50 | 51 | 52 | 54 | } onRequestClose={this.handleRequestClose}>1-2-3-4-5 55 |
56 |
57 | } -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {hydrate} from 'react-dom' 3 | 4 | import Application from './application/Main' 5 | 6 | hydrate(, document.getElementById('root')) 7 | 8 | if (module.hot) 9 | module.hot.accept() -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import server from './server' 3 | 4 | import generateStaticSite from './static' 5 | 6 | if (module.hot) { 7 | module.hot.accept('./server') 8 | console.info('Server-side HMR Enabled.\n') 9 | } 10 | 11 | const mainServer = express() 12 | .use((request, response) => server.handle(request, response)) 13 | 14 | , serverInstance = mainServer 15 | .listen(process.env.PORT, error => { 16 | if (error) { 17 | console.error(error) 18 | 19 | return 20 | } 21 | 22 | console.log('Server started at ' + process.env.HOST + ':' + process.env.PORT + '.\n') 23 | 24 | if (process.env.RAZZLE_STATIC) 25 | generateStaticSite(serverInstance) 26 | }) 27 | 28 | export default mainServer -------------------------------------------------------------------------------- /src/server.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import compression from 'compression' 3 | import {minify} from 'html-minifier' 4 | 5 | import React from 'react' 6 | import {renderToString} from 'react-dom/server' 7 | import {ServerStyleSheet} from 'styled-components' 8 | 9 | import Application from './application/Main' 10 | 11 | const assets = require(process.env.RAZZLE_ASSETS_MANIFEST) 12 | 13 | // Workaround for Razzle's assets route issue in terms of static site genearation 14 | var clientCss = assets.client.css 15 | , clientJs = assets.client.js 16 | 17 | if (process.env.NODE_ENV == 'production') { 18 | if (clientCss) 19 | clientCss = clientCss.replace('/', '') 20 | 21 | clientJs = clientJs.replace('/', '') 22 | } 23 | 24 | export default express() 25 | .disable('x-powered-by') 26 | .use(compression()) 27 | .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) 28 | .get('/*', (request, response) => { 29 | const sheet = new ServerStyleSheet() 30 | , html = renderToString(sheet.collectStyles()) 31 | , css = sheet.getStyleTags() 32 | 33 | response.send(minify( 34 | ` 35 | 36 | 37 | Material-UI Example 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ` + (clientCss ? 48 | '' : '' 49 | ) + css + ` 50 | 51 | 52 | 53 | 54 |
` + html + `
55 | 56 | ` 57 | , { 58 | collapseWhitespace: true 59 | , removeComments: true 60 | , minifyCSS: true 61 | , minifyJS: true 62 | })) 63 | }) -------------------------------------------------------------------------------- /src/static.js: -------------------------------------------------------------------------------- 1 | import http from 'http' 2 | import fs from 'fs-extra' 3 | 4 | const staticDirectory = process.env.RAZZLE_STATIC_PATH || 'static' 5 | 6 | export default server => { 7 | fs.emptyDirSync(staticDirectory) 8 | 9 | fs.copy(process.env.RAZZLE_PUBLIC_DIR, staticDirectory) 10 | 11 | http.get({url: 'http://' + process.env.HOST + ':' + process.env.PORT 12 | , headers: {'User-Agent': 'all'} 13 | }, response => 14 | response.on('data', html => 15 | fs.writeFile(staticDirectory + '/' + 'index.html', html, error => { 16 | if (error) 17 | console.error(error) 18 | 19 | server.close() 20 | 21 | console.log('Static site generated.\n') 22 | }) 23 | ) 24 | ) 25 | } --------------------------------------------------------------------------------