JSPM

  • Created
  • Published
  • Downloads 1313
  • Score
    100M100P100Q114056F
  • License MIT

HTTP static file server for React Native

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

Latest NPM Release NPM Downloads GitHub Repo stars

Embed HTTP server for React Native applications.

Sponsor

Content

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:

  • 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:

  • 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 set minSdkVersion 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

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:

  • fileDirstring — The root path on target device from where static assets should be served. Relative paths (those not starting with /, neither file:///) will be automatically prepended by the document directory path; however, empty fileDir value is forbidden: if you really want to serve entire documents directory of the app, provide its absolute path explicitly.

  • nonLocalboolean — By default, the server is started on localhost 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.

  • portnumber — The port at which to start the server. If 0 (default) an available port will be automatically selected.

  • stopInBackgroundboolean — 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 matter stopInBackground 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 (in build.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 old root 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 old localOnly 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. Setting nonLocal 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 old keepAlive 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. Setting stopInBackground 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.