Giter Site home page Giter Site logo

alidcast / rogue.js Goto Github PK

View Code? Open in Web Editor NEW
1.9K 22.0 49.0 849 KB

The "nearly invisible" way to server-render React applications

License: MIT License

JavaScript 65.03% TypeScript 34.97%
server-side-rendering react react-router-v4 apollo css-in-js

rogue.js's People

Contributors

alidcast avatar davidjb avatar gaverdugo avatar isbasex avatar juanbrujo avatar kanuny avatar msrahman07 avatar rayandrew avatar stevefan1999-personal avatar thompsonemerson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rogue.js's Issues

add more examples

nextjs /examples folder provides a great starting point if anyone wants to help with this

Though I'm thinking so many examples aren't needed since Rogue is much simpler (It's basically just React and React Router 4!).

I'll soon create a starter template and I think that will be much more useful than examples; but I'll still leave this issue here in case anyone encounters it and wants to contribute/discuss

ReferenceError: SERVER is not defined

hi,

0.1.9 build results in the following error

ReferenceError: SERVER is not defined
    at Object.<anonymous> (.../node_modules/rogue/scripts/dev.js:16:31)
    at Module._compile (internal/modules/cjs/loader.js:702:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10)
    at Module.load (internal/modules/cjs/loader.js:612:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:551:12)
    at Function.Module._load (internal/modules/cjs/loader.js:543:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:744:10)
    at startup (internal/bootstrap/node.js:238:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:572:3)

0.1.6 is OK

thanks,

tinto

disambiguate usage of getInitialProps

We need to decide on getInitialProps` usage:

  • Are server rendered props meant to be passed only to each respective page -- or can we keep passing them only to App.js component? #37 #6
  • Should getInitialProps be called during client navigation? #18
  • Does the behavior of getInitialProps align with expectations based on its name? If not, we should consider our own method #42

In order to get point 1 & 2 I'm thinking we would need to wrap Router component so that we can handle getInitialProps per page on the client...though that still leaves open behavior for Providers/Hocs that aren't nested in Routes

For now I'm considering changing name since it seems to be simplest path forward

Consider making rogue app independent of build setup

There are two ways we can go with Rogue. The Nextjs route, where the build setup and ssr setup are together, or Afterjs route, where they are separate and you can use any build system (.e. Razzlejs)

The reason I'm considering the second option, is that I've run into a few problems with Parcel; and I'm supposed to be focused on building an app I'm working on, so would like to get back to that asap

If we make a Rogue app independent of build setup, then anyone can start using Rogue now using Razzle and not have to wait till the rogue-parcel-srr build setup is far enough along to push an app to production; and later it should be easy to exchange Razzle for a Rogue-Parcel setup fsor faster build times

I'll also note that, @DeMoorJasper, a core team member of Parcel, recently released Blazingly (https://github.com/DeMoorJasper/blazingly), an experimental repo testing Parcel for SSR. I think I'd be awesome if we could work together towards a common solution. If he'd consider putting the framework specific bit aside, I could see Blazingly turning into a Razzlejs alternative that any application, such as Rogue, can run on top of.

You guys have showed interested in project so cc'ing you to get your thoughts
@alexparish @peter-mouland @ctrlplusb @nyl-auster

Uncaught Error: Cannot find module 'core-js/modules/es6.typed.array-buffer'

bundle.js:39 Uncaught Error: Cannot find module 'core-js/modules/es6.typed.array-buffer'
at newRequire (VM152 bundle.js:39)
at localRequire (VM152 bundle.js:54)
at Object.parcelRequire.1 (VM152 bundle.js:109)
at newRequire (VM152 bundle.js:48)
at parcelRequire.1 (VM152 bundle.js:80)
at VM152 bundle.js:106

call `getInitialProps` on client side navigation

We shouldn't call it on client side mount side that will cause a props mismatch. But it should still be called on client navigation, i.e. for redirects to work.

In order to make this happen I'm thinking will need to wrap the router Link component (which I'd rather not do), unless there's a way to hook up to its events; gotta look into this

TypeError: Cannot destructure property `bundleUrl` of 'undefined' or 'null'.

Hey, I've been checking out your project and I've been having some trouble integrating it into my React application which needs SSR. Essentially what happens is that I get the following error when I run npm run dev:

C:\Users\lukec\Documents\git\the-jade-podium\node_modules\@roguejs\app\dist\server.js:165
    constructor(App, { bundleUrl }) {
               ^
TypeError: Cannot destructure property `bundleUrl` of 'undefined' or 'null'.
    at new App (C:\Users\lukec\Documents\git\the-jade-podium\node_modules\@roguejs\app\dist\server.js:165:16)
    at Module../src/server.js (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\src\server.js:9:1)
    at __webpack_require__ (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\webpack\bootstrap:682:1)
    at fn (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\webpack\bootstrap:59:1)
    at Module../src/index.js (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\src\index.js:1:1)
    at __webpack_require__ (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\webpack\bootstrap:682:1)
    at fn (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\webpack\bootstrap:59:1)
    at Object.0 (C:\Users\lukec\Documents\git\the-jade-podium\build\server.js:1704:18)
    at __webpack_require__ (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\webpack\bootstrap:682:1)
    at module.exports../build/assets.json.module.exports.client.js (C:\Users\lukec\Documents\git\the-jade-podium\build\webpack:\webpack\bootstrap:749:1)

I modified my code to be similar to what you have for the with-razzle example. Here is my package.json:

{
  "name": "the-jade-podium",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@roguejs/app": "^0.6.8",
    "razzle": "^2.2.0",
    "react-bulma-components": "^1.5.0",
    "react-typography": "^0.16.13",
    "typeface-cabin-condensed": "0.0.54",
    "typeface-patua-one": "0.0.54",
    "typography": "^0.16.17",
    "typography-theme-funston": "^0.15.10",
    "babel-polyfill": "^6.26.0"
  },
  "scripts": {
    "dev": "razzle start"
  }
}

client.js

import { hydrate } from '@roguejs/app'
import App from './App'

hydrate(App)

index.js

import http from 'http'
import app from './server'

const server = http.createServer(app.render)

let currentApp = app

server.listen(process.env.PORT || 3000, error => {
  if (error) {
    console.log(error)
  }

  console.log('๐Ÿš€ started')
})

if (module.hot) {
  console.log('โœ…  Server-side HMR Enabled!')

  module.hot.accept('./server', () => {
    console.log('๐Ÿ”  HMR Reloading `./server`...')
    server.removeListener('request', currentApp)
    const newApp = require('./server').default
    server.on('request', newApp)
    currentApp = newApp
  })
}

server.js


import Rogue from '@roguejs/app/server'
import { Helmet } from 'react-helmet'
import serveStatic from 'serve-static'
import App from './App'

const publicDir = process.env.RAZZLE_PUBLIC_DIR
const bundleUrl = require(process.env.RAZZLE_ASSETS_MANIFEST).client.js

const app = new Rogue({
  Helmet,
  App, 
  bundleUrl
})

app.preuse(serveStatic(publicDir))

export default app

and my App.js

import React, { Component } from 'react';
import './App.css';
import 'react-bulma-components/dist/react-bulma-components.min.css';
import { Columns } from 'react-bulma-components';
import NavBar from './components/NavBar';
import Banner from './components/Banner';
import Typography from 'typography';
import funstonTheme from 'typography-theme-funston';
import logo from './assets/images/logo.png';

const typography = new Typography(funstonTheme);


typography.injectStyles();
class App extends Component {
  render() {
    return (
      <div className="App">
        <NavBar/>
        <Banner/>
      </div>
    );
  }
}

export default App;

Do you have any idea what I could be doing wrong?

npm run dev : Unknown script "undefined".

Hello here !
when running "npm run dev" i get the following message :
( mac OS Sierra 10.12.6, npm 6.1.0 )

> [email protected] dev /Applications/MAMP/htdocs/TEST/roguetest
> rogue

Unknown script "undefined".
Perhaps you need to update renso?

My package.json:

{
  "name": "roguetest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "rogue",
    "build": "rogue build",
    "start": "rogue start"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-router-dom": "^4.3.1",
    "rogue": "^0.1.1"
  }
}

Access parsed route parameters in getInitialProps

It would be very useful to be able to access the parsed route params in getInitialProps to load a particular resource using the url params as identifiers.

For example, when navigating to /users/:name:

export default class App extends React.Component {
  static async getInitialProps({ params }) {
    const user = await fetchUserByName(params.name)
    return { user }
  }
  // ...
}

I couldn't find a way to do this without parsing req.url manually.

Awesome work

Sorry, not an issue. Just want to sing your praise on the work you are doing here. Amazing stuff. ๐Ÿ‘

[QUESTION] Not with Apollo GraphQL

Can I still use this even I don't use Apollo GraphQL? Im using React Router 4 to manage my routes and I would like to explore doing SSR.

Cheers!

Npm name

Hey @mkay581 are you still using the rogue npm name? I couldn't find any repo for it but did see that you published a package under it.

If you're not using it, are you willing to give it away? I'm creating a SSR framework for React, with the tagline that it's "quick and invisible" so I'd love to use that name.

I didn't know how else to reach you, so if you see this let me know, thanks!

Add a logo - any designers/illustrators out there?

I really like emotion's logo.

Not sure how hard this would be to pull off, but I'd be super cool to have a logo that shows the upper body of semi-invisible female with a rogue outfit that partially displays a react logo

I'm also open to any ideas

If anyone is interested in contributing this, let me know

credit & link to your work will be given in readme

Electron and Rogue

Can one of the examples be of importing this into an electron app. Please.

Error: ENOENT: no such file or directory, stat '/Applications/MAMP/htdocs/TEST/roguetest/public' at Object.fs.statSync (fs.js:948:11)

[email protected] dev /Applications/MAMP/htdocs/TEST/roguetest
rogue dev

fs.js:948
binding.stat(pathModule._makeLong(path));
^

Error: ENOENT: no such file or directory, stat '/Applications/MAMP/htdocs/TEST/roguetest/public'
at Object.fs.statSync (fs.js:948:11)
at /Applications/MAMP/htdocs/TEST/roguetest/node_modules/graceful-fs/polyfills.js:297:22
at getStats (/Applications/MAMP/htdocs/TEST/roguetest/node_modules/fs-extra/lib/copy-sync/copy-sync.js:42:14)
at startCopy (/Applications/MAMP/htdocs/TEST/roguetest/node_modules/fs-extra/lib/copy-sync/copy-sync.js:37:10)
at copySync (/Applications/MAMP/htdocs/TEST/roguetest/node_modules/fs-extra/lib/copy-sync/copy-sync.js:32:10)
at prepBuild (/Applications/MAMP/htdocs/TEST/roguetest/node_modules/rogue/src/bundler/index.js:55:3)
at bundler (/Applications/MAMP/htdocs/TEST/roguetest/node_modules/rogue/src/bundler/index.js:61:3)
at Object. (/Applications/MAMP/htdocs/TEST/roguetest/node_modules/rogue/scripts/dev.js:21:23)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)

how to pass props directly to each page component (and is it worth the hassle?)

Right now any data returned from getInitialProps will be passed to the App.js component. That component can then delegate the data to each page component.

Obviously, this isn't ideal as each getInitialProps should operate in a black box.

Some ideas for handling this correctly:

  • As we walk the component tree, we can recreate it and pass each component the correct data (honestly not even sure if this could work?)
  • We can do what loadable-components does and pass data from server to window object and the render component with appropriate data (this seems like the way to go)

However, I don't know to what extent this is worth the hassle. If you're using Apollo, you don't really need to fetch data from getInitialProps (right??). So it's only useful for plugin hocs (e.g. Apollo, Redux, etc) to server render their own data (which would be passed to App.js anyway) and to handle route middleware in the server (which doesn't return any data).

So going to leave it as it is for now but posting my thoughts here for reference

babel plugin to extract server side only component methods

First need to resolve #42

getIntialProps is only called in server now to bootstrap App.js with server logic

This method can be extracted at compile from the client bundle using a babel plugin. This would prevent unnecessary server code from being included in client bundle without relying on tree-shaking

bundlerUrl: bundle.js: Uncaught SyntaxError: Unexpected token <

I am running rogue.js version 0.6.10 and still getting this issue for bundle.js. Mentioned in #20.

I am also new to SSR and I don't know if I figured out what is the right purpose for this bundle. Should it be compiled client side (client.js) script for usage when continuing with an app on the browser side after initial server render?

razzle example uses some client.js script so I don't know, because when I build the app via @roguejs/cli the bundle.js contains ES5 version of server.js code, but that may be the error and because of it I got confused.

Thanks for answer.
Keep up the great work. Rogue.js will be awesome.

should we walk tree two switch statements deep?

right now we're walking tree checking for two switch statements

The idea was that you'd have a layout and a page

However, with React Router 4, layouts are declared inside the same route as a page

E.g. rather than this

<Route path="login|register" component={AuthLayout} />

You do this:

<Route path="login" render:{() => <AuthLayout><Login /><AuthLayout>} />

So we can likely remove condition where we look for two switch statements, and just continue walking tree until we find non-servevable components 5 levels apart

Custom css-in-js solutions

How would it be like to write custom plugins for rogue?
I'd like to support JSS to use Material-UI and it seems that only rogue-made hocs would work.
As I could see from their code, the hocs are simple and I could implement another one myself.
My question is: would that work? Because from what I could see from the docs it wouldn't.

Thanks for the awesome work!

Error in browser when calling render on initial load

I'm getting the following error when running the with-razzle example:

Warning: render(): Calling ReactDOM.render() to hydrate server-rendered markup will stop working in React v17. Replace the ReactDOM.render() call with ReactDOM.hydrate() if you want React to attach to the server HTML.

From what I can tell, the error seems to occur because window.__SSR_DATA__ is an empty object initially, which causes render to be called. As I understand it, hydrate should be called initially, followed by render going forward on the client.

Would it be reasonable to tweak this similar to the approach Next took?

bundling code is a pain!!

Spent all day yesterday trying to get to the bottom of bundling issues... first an unexpected token import then an undefined module 'react' error.

I was using the package via a linked module, so then I randomly tried downloading the actual package and it worked, jesus

So problem seems to be the Parcel treats linked modules differently than downloaded ones (parcel-bundler/parcel#1617)... geezzz, I guess that's why people don't like too much magic but still I think Parcel's going to be great

Anyway, I ended up going back to es5 code and using React.createElement rather than JSX and now, no bundling needed!

Wow, everythings so simple now

I hate fighting with bundling issues, such a waste of time

Opening this issue as a reminder of why I made this decision, and so I can send anyone that asks over here

Cheers

zero configuration?

I like the idea of zero configuration while being able to eject (like create-react-app)

Just not sure if for SSR it's more problems than it's worth.

E.g. if I contionally take over server.js, need a way for user to still start app manually for testing

Odd behavior running with-razzle example

I'm running into very odd behavior using the with-razzle example. The Razzle app runs and reloads as expected prior to adding Rogue and I'm wondering if anyone else is seeing this behavior or not.

Steps to reproduce:

  • Create new Razzle app

    create-razzle-app with-razzle
    cd with-razzle

  • Start the app, make a change to Home.js, then verify the app is built and reloads as expected

  • Install Rogue using specific version to match with-razzle example

    yarn add @roguejs/[email protected]

  • Overwrite contents of local server.js, index.js, client.js, and App.js files with content from with-razzle example directory files

  • Start the app, make a change to App.js, then verify the app is built and reloads as expected

    โˆš success server compiled in 141ms
    โˆš success client compiled in 165ms
    ๐Ÿ”  HMR Reloading `./server`...
    [HMR] Updated modules:
    [HMR]  - ./src/App.js
    [HMR]  - ./src/server.js
    [HMR] Update applied.
    โˆš success client compiled in 564ms
  • Error displayed in the console:

    Warning: Text content did not match. Server: "Roguejs with Razzle" Client: "Roguejs with Razzle!"

  • Browser still shows old content, but view source and JS bundle show the updated content

  • Upgrade @rogue/app to 0.6.11

  • Start the app, make a change to App.js, then verify the app is built and reloads as expected

    โˆš success server compiled in 750ms
    โˆš success client compiled in 671ms
    ๐Ÿ”  HMR Reloading `./server`...
    [HMR] Updated modules:
    [HMR]  - ./src/App.js
    [HMR]  - ./src/server.js
    [HMR] Update applied.
    โˆš success client compiled in 933ms
  • Browser shows the change quickly, then reverts to the content as it was prior to the change. Also, the 'text content did not match' message is back in the console.

  • View page source and JS bundle both have content matching the source

    "dependencies": {
      "@roguejs/app": "0.6.11",
      "express": "4.16.3",
      "razzle": "2.2.0",
      "react": "16.4.1",
      "react-dom": "16.4.1",
      "react-router-dom": "4.3.1"
    }

OS: Windows 10
Node: 8.11.3
Yarn: 1.5.1

redux store provider initiated before page component

Right now we walk component tree and call getInitialProps per component

The problem for redux is that getInitialProps is called before App/Page components, so its doing nothing for ssr the store

Few ideas:

  • add a function like nuxtjs does for ssr logic that the store should handle (not ideal)
  • different methods to call before and post walking tree (not ideal)
  • I considered changing way hocs work such that they wrap one another (better but then store would only work for App.js and not Pages)

I guess it goes back to #42 - if pages don't need to query server data nor handle redirects what do pages need getInitialProps for?

Question: Server-side authentication

Hi there,

I was wondering if it would be possible to have a route protected by some server-side authentication.

Simplest example:

  • Auth page (public)
  • Secret page (loaded only if authenticated)

Most importantly, the data (including layout / content of the page) cannot be transmitted unless the client has successfully authenticated. I was hoping to use import and have the server only return the component if the user is authenticated but don't know how to hook into this tool (or if it is possible).

Thanks in advance!

bundle.js:sourcemap:5721 Warning: Text content did not match.

Hi!

I'm giving rogue a trial with typescript.

I'm just using the example setup but exchanged the App.js with a App.tsx.

It's not hot-reloading and when i change the text in the divs i get the folowing error:

bundle.js:sourcemap:5721 Warning: Text content did not match. Server: "Welcome to Rogue.js test!" Client: "Welcome to Rogue.js!"...

What gives? Did i miss something?

cache busting

When you do a 'npm run build' it be great if the files had checksums for cache busting (like webpack does). Otherwise you will still need to something like grunt to do that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.