-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server-side rendering #3
Comments
I'm gonna start working on this soon. I think to load the pack files we should stick to some convention (probably configurable) like react-rails' components.js does, so we know where can find the components. |
You can have multiple components registered in one packfile. The logic is to have separate packs for different parts of your website, but you may have multiple root components in it, especially if not using an SPA. |
Exactly, that file ( |
Seems good. Maybe use a more expressive default name, like |
I'd try to challenge the whole server-side rendering idea later :) |
Hi guys, any news about server side rendering? |
I
|
@sevos for our company server side rendering is not a choice: it's mandatory. We don't have a full SPA but many simple widgets that for SEO and UX reasons need to be already present when the browser/bot loads the page. It can of course add some edge cases due to many different libraries available, but IMHO is up you to choose one that does not need the browser env or to implement a different approach when the server side rendering is running... What do you think? |
@risinglf @sevos @daninfpj Why would prefer to put server rendering in this library compared to using React on Rails? |
@justin808: The whole point of this library (not just server rendering) is to take advantage of Rails 5.1 (currently on rc2) first-class support for Webpack and React. This allows for a cleaner and simpler integration in my opinion. |
@daninfpj wrote:
We're almost done with that. See shakacode/react_on_rails#822 and shakacode/react_on_rails#811. and see: |
React on Rails 8.0.0 shipped with support for webpacker_lite. I think this has the server rendering support you desire. |
Hi guys, how is this feature progress? |
Is there anything we can do to help? |
I have not got time to really work on server-rendering. If you would like to have a stab at it, feel free! I outlined my ideas in this issue and I am available to discuss it further. I am not opposed to a minimal and non-modular approach at first, supporting only |
I've got a minimal approach working already if that is of interest. I'm using I took the single point of entry approach with one "server" pack that imports all the various components. Right now the issue I'm working through is due to the way webpacker 3 enables the |
Nice! This seems like a good start. What is the issue with |
Ya, I've read through that issue. I actually don't need to turn off inline mode like is specified there. I'm messing with a server-only webpack config to try and figure out a clean way of having HMR and server side rendering. I'm not a huge fan of that thread's suggestion of maintaining a per-file list. IMO there should be another point of entry for server-side packs that the second config handles. Another issue at play here is whether or not the client will then mount the same component on top of the server side render. This may not be wanted if you are basically statically rendering React components out, but if you are trying to bootstrap a SPA you probably want to do that. One thing at a time though 😄
|
Well, server rendering should not worry about styles at all and not output anything related (except for css modules). React 16 changed quite a lot of things related to SsR’ I foudn this article useful: https://medium.com/@aickin/whats-new-with-server-side-rendering-in-react-16-9b0d78585d67 Can you publish your work in progress somewhere so I can have a look and we can discuss over real code? This will be easier 🙂 |
Agree to disagree on that one. We use Also, not everyone's whole stack is Ruby. We've got SPA, express, and Rails apps in production. We have a React-based component library that is shared between them. Components like our footer take an initial set of props and are rendered out. Having that statically rendered is a valid use case for us. The issue isn't even about the appropriateness of CSS on the server. When the style-loader is enabled webpack emits additional code that causes execJS to choke. However, you need the style-loader for HMR. So, you either get HMR or server side rendering. Sure, I can put stuff up in a gist |
Ok I see how it works. Let me correct what I said by "server-rendering should ignore I guess we will need hooks to allow The first and simplest goal of server-side rendering is to be able to call |
Here's a gist of what we are using right now. Like I said, this is a pretty simple implementation. I'm still wondering if a server-only webpack config is a better approach. It would make messing around with https://gist.github.com/wingrunr21/b2e2a1aca3083eb877a6deae9dedbd89 |
@renchap @wingrunr21 I am about to tackle this in my app. Is there any progress on this or should I pickup from the gist @wingrunr21 posted? |
@tomasc I won't be submitting a PR to this repo for server side render support. As we continued to iterate on our solution, it became obvious that a more standalone solution was the best fit. We are prepping to open source a generic SSR solution for webpacker (which will still have full support for |
@wingrunr21 that sounds good. If interested, I can help test your project as I am about to start dealing with SSR and solution with bare-bones |
@tomasc I havent got time to work on this yet. Feel free to tackle it if you want! @wingrunr21 I am curious about how you want to tackle it at the Webpacker level. Can you outline how it would work? |
@wingrunr21 Yep that sounds interesting. Just commenting so I watch this thread (spying from react-rails 😉 ) |
@BookOfGreg honestly, your SSR support formed a really solid basis for the work. It definitely gave us a good starting point on a solution that was known to work. Your project is also a reason we wanted to target a more generic webpacker solution. It's fairly difficult to parse out how to implement SSR in an express application without using something like @renchap Sure. We wanted this to work as closely as possible to how "real" SSR is done in a node environment. As I outlined before, our onus around this is because our React codebases are used across various environments. In addition, the vast majority of SSR testing by upstream users is done against a node environment. Emulating how those setups work seemed to be the optimal approach.
|
@wingrunr21 is there any updated on this please? I am eager to test or help out. |
@tomasc sorry, our November/December ended up being crazy with other work. I'm working on it this weekend and hope to have some good stuff come next week. |
@wingrunr21 thanks, that would be fantastic – and right on time ;-) |
@wingrunr21 🤞 that you still working on this, do you have ETA in mind? |
Code is up: https://github.com/GuildEducationInc/webpacker_ssr, https://github.com/GuildEducationInc/webpacker_ssr-execjs, https://github.com/GuildEducationInc/webpacker_ssr-react Need to write docs still (hoping today or tomorrow). We just deployed the changes into production yesterday. |
@wingrunr21 I am trying to test, but have hard time setting it up. |
Here my findings: # config/initializers/webpacker_ssr.rb
require 'webpacker_ssr'
require 'webpacker_ssr/execjs'
require 'webpacker_ssr/react'
WebpackerSSR.configure do |config|
config.server_bundle = 'server_bundle.js'
config.server_manifest = 'manifest.json'
config.renderer = :execjs
end When assets are precompiled ( import React from 'react';
import ReactDOMServer from 'react-dom/server'; When using Also when using the module WebpackerSSR
class VendorBundle < ServerBundle
def self.read(file_name)
manifest = ServerManifest.new
asset_path = manifest.lookup(file_name).to_s
Webpacker.dev_server.running? ? load_from_dev_server(asset_path) : load_from_file(asset_path)
end
end
end
module WebpackerSSR
module React
module Plugins
class Vendor < Plugin
self.priority = -1
def set_up_js_variables(_input)
VendorBundle.read('manifest.js')
end
end
end
end
end
WebpackerSSR::React.register_plugin(:vendor, WebpackerSSR::React::Plugins::Vendor)
WebpackerSSR::React.config.default_plugins = %i[vendor react] Help would be appreciated. |
Hi all, Really sorry. We are in the middle of multiple large client launches right now and my time is being monopolized in support of those. In the mean time: Gemfile: gem 'webpacker', '~> 3.2.0'
gem 'webpacker-react', '~> 0.3.1'
gem 'webpacker_ssr', '~> 1.0.0.alpha.1', github: 'GuildEducationInc/webpacker_ssr'
gem 'webpacker_ssr-execjs', '~> 1.0.0.alpha.1', github: 'GuildEducationInc/webpacker_ssr-execjs'
gem 'webpacker_ssr-react', '~> 1.0.0.alpha.1', github: 'GuildEducationInc/webpacker_ssr-react'
WebpackerSSR.configure do |config|
config.renderer = :execjs
config.server_bundle = 'server_side_render'
config.server_manifest = 'server-manifest.json'
config.react.default_plugins = [:react]
end
const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')
const { Environment } = require('@rails/webpacker')
// Webpacker screws around with the exports so this needs to be redefined
const postcssConfigPath = path.resolve(process.cwd(), '.postcssrc.yml')
const isProduction = process.env.NODE_ENV === 'production'
const extractOptions = {
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { minimize: isProduction } },
{ loader: 'postcss-loader', options: { sourceMap: true, config: { path: postcssConfigPath } } },
'resolve-url-loader',
{ loader: 'sass-loader', options: { sourceMap: true } }
]
}
const extractCSSLoader = {
test: /\.(scss|sass|css)$/i,
use: ExtractTextPlugin.extract(extractOptions)
}
class ServerEnvironment extends Environment {
constructor() {
super()
// Fix so HMR can be used at the same time
this.loaders.set('style', extractCSSLoader)
// Override server manifest
const manifestPlugin = this.plugins.get('Manifest')
manifestPlugin.opts.fileName = 'server-manifest.json'
this.plugins.set('Manifest', manifestPlugin)
}
toWebpackConfig() {
const result = super.toWebpackConfig()
const serverSideEntry = result.entry['server_side_render']
result.devtool = undefined
result.output.libraryTarget = 'this'
result.entry = () => {
return {'server_side_render': serverSideEntry }
}
return result
}
}
const environment = new ServerEnvironment()
module.exports = environment
const environment = require('./environment')
const serverEnvironment = require('./server')
const config = environment.toWebpackConfig()
delete config.entry['server_side_render']
const serverConfig = serverEnvironment.toWebpackConfig()
module.exports = [config, serverConfig]
const environment = require('./environment')
const serverEnvironment = require('./server')
const config = environment.toWebpackConfig()
config.devtool = 'hidden-source-map'
const serverConfig = serverEnvironment.toWebpackConfig()
module.exports = [config, serverConfig] We are running against webpacker 3.2.0 (apparently there are some issues with 3.2.2). |
Thanks, @wingrunr21, that's very helpful, I will give it a try! |
PS got it to work with no issues on webpacker 3.2.2 (although I do not use styled components). |
@wingrunr21 would be helpful if the three projects could be released as gems already – even if as alpha. |
kk. I want to get some tests in place first. Crossing my fingers that I can use some weekend time on these projects. |
Thanks. Once we get the base set up I can help with refining the edges. |
Hey all, So sorry. I have not forgotten about these projects. I'm blocking time this Friday to write documentation + make some additional improvements to the gems. Startup life... |
@wingrunr21 I know what you mean, barely have any time to work on react-rails anymore, moved company to a startup and there's no sponsored time anymore. Honestly good luck with this effort. |
@wingrunr21 thanks – let me know if I can help anyhow. I have been running the |
To anyone having issues, it took me a while to realize i needed to have a pack named
You must also use Fantastic work! |
Using ExecJS, we should be able (optionally) to run React on the server, render the content, and then re-hydrate the components in the browser.
The steps for this would be something like:
The text was updated successfully, but these errors were encountered: