FoalTS / foal

Full-featured Node.js framework 🚀
https://foalts.org/
MIT License
1.9k stars 142 forks source link

Some common features that would be awesome #381

Closed rick-software closed 5 years ago

rick-software commented 5 years ago

server-side-render sharing via email/social i18n

This is awesome by the way!

LoicPoullain commented 5 years ago

Thanks for the suggestion. I'll put this in the backlog.

Regarding SSR, is this link what you're looking for? https://foalts.gitbook.io/docs/topic-guides/utilities/templating

rick-software commented 5 years ago

renderToString is definitely needed... instead of a template engine is it possible to simply use JSX? Thanks for your timely responses.

On Fri, Mar 15, 2019 at 8:44 AM Loïc Poullain notifications@github.com wrote:

Thanks for the suggestion. I'll put this in the backlog.

Regarding SSR, is this link what you're looking for? https://foalts.gitbook.io/docs/topic-guides/utilities/templating

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FoalTS/foal/issues/381#issuecomment-473336768, or mute the thread https://github.com/notifications/unsubscribe-auth/AjoLmHAxQF6HXQ7bCzGPG4u8dpuHFZqNks5vW7-_gaJpZM4b05Ay .

LoicPoullain commented 5 years ago

Would you have a code example of what you would like to have? What are you trying to accomplish?

rick-software commented 5 years ago

I use material ui and nivo charts and want to be able to render react components on the server for use in shares, emails and embeds.

Here's what I'm doing on the server (App, here is just the Dashboard):

import express from 'express' import React from 'react' import ReactDOMServer from 'react-dom/server' import { SheetsRegistry } from 'jss' import JssProvider from 'react-jss/lib/JssProvider' import { MuiThemeProvider, createMuiTheme, createGenerateClassName } from '@material-ui/core/styles' import green from '@material-ui/core/colors/green' import red from '@material-ui/core/colors/red' import App from './App'

function renderFullPage(html, css) { return ` <!doctype html>

Material-UI
${html}

` }

function handleRender(req, res) { // Create a sheetsRegistry instance. const sheetsRegistry = new SheetsRegistry()

// Create a sheetsManager instance. const sheetsManager = new Map()

// Create a theme instance. const theme = createMuiTheme({ palette: { primary: green, accent: red, type: 'light' }, typography: { useNextVariants: true } })

// Create a new class name generator. const generateClassName = createGenerateClassName()

// Render the component to a string. const html = ReactDOMServer.renderToString( <JssProvider registry={sheetsRegistry} generateClassName={generateClassName}

)

// Grab the CSS from our sheetsRegistry. const css = sheetsRegistry.toString()

// Send the rendered page back to the client. res.send(renderFullPage(html, css)) }

const app = express()

app.use('/build', express.static('build'))

// This is fired every time the server-side receives a request. app.use(handleRender)

app.listen(7000)

On Fri, Mar 15, 2019 at 8:58 AM Loïc Poullain notifications@github.com wrote:

Would you have a code example of what you would like to have? What are you trying to accomplish?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/FoalTS/foal/issues/381#issuecomment-473342421, or mute the thread https://github.com/notifications/unsubscribe-auth/AjoLmB2CZbx2zxXc7viwkh_sJd5FBVoPks5vW8MjgaJpZM4b05Ay .

LoicPoullain commented 5 years ago
import express from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { SheetsRegistry } from 'jss'
import JssProvider from 'react-jss/lib/JssProvider'
import { MuiThemeProvider, createMuiTheme, createGenerateClassName } from '@material-ui/core/styles'
import green from '@material-ui/core/colors/green'
import red from '@material-ui/core/colors/red'
import App from './App'

function renderFullPage(html, css) {
  return `
    <!doctype html>
    <html>
    <head>
    <title>Material-UI</title>
    </head>
    <body>
    <script async src="build/bundle.js"></script>
    <div id="root">${html}</div>
    <style id="jss-server-side">${css}</style>
    </body>
    </html>
  `
}

function handleRender(req, res) {
  // Create a sheetsRegistry instance.
  const sheetsRegistry = new SheetsRegistry()

  // Create a sheetsManager instance.
  const sheetsManager = new Map()

  // Create a theme instance.
  const theme = createMuiTheme({
    palette: {
      primary: green,
      accent: red,
      type: 'light'
    },
    typography: {
      useNextVariants: true
    }
  })

  // Create a new class name generator.
  const generateClassName = createGenerateClassName()

  // Render the component to a string.
  const html = ReactDOMServer.renderToString(
    <JssProvider
      registry={sheetsRegistry}
      generateClassName={generateClassName}>
        <MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
          <App />
        </MuiThemeProvider>
    </JssProvider>
  )

  // Grab the CSS from our sheetsRegistry.
  const css = sheetsRegistry.toString()

  // Send the rendered page back to the client.
  res.send(renderFullPage(html, css))
}

const app = express()

app.use('/build', express.static('build'))

// This is fired every time the server-side receives a request.
app.use(handleRender)

app.listen(7000)
LoicPoullain commented 5 years ago

@rick-software I came up with this implementation with Foal:

import { Context, Get, HttpResponseOK } from '@foal/core';

import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { SheetsRegistry } from 'jss'
import JssProvider from 'react-jss/lib/JssProvider'
import { MuiThemeProvider, createMuiTheme, createGenerateClassName } from '@material-ui/core/styles'
import green from '@material-ui/core/colors/green'
import red from '@material-ui/core/colors/red'
import App from './App'

class AppController {

  private renderFullPage(html, css) {
    return `
      <!doctype html>
      <html>
      <head>
      <title>Material-UI</title>
      </head>
      <body>
      <script async src="build/bundle.js"></script>
      <div id="root">${html}</div>
      <style id="jss-server-side">${css}</style>
      </body>
      </html>
    `
  }

  @Get('*')
  render() {
    // Create a sheetsRegistry instance.
    const sheetsRegistry = new SheetsRegistry()

    // Create a sheetsManager instance.
    const sheetsManager = new Map()

    // Create a theme instance.
    const theme = createMuiTheme({
      palette: {
        primary: green,
        accent: red,
        type: 'light'
      },
      typography: {
        useNextVariants: true
      }
    })

    // Create a new class name generator.
    const generateClassName = createGenerateClassName()

    // Render the component to a string.
    const html = ReactDOMServer.renderToString(
      <JssProvider
        registry={sheetsRegistry}
        generateClassName={generateClassName}>
          <MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
            <App />
          </MuiThemeProvider>
      </JssProvider>
    )

    // Grab the CSS from our sheetsRegistry.
    const css = sheetsRegistry.toString()

    // Send the rendered page back to the client.
    return new HttpResponseOK(
      this.renderFullPage(html, css)
    );
  }

}

If I understand well (tell me if I'm wrong), you currently have two problems:

Regarding the first point, I'm going to open an issue for that as other people may need this too.

Regarding the second point, could it be solved by renaming your file with the tsx extension and update your tsconfig.json file?

{
  "compilerOptions": {
    ...
    "jsx": "react"
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
  ]
}

Let me know if this works.

LoicPoullain commented 5 years ago

I added a small tuto on JSX SSR in the docs. With regard to the sharing via email/social feature, would nodemailer be what you're looking for?

rick-software commented 5 years ago

Yes

On Mon, Apr 22, 2019 at 9:35 AM Loïc Poullain notifications@github.com wrote:

I added a small tuto on JSX SSR in the docs. With regard to the sharing via email/social feature, would nodemailer https://nodemailer.com/about/ be what you're looking for?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/FoalTS/foal/issues/381#issuecomment-485469089, or mute the thread https://github.com/notifications/unsubscribe-auth/AI5AXGAE5NVL23QDAXZLYOLPRXSNDANCNFSM4G6TSAZA .

LoicPoullain commented 5 years ago

Closing this in favor of #447 & #448