electrode-archetype-react-app
v7.0.7
Published
Electrode NodeJS/React Universal Application Archetype
Downloads
629
Readme
Archetype: Electrode React ~~Isomorphic~~ Universal App
A Walmart Labs flavored React Universal App archetype.
Have a question? Check the FAQ
Installation
NOTE: Generally you don't need to install these modules directly. You should start your app by using our Yeoman generator-electrode or check our Electrode getting started guide.
However, if you are manually creating your app:
Install the two complementary modules
$ npm install --save electrode-archetype-react-app
$ npm install --save-dev electrode-archetype-react-app-dev
Add a xclap.js
The xclap.js
should contain the following and be located in the root of your project
require("electrode-archetype-react-app")();
Usage
The primary interface to the archetype is a list of tasks you can invoke with clap to do your bidding.
To see the tasks, simply run:
$ clap
To invoke a task, for example, the dev
task, run:
$ clap dev
Directory Structure
The archetype supports the src/lib directory structure. In this mode, you put your client
and server
code under the src
directory and the build
task will transpile them into the lib
directory during build time.
If you are not currently using this directory structure, please read the src/lib section for migration instructions
Opt-in features
Run time support API
For the things that should be initialized at your Node server's startup, they are all combined into a single API in the archetype as support.load
.
Here is how you can use it:
In your server/index.js
:
const support = require("electrode-archetype-react-app/support");
const electrodeServer = require("electrode-server");
const electrodeConfippet = require("electrode-confippet");
support.load()
.then(() => {
return electrodeServer(electrodeConfippet.config);
})
.catch((e) => {
console.log("Server start failed", e); // eslint-disable-line no-console
});
If you are using this API, then things like isomorphic support and React module optimization are handled for you.
It accepts a single options
object, with the following supported fields:
babelRegister
- Set tofalse
to disable loadingbabel-register
cssModuleHook
- Set tofalse
to disable loading [css-module-hook]- If this is an object, then it's used as
options
forcssModuleHook
- If this is an object, then it's used as
isomorphicExtendRequire
- Set tofalse
to disable loading isomorphic-loader support
src/lib Mode
In order to avoid requiring run time babel transpilation, this archetype supports a src/lib app mode. To use this, you need to put your client
and server
into a src
directory. The archetype's build
task will transpile those into the lib
directory.
The archetype
build
task will only overwritelib/client
andlib/server
. So you can put other normal code underlib
if you want.If you are migrating from the deprecated babel-register mode, then you should move your code to
src
directory. For the most part, there should be very little you need to change except if you have code that refers to those two directories explicitly from outside.
You will also need to use the Run time support API to initialize your server startup.
src
or lib
?
So where is your code being executed from? src
or lib
? Actually, it could be either, depending on NODE_ENV
.
If you need to refer to your client or server code from outside, you can use APP_SRC_DIR
environment variable to automatically refer to the directory where code is being executed from.
For UI code under src/client
or test/client
, webpack config sets src
as a root so you can refer to code in src/client
with "client/foo"
.
For example:
import Hello from "client/components/hello"
For code under src/server
, you can refer to client with "../client/foo"
.
development
In dev mode, your code will be executed from the src
directory. Your client code is transpiled and packed by webpack-dev-middleware
on the fly. Your node server is executed by babel-node
.
production
In prod mode, your client code is being loaded from the bundle packed by webpack. On server side, SSR will load client code from lib
and your node server being executed from the lib/server
directory. ie: NODE_ENV=production node lib/server/index.js
.babelrc
An independent .babelrc
file will be automatically generated for you in both src/client
and src/server
. The one for client is setup for React and the one for server is setup for the NodeJS version you are using.
APP_SRC_DIR
An env variable APP_SRC_DIR
is always set by the Run time support API to indicate where your code is running from. If your app config needs to refer to some code there, you can use this.
NOTE: The dir path set in $APP_SRC_DIR
will include the trailing /
automatically. ie: src/
or lib/
For example, to pass your server side React app entry to react-webapp:
{
"plugins": {
"electrode-react-webapp": {
"options": {
"pageTitle": "Getting Started",
"paths": {
"/{args*}": {
"view": "index",
"content": {
"module": "./{{env.APP_SRC_DIR}}/server/app" // Note the use of APP_SRC_DIR here
}
}
}
}
}
}
}
NPM Prune for production
Starting with version 9.4.0, the archetypes now fully support your application running without the development archetype. Make sure you install electrode-archetype-react-app
under your dependencies
and electrode-archetype-react-app-dev
under devDependencies
and you can run npm prune --production
on your app to clear devDependencies
. If you are using the electrode-build script in your build job, you can set the build parameter PRUNE_DEV_DEPENDENCIES
to true.
NOTE: if your app runs in production mode but rely on something else you've put under
devDependencies
then doingnpm prune --production
will still break your app.
Define client entry points
By default, the archetype uses client/app.js
or client/app.jsx
as a client entry point. Alternatively,
you can define multiple entry points for your application, so the Webpack will create bundles for each app
entry point. To do that, place entry.config.js
module into your app's client
directory:
Here is an example of entry.config.js
:
module.exports = {
"web": "./app-web.js",
"ios": "./app-ios.js",
"android": "./app-android.js"
};
NodeJS Server Required Runtime Support
If you don't use the support.load
API to get the runtime support needed for some of the features in your NodeJS server, then you need to initialize them manually during your server startup.
babel-core/register
If you are using the babel-register mode, then you need to load the babel-register
module.
If you don't have a build step for your server code, then you must transpile
on the fly using babel-register
. For performance reasons, we recommend
whitelisting the react
module to be transpiled as well, so that the
transform-node-env-inline
plugin gets applied to the React codebase:
require("babel-core/register")({
ignore: /node_modules\/(?!react\/)/
});
cssModuleHook
for isomorphic CSS modules
If you want to enable isomorphic css modules, the server needs to know how to import css files
and generate unique class names.
The archetype can handle this for you using the supports
module. In your server entry point:
var supports = require("electrode-archetype-react-app/supports");
supports.cssModuleHook();
Extending Webpack Configuration
The webpack config for your app is being generated by the archetype. While composing the webpack config, the archetype looks for the archetype/config
folder at the project root of your app.
In order to override or extend the webpack configuration you should create a file under archetype/config/webpack
.
Your directory structure should look like this:
archetype
└── config
└── webpack
└── webpack.config.js
Where webpack.config.js
is your extended or overriding webpack config, for example:
const BellOnBundlerErrorPlugin = require('bell-on-bundler-error-plugin');
const config = {
plugins: [
new BellOnBundlerErrorPlugin()
]
};
module.exports = config;
Built with :heart: by Team Electrode @WalmartLabs.