- Notifications
You must be signed in to change notification settings - Fork16
SSR - Router with SSR for Node & Meteor
License
ssrwpo/ssr
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Server side rendering with Express, react-router-4 & redux for Meteor.
You can replace yarn by your favorite way of installing NPM packages.
To install yarn :https://yarnpkg.com/en/docs/install
To install "meteor yarn" :meteor npm i -g yarn
meteor yarn add react prop-types react-dom react-router-dom express helmet \ html-minifier react-helmet pino receptacle useragent redux react-redux moment \ i18next i18next-node-remote-backend i18next-xhr-backend react-i18next \ i18next-express-middleware serialize-javascript lodash actual is-retinameteor add ssrwpo:ssrgit clone https://github.com/ssrwpo/ssr.git && cd ssrmeteor yarn installcd demometeor yarn install# For launching the demo in development modeyarn dev# For launching the demo in production modeyarn prod# For launching the demo with ios in simulator modeyarn ios# For launching the demo with android in simulator modeyarn androidimport{createRouter,logger}from'meteor/ssrwpo:ssr';...createRouter({// Your MainApp as the top component that will get rendered in <div id='react' /> MainApp,// Optional: Store subscription storeSubscription,// Optional: An object containing your application reducers appReducers,// Optional: An array of your redux middleware of choice appMiddlewares,// Optional: An array of your collection names appCursorNames,// Optional: Add a redux store that watches for URL changeshasUrlStore:false,// Optional: An i18n config for client side i18n,// Optional: Server uses a platform transformer, client must load optional reducers hasPlatformTransformer=true,}).then(()=>logger.info('Router started'));
import{createRouter,logger}from'meteor/ssrwpo:ssr';...createRouter({// Your MainApp as the top component rendered and injected in the HTML payload MainApp,// Optional: Store subscription storeSubscription,// Optional: An object containing your application reducers appReducers,// Optional: An object containing the cursors required as data context appCursors,// Optional: A function that returns the content of your robots.txt robotsTxt,// Optional: A function that returns the content of your sitemap.xml sitemapXml,// Optional: A function that return the content of you humans.txt humansTxt,// Optional: An object with keys on URL with query parameters urlQueryParameters,// Optional: An object with keys on route solver webhooks,// Optional: An i18n config for server side i18n,});logger.info('Router started');
By default this package logs for this package a muted. You can add asymetriclogging using an universal logger likepinousing thelogger.set method. The logger requires the following methods:debug,info,warn &error which are used within this package.
We use i18next for server side rendered localization. It gets the user browser language and serves the right language with a default one(in case you don't serve for users one).
You can find more about :
Do not need it seeFAQ how to remove fromdemo app.
react-router will always render your application. For identifying a404, youhave to tell to the server that while rendering the app, one of the displayedcomponent is due to a404. This is achieved via thereact-router'sstaticContextand by setting into it ahas404 boolean used by the server to identify the routeas404 Not found route.
Example:NotFound
To set up yourrobots.txt, you need to have a keyrobotsTxt inside the objectthat you pass to the server-side createRouter function. This key should containa function that returns a string with the desired content of yourrobots.txt.The function receives the store as its first arguments. This allows you toprogrammatically build yourrobots.txt based on the store contents.
The same principle applies tohumans.txt andsitemap.xml,with the keyhumansTxt andsitemapXml respectively.
For example, you can populate your sitemap.xml of dynamic routes generated basedon the store data. You can see examples of building these functions here:
NOTE For
sitemap.xmlwe strongly recommendsitemap.js.
By passing a webhooks function, you can build your own server side routes poweredby Express. A small example is setup in the demo:webhooks.
For the initial render, your app may require some defaults to ensure thatit will server retina images or specific layout for a platform.
Theplatform detection reducer provides the following platforms:
android: Any tablet or phone with Android using Chrome or the built-in browser.ipad: Any Apple iPad.iphone: Any Apple iPhone.safari: Any MacOS Safari (not iPhone or iPad).ie: Any Internet Explorer before Edge.default: All the other browsers and devices.
By default, aplatformTransformers is provided and adds 4 built-in reducers tothe app:retina,mobile,viewportWidth,viewportHeight. It only appliesto server side rendering. When your client side app is rendered, you can patchthe default values that the server has injected with a bult-in component:
<BrowserStats retinaMinDpi={<number>} mobileBreakpoint={<number>} debounceTimer={<number>} />where :
retinaMinDpi: 144, by default (1.5 x 96 in dpi).mobileBreakpoint: 992, by default (in px).debounceTimer: 64, by default (4 x 16 in ms).
If you want to build your ownplatformTransformers and<BrowserStats />, pleaserefer to the following sources for inspiration:
Each produced HTML payload is tagged with a build date allowing capabilitiesto check if a reload is required. The reducer is namedbuildDate and itcontains a UNIX date.
Store creation (seeReducer):
- Collections store:
createCollectionReducers - Value store:
createValueReducer
Actions on reducers:
- On collection store:
collectionAddcollectionChangecollectionRemove
- On value store:
valueSetvalueReset
When your collection is serialized in the store, you may want to synchronize itwhen your application starts, or when entering a page, or on a user action ...As this is a common use case for Meteor, we provide an easy way to createmapDispatchToProps methods for subscribing/subscribing or calling a validatedmethod that will synchronize your collection store.
Example:PubSub
The subscribe / unsubscribe based synchronization helper has the following API:
/** * `createHandleSubscribe` * Create an `handleSubscribe` function for your `mapDispatchToProps`. *@param dispatch Store's dispatch. *@param publicationName Your publication name which must accept an UNIX date value as `lastMod`. *@param cursor A cursor on Mongo collection with a `lastMod` set on each item. *@param valueStoreNameForSubscription Name of the value store identifying subscription state. *@param collectionStoreName Name of the collection store holding replica of collection. *@return A function allowing to subscribe and unsubscribe. */
The validated method based synchronization helper has the following API:
/** * `createHandleSyncViaMethod` * Create an `handleSyncViaMethod` function for your `mapDispatchToProps`. *@param dispatch Store's dispatch. *@param validatedMethod A validated method, promised based * (see didericis:callpromise-mixin) that accepts { lastMod } as its params. *@param collectionStoreName Name of the collection store holding replica of collection. *@return A function allowing to subscribe and unsubscribe. */
This package provides some HOC for common cases scenarios all geared torwardsperformances.
Asymetric HOC for transforming a functional component into aReact.PureComponent on the client and leaving it unmodified on the server.
importReactfrom'react';import{pure}from'meteor/ssrwpo:ssr';constMyComponent=(props)=>( ...);exportdefaultpure(MyComponent);
Example:Performance
Same aspure apart that it takes one or two component:
- When 2 components are used, the first one is rendered client side only, thesecond server side only. This allows changes of behavior while the app isloading, like for displaying a spinner or forbidding access to some functions.
- When one component is used, the server will not render the component(the no SSR case) which only shows up on the client when React is started.
importReactfrom'react';import{asymetricSsr}from'meteor/ssrwpo:ssr';...constLoading=()=><p>Loading</p>;constLoaded=()=><p>Loaded</p>;...constLoadingStateWithServerDisplay=asymetricSsr(Loaded,Loading);constLoadingStateWithout=asymetricSsr(Loaded);...
Example:Asymetric SSR
For optimal results, set your.babelrc with the following content:
{"presets": ["meteor"],"plugins": ["transform-class-properties","transform-react-constant-elements","transform-react-inline-elements","transform-react-remove-prop-types" ]}
⚠️ On Windows OS, these transforms could mess with your build process.A reduced set should be used with carefully chosen transforms. One contributorssucceed to make the demo working on Windows using the following.babelrc:
{"presets": ["meteor"],"plugins": ["transform-class-properties" ]}For profiling the most appropriate libraries or function call a benchmark suiteis setup inbenchmarks. Launch a test usingbabel-node.
Ex.babel-node benchmarks/getFromObject.js
The last request and last response received in Express are exposes by thispackage asdebugLastRequest anddebugLastResponse, respectively. In Meteor'sshell, you can access them via:
import{debugLastRequest,debugLastResponse}from'meteor/ssrwpo:ssr';
This project usesJest andchai.
# In one-shot mode:yarn test# In watch mode:yarn test.watchThe linter is based onESlint configured withAirbnb styles.
yarn lintLogo created byAlexandre Tabbuso.
- Application router: react-router-4
- Egghead's React router 4 - videos tutorials
- Universal logging: pino
- Protocol: Robots.txt
- Protocol: Sitemaps
- Protocol: Humans.txt
- Server side security: helmet
- Server side performance profiling: benchmark
- In memory LRU cache: receptacle
- Server side component caching: electrode-react-ssr-caching
- User agent parser: useragent
- Meteor issue on Hot code push
- Discussions about Hot code push issue
- Unit tests: Jest
- Unit tests: chai
- Reactjs - Speed up Server Side Rendering - Sasha Aickin
- Hastening React SSR with Component Memoization and Templatization
- Server-Side Rendering: Live Code Session - Supercharged (with info on cache control)
- AppCache
- Caching best practices & max-age gotchas
- Increasing Application Performance with HTTP Cache Headers
- Progressive Web Apps With React
- Discussion on main thread at client side initial rendering
About
SSR - Router with SSR for Node & Meteor
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors5
Uh oh!
There was an error while loading.Please reload this page.
