Package Exports
- @dr.pogodin/react-native-static-server
- @dr.pogodin/react-native-static-server/lib/commonjs/index.js
- @dr.pogodin/react-native-static-server/lib/module/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@dr.pogodin/react-native-static-server) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
React Native Static Server
Embed HTTP server for React Native applications.
Content
- Project History and Roadmap
- Documentation for Older Library Versions (v0.6, v0.5)
- Getting Started
- Reference
- Migration from Older Versions (v0.6, v0.5)
Project History and Roadmap
This project started as a fork of the original
react-native-static-server
library, abandoned by its creators.
It is published to NPM as
@dr.pogodin/react-native-static-server,
and it aims to provide a well-maintained embed HTTP server for React Native (RN)
applications.
These are notable versions of the library:
v0.7.0-alpha.1 — The aim for upcoming v0.7.0 release is to migrate from the currently used, and not actively maintained, native server implementations (GCDWebServer on iOS, and NanoHttpd on Android) to the same, actively maintained Lighttpd sever on both platforms (and Windows in perspective). See Issue #12 for details.
Also, library interface will be reworked in this version, with a bunch of breaking changes, and library documentation will be enhanced.
As of the latest alpha version, the status is:
- NOT READY FOR PUBLIC USE, prefer v0.6.0-alpha.8 or v0.5.5, described below.
- PoC migration to Lighttpd is completed for Android, both with RN's New Architecture (tested) and, presumably, RN's Old Architecture (not tested).
- iOS version is broken.
v0.6.0-alpha.8 — The aim for upcoming v0.6.0 release is to refactor the library to support RN's New Architecture, while keeping backward compatibility with RN's Old Architecture, and the original library API. Also, the codebase will be refactored to follow the standard RN library template.
As of the latest alpha version, the status is:
- The code refactoring is completed.
- The outcome is tested and works with RN's Old Architecture both on Android and iOS devices.
- The outcome is tested to work with RN's New Architecture on Android, when using RN@0.70.
- NOT YET TESTED with RN's New Architecture on iOS. Likely to need minor fixes there.
v0.5.5 — Almost exact close copy of the latest version of the original library, patched to work with React Native v0.67+, and with all dependencies updated (as of May 17, 2022).
Documentation for Older Library Versions (v0.6, v0.5)
See OLD-README.md
Usage Instructions
This is a very raw draft, it will be elaborated later.
Install the package
$ npm install --save @dr.pogodin/react-native-static-server
On Android in
build.gradle
file setminSdkVersion
to the value 28 or larger.TODO: To use with Expo some extra setup is needed, probably we'll document it later. Contributions to this piece of documentation are welcome!
Create and run server instance:
import Server from '@dr.pogodin/react-native-static-server'; // NOTE: In practice, you probably want to create and persitently keep // server instance within a RN component, presumably using useRef() hook, // so this example should be enhanced to demonstrate it. const server = new Server({ // See further in the docs how to statically bundle assets into the App, // alternatively assets to server might be created or downloaded during // the app's runtime. fileDir: '/path/to/static/assets/on/target/device', }); // As BEWARE note below says, you may have multiple Server instances around, // but you MUST NOT start more than one instance a time, i.e. before calling // .start() on an instance you MUST .stop() a previously started instance, // if any. server.start().then((origin) => { console.log(`Serving at URL ${url}`); });
BEWARE: With the current implementation of v0.7 versions no more than a single server instance can be active at time. Attempt to start a new server instance while another one is still active will result in the crash of that new instance.
Add files to serve into your app bundle (this is use-case and OS-dependable, should be explained into details).
- TODO: Bundling assets in Android
- TODO: Bundling assets in iOS
Reference
- STATES — Enumerates possible states of Server instance.
- Server — Represents a server instance.
- constructor() — Creates a new Server instance.
- .addStateListener() — Adds state listener to the server instance.
- .start() — Launches the server.
- .stop() — Stops the server.
- .fileDir — Holds absolute path to static assets on target device.
- .hostname — Holds the hostname used by server.
- .nonLocal — Holds
nonLocal
value provided to constructor(). - .origin — Holds server origin.
- .port — Holds the port used by server.
- .state — Holds the current server state.
- .stopInBackground — Holds
stopInBackground
value provided to constructor().
STATES
import {STATES} from '@dr.pogodin/react-native-static-server';
The STATES enumerator provides possible states of a server instance:
STATES.ACTIVE
— The server instance is up and running;STATES.CRASHED
— The server instance has crashed and is inactive;STATES.INACTIVE
— The server instance is shut down;STATES.STARTING
— The server instance is starting up;STATES.STOPPING
— The server instance is shutting down.
Upon creation, a new server instance is in INACTIVE
state. Calling .start()
will immediately move it to STARTING
state, and then to ACTIVE
state once
the server is fully initiated in the native layer and is ready to handle
requests.
When .stop() is called on ACTIVE
server, or app enters background when
a server created with stopInBackground
option is ACTIVE
, the server moves
to STOPPING
state, and it becomes INACTIVE
once it is confirmed to fully
stop within the native layer. The server automatically stopped because of
stopInBackground
option will automatically restart once the app enters
foreground, and state changes will be the same as for its regular .start()
sequence described above.
It is legit to call .stop() on INACTIVE
server — if server was stopped
due to stopInBackground
option and intends to automatically restart once
the app is in foreground, calling .stop() will cancel such restart, and
ensure that only explicit call to .start() will launch this server again.
If any error at any time happens to server, either within native, or Java,
or JavaScript layers, the server instance will terminate and move to CRASHED
state. You may try to restart such instance calling .start() and if succeed,
the state changes will follow the regular start sequence.
Server
import Server from '@dr.pogodin/react-native-static-server';
The Server class instances represent individual server instances.
BEWARE: As of the current (v0.7+) library implementations at most one server instance can be active at time. Attempts to start a new server instance will result in crash of that new instance. That means, although you may have multiple instance of Server class created, you should not call an instance .start() method unless all other server instances are stopped.
constructor()
const server = new Server(options: object);
Creates a new, inactive server instance. The following settings are supported
within options
argument:
fileDir
— string — The root path on target device from where static assets should be served. Relative paths (those not starting with/
, neitherfile:///
) will be automatically prepended by the document directory path; however, emptyfileDir
value is forbidden: if you really want to serve entire documents directory of the app, provide its absolute path explicitly.nonLocal
— boolean — By default, the server is started onlocalhost
address, and it is only accessible within the app. With this flag set true the server will be started on a local IP adress also accessible from outside the app.port
— number — The port at which to start the server. If 0 (default) an available port will be automatically selected.stopInBackground
— boolean — By default, server intents to keep working as usual when app enters background / returns to foreground. Setting this flag true will cause an active server to automatically stop each time the app transitions to background, and then automatically restart once the app re-enters foreground. Note that calling .stop() explicitly will stop the server for good — no matterstopInBackground
value, once .stop() is called the server won't restart automatically unless you explicitly .start() it again.
.addStateListener()
server.addStateListener(listener: callback): function;
Adds given state listener to the server instance. The listener will be called each time the server state changes with a single argument passed in, the new state, which will be one of STATES values.
This method also returns "unsubscribe" function, call it to remove added listener from the server instance.
.start()
server.start(): Promise<string>
Launches Server instance. It returns a Promise, which resolves to the server origin once the server is ready to handle requests (the origin is the URL at which the server is bound, e.g. "http://localhost:3000"). See STATES documentation for details of possible server states and transitions between them.
.stop()
server.stop(): Promise<>
Shuts down the Server.
NOTE: When server was created with pauseInBackground
option (default),
calling .stop()
also ensures that the stopped server won't be restarted
when the app re-enters foreground. Once stopped, the server only can be
re-launched by explicity call to .start().
.fileDir
server.fileDir: string;
Readonly property, it holds fileDir
value — the absolute path
on target device from which static assets are served by the server.
.hostname
server.hostname: string;
Readonly property, it holds hostname used by the server. If server instance
was constructed without nonLocal
option (default), the .hostname
property
will equal "localhost
" from the beginning. Otherwise, it will be empty string
till the first launch of server instance, after which it will be equal to IP
address automatically selected for the server. This IP address won't change
upon subsequent re-starts of the server.
.nonLocal
server.nonLocal: boolean;
Readonly property, it holds nonLocal
value provided to server
constructor().
.origin
server.origin: string;
Readonly property, it holds server origin. Initially it equals empty string,
and after the first launch of server instance it becomes equal to its origin,
i.e. "http://HOSTNAME:PORT
", where HOSTNAME
and PORT
are selected hostname
and port, also accessible via .hostname and .port properties.
.port
server.port: number;
Readonly property, it holds the port used by the server. Initially it equals
the port
value provided to constructor(), or 0 (default value), if it was
not provided. If it is 0, it will change to the automatically selected port
number once the server is started the first time. The selected port number
does not change upon subsequent re-starts of the server.
.state
server.state: STATES;
Readonly property, it holds current server state, which is one of STATES values.
.stopInBackground
server.stopInBackground: boolean;
Readonly property, it holds stopInBackground
value provided to
constructor().
Migration from Older Versions (v0.6, v0.5)
On Android it now requires
minSdkVersion
to be set in equal 28 or larger (inbuild.gradle
file). Also, now it is not supported to start more than one server instance a time (previously started server instance, if any, must be stopped before starting another one).Server's constructor() signature was changed, as well as default behavior:
- constructor() now accepts a single required argument: an object holding all available server options:
fileDir
option replaces oldroot
argument, and now it MUST BE a non-empty string (to prevent any mistakes due to wrong assumptions what folder is served by default).nonLocal
option replaces the oldlocalOnly
option, with the opposite meaning and default behavior. Now, by default the server is started on "localhost
" and is only accessible from within the app. SettingnonLocal
flag will start it on an automatically assigned IP, accessible from outside the app as well. This is the opposite to behavior in previous versions, and it feels more secure (prevents exposing server outside the app due to overlooking the default behavior).stopInBackground
option replaces the oldkeepAlive
option, with the opposite meaning and behavior. Now, by default the server does not do anything special when the app goes into background / returns to foreground. SettingstopInBackground
true will cause automatic stop of the server each time the app enters background, with subsequent automatic server restart when the app returns to foreground. This is opposite to behavior in previous versions, and the rationale is: it is easy to handle the server without stopping in background (in this case there is no need to watch server state and synchronize possible requests with current server state), thus new default behavior allows for easier server usage, while the opt-in stopping of server in background allows more advanced usage scenario.
The new server implementation relies on app's temporary data folder to store some internal files (all within its
__rn-static-server__
subfolder), don't mess with it if you do anything special with the temporary folder.