-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add a test project for subapp-redux, copied from poc-subapp * remove unneeded remote subapp settings * add option of enhancer for subapp-reux Redux createStore * add demo cases for subapp-redux Redux createStore enhancer * delete an unrelated file * refactor: make reduc enhancer name more self explanatory Co-authored-by: Wesley Ren <[email protected]>
- Loading branch information
Showing
47 changed files
with
2,998 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Browsers that we support | ||
last 2 versions | ||
ie >= 11 | ||
> 5% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
root = true | ||
|
||
[*] | ||
indent_style = space | ||
indent_size = 2 | ||
charset = utf-8 | ||
trim_trailing_whitespace = true | ||
insert_final_newline = true | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
var path = require("path"); | ||
var archetype = require("@xarc/app/config/archetype")(); | ||
var archetypeEslint = path.join(archetype.config.eslint, ".eslintrc-react"); | ||
|
||
function dotify(p) { | ||
return path.isAbsolute(p) ? p : "." + path.sep + p; | ||
} | ||
|
||
module.exports = { | ||
extends: dotify(path.relative(__dirname, archetypeEslint)) | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* text=auto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright 2018-present @WalmartLabs | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
# subapp poc sample | ||
|
||
## The Concept | ||
|
||
- What is a subapp? | ||
|
||
At its core, a subapp is just a component, and if React is used, a React component. | ||
|
||
The goal is to not limit subapps to a framework, but at the moment React is the primary focus. | ||
|
||
- What makes a subapp special? | ||
|
||
Electrode provide enhancements to make subapps special: | ||
|
||
- `Code splitting` - Automatically detect subapps and configure webpack to split your JS by subapps. | ||
- `Composable` - Create routes/pages that are composed of multiple subapps. | ||
- `Lazy loading` - Dynamically lazy load and create multiple instances of subapps on a page. | ||
- `Initial Props` - Automatically retrieve initial props before rendering subapps. | ||
- `Async data fetch` - Use React suspense to enable single pass async data fetch within components. | ||
- `Server Side Rendering` - Independently enable server side render for each subapp. | ||
- `Redux` - Automatically facilitate, initialize, and hydrate SSR data using Redux. | ||
- `React Router` - Automatically setup component routing using [react-router]. | ||
- `Hot module Reload` - Automatically support Hot Module Reload during development. | ||
|
||
## Introduction | ||
|
||
**How do I create a subapp?** | ||
|
||
- Electrode automatically look under the directory `src` for subapps. | ||
- To create a subapp, create a directory for it and an entry file with `subapp-` prefix, or just `subapp.js`. | ||
- Load your subapp with the `loadSubApp` API. | ||
|
||
- The simplest sample of a subapp: | ||
|
||
```js | ||
import React from "react"; | ||
import { loadSubApp } from "subapp-web"; | ||
|
||
const Home = () => <div>Home</div>; | ||
|
||
export default loadSubApp({ | ||
name: "Home", | ||
Component: Home | ||
}); | ||
``` | ||
|
||
And that's it! **TBD**: Electrode will detect your subapps and generate a route for each subapp base on its name. The `home` subapp will be used for the default route. | ||
|
||
## Flexible Server Routing | ||
|
||
To control server routes, you can create a `src/routes.js` file that specify the server routes. | ||
|
||
Example: | ||
|
||
```js | ||
export const favicon = "static/favicon.png"; | ||
|
||
export default { | ||
"/": { | ||
pageTitle: "Home", | ||
subApps: ["./home", "./demo1"] | ||
}, | ||
about: { | ||
pageTitle: "About us", | ||
subApps: ["./about"] | ||
} | ||
}; | ||
``` | ||
|
||
## Initial Props | ||
|
||
Your subapp can provide a `prepare` method that retrieves `props`. | ||
|
||
Example: | ||
|
||
```js | ||
import React from "react"; | ||
import { loadSubApp } from "subapp-web"; | ||
|
||
const Demo1 = props => <div>Demo1 props: {JSON.stringify(props)}</div>; | ||
|
||
export default loadSubApp({ | ||
name: "Demo1", | ||
Component: Home, | ||
prepare() { | ||
return fetch("/api/demo-data"); | ||
} | ||
}); | ||
``` | ||
|
||
## Server Side Rendering | ||
|
||
### Enable SSR for a subapp | ||
|
||
When you create an instance of a subapp, you can specify attributes for that instance. To enable SSR, set the `serverSideRendering` attribute. | ||
|
||
Example in `routes.js`: | ||
|
||
```js | ||
export const favicon = "static/favicon.png"; | ||
|
||
export default { | ||
"/": { | ||
pageTitle: "Home", | ||
subApps: [["./home", { serverSideRendering: true }], "./demo1"] | ||
}, | ||
about: { | ||
pageTitle: "About us", | ||
subApps: ["./about"] | ||
} | ||
}; | ||
``` | ||
|
||
### Server Side Data Fetching | ||
|
||
You can have data fetching that only runs on server side, and send that to the client for hydration if you use Redux. | ||
|
||
To enable server side only data fetching, create a file `server.js` under your subapp's directory, and have it exports a `prepare` method. | ||
|
||
Example: | ||
|
||
```js | ||
export default { | ||
prepare: ({ request, context }) => { | ||
return fetch("remote-service-url/api/data").then(result => { | ||
return { initialState: result }; | ||
}); | ||
} | ||
}; | ||
``` | ||
|
||
### Other SSR attributes | ||
|
||
You can also control how your subapp works from server side to client side for each instance. | ||
|
||
Some of the attributes supported: | ||
|
||
- `hydrate` - Enable client side hydration of initial state from server. ie: Use `React.hydrate` API. | ||
- `useStream` - Use the stream SSR APIs. ie: `ReactDomServer.renderToNodeStream`. | ||
- `suspenseSsr` - Support suspense in SSR. No stream support. | ||
|
||
## React Router and SPA | ||
|
||
In addition to the basic server routes, your subapps can have its own routing using [react-router]. | ||
|
||
To enable, set the `useReactRouter` flag when loading your subapp and wrap your component with a router. | ||
|
||
Example: | ||
|
||
```js | ||
import React from "react"; | ||
import { loadSubApp } from "subapp-web"; | ||
import { Router, Route, Switch } from "react-router-dom"; | ||
import { withRouter } from "react-router"; | ||
|
||
const Home = () => { | ||
return ( | ||
<div> | ||
<Navigation /> | ||
<Switch> | ||
<Route path="/" exact component={Main} {...props} /> | ||
<Route path="/products" component={About} {...props} /> | ||
<Route path="/contact" component={Contact} {...props} /> | ||
</Switch> | ||
</div> | ||
); | ||
}; | ||
|
||
export default loadSubApp({ | ||
name: "Home", | ||
Component: withRouter(Home), | ||
useReactRouter: true | ||
}); | ||
``` | ||
|
||
Electrode will automatically ensure your subapp is integrated with `StaticRouter` when doing SSR and `DynamicRouter` with `history` when running in the browser. | ||
|
||
**SPA** Further, you can have other subapps on the same page, and those will stay persistent while your subapp that is enabled with [react-router] will change. When loading each of the [react-router] routes, your page will be properly server side rendered. | ||
|
||
## Redux | ||
|
||
Electrode enables automatic integration with Redux for your subapps. To enable, add `redux` and `react-redux` to your dependencies, and use `reduxLoadSubApp` from the module `subapp-redux`, and provide reducers or `reduxCreateStore` for the subapp. | ||
|
||
Example: | ||
|
||
```js | ||
import React from "react"; | ||
import { reduxLoadSubApp } from "subapp-redux"; | ||
import { connect } from "react-redux"; | ||
import reducers from "./reducers"; | ||
|
||
const Home = props => <div>Home</div>; | ||
|
||
const mapStateToProps = state => state; | ||
|
||
export default reduxLoadSubApp({ | ||
name: "Home", | ||
Component: connect(mapStateToProps, dispatch => ({ dispatch }))(Home), | ||
reduxCreateStore(initialState) { | ||
return createStore(reducers, initialState); | ||
} | ||
}); | ||
``` | ||
|
||
## License | ||
|
||
Apache-2.0 © | ||
|
||
[react-router]: https://www.npmjs.com/package/react-router |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
options: { | ||
subapp: true | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"use strict"; | ||
module.exports = { | ||
extends: "@xarc/app-dev/config/babel/babelrc.js" | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"use strict"; | ||
|
||
const defaultListenPort = 3000; | ||
|
||
const portFromEnv = () => { | ||
const x = parseInt(process.env.APP_SERVER_PORT || process.env.PORT, 10); | ||
/* istanbul ignore next */ | ||
return x !== null && !isNaN(x) ? x : defaultListenPort; | ||
}; | ||
|
||
module.exports = { | ||
plugins: { | ||
"@xarc/app-dev": { | ||
enable: process.env.WEBPACK_DEV === "true" | ||
}, | ||
"subapp-server": { options: { insertTokenIds: true } } | ||
}, | ||
connections: { | ||
default: { | ||
host: process.env.HOST, | ||
address: process.env.HOST_IP || "0.0.0.0", | ||
port: portFromEnv(), | ||
routes: { | ||
cors: false | ||
}, | ||
state: { | ||
ignoreErrors: true | ||
} | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module.exports = { | ||
plugins: { | ||
"subapp-server": { | ||
options: { | ||
insertTokenIds: false, | ||
cdn: { enable: true } | ||
} | ||
} | ||
} | ||
}; |
Oops, something went wrong.