GithubHelp home page GithubHelp logo

hypernova's Introduction

❗ Deprecation Notice
We want to express our sincere gratitude for your support and contributions to the Hypernova open source project. As we are no longer using this technology internally, we have come to the decision to archive the Hypernova repositories. While we won't be providing further updates or support, the existing code and resources will remain accessible for your reference. We encourage anyone interested to fork the repository and continue the project's legacy independently. Thank you for being a part of this journey and for your patience and understanding.

Hypernova

A service for server-side rendering your JavaScript views

Join the chat at https://gitter.im/airbnb/hypernova

NPM version Build Status Dependency Status

Why?

First and foremost, server-side rendering is a better user experience compared to just client-side rendering. The user gets the content faster, the webpage is more accessible when JS fails or is disabled, and search engines have an easier time indexing it.

Secondly, it provides a better developer experience. Writing the same markup twice both on the server in your preferred templating library and in JavaScript can be tedious and hard to maintain. Hypernova lets you write all of your view code in a single place without having to sacrifice the user’s experience.

How?

Diagram that visually explains how hypernova works

  1. A user requests a page on your server.
  2. Your server then gathers all the data it needs to render the page.
  3. Your server uses a Hypernova client to submit an HTTP request to a Hypernova server.
  4. Hypernova server computes all the views into an HTML string and sends them back to the client.
  5. Your server then sends down the markup plus the JavaScript to the browser.
  6. On the browser, JavaScript is used to progressively enhance the application and make it dynamic.

Terminology

  • hypernova/server - Service that accepts data via HTTP request and responds with HTML.
  • hypernova - The universal component that takes care of turning your view into the HTML structure it needs to server-render. On the browser it bootstraps the server-rendered markup and runs it.
  • hypernova-${client} - This can be something like hypernova-ruby or hypernova-node. It is the client which gives your application the superpower of querying Hypernova and understanding how to fallback to client-rendering in case there is a failure.

Get Started

First you’ll need to install a few packages: the server, the browser component, and the client. For development purposes it is recommended to install either alongside the code you wish to server-render or in the same application.

From here on out we’ll assume you’re using hypernova-ruby and React with hypernova-react.

Node

npm install hypernova --save

This package contains both the server and the client.

Next, lets configure the development server. To keep things simple we can put the configuration in your root folder, it can be named something like hypernova.js.

var hypernova = require('hypernova/server');

hypernova({
  devMode: true,

  getComponent(name) {
    if (name === 'MyComponent.js') {
      return require('./app/assets/javascripts/MyComponent.js');
    }
    return null;
  },

  port: 3030,
});

Only the getComponent function is required for Hypernova. All other configuration options are optional. Notes on getComponent can be found below.

We can run this server by starting it up with node.

node hypernova.js

If all goes well you should see a message that says "Connected". If there is an issue, a stack trace should appear in stderr.

Rails

If your server code is written in a language other than Ruby, then you can build your own client for Hypernova. A spec exists and details on how clients should function as well as fall-back in case of failure.

Add this line to your application’s Gemfile:

gem 'hypernova'

And then execute:

$ bundle

Or install it yourself as:

$ gem install hypernova

Now lets add support on the Rails side for Hypernova. First, we’ll need to create an initializer.

config/initializers/hypernova_initializer.rb

Hypernova.configure do |config|
  config.host = "localhost"
  config.port = 3030            # The port where the node service is listening
end

In your controller, you’ll need an :around_filter so you can opt into Hypernova rendering of view partials.

class SampleController < ApplicationController
  around_filter :hypernova_render_support
end

And then in your view we render_react_component.

<%= render_react_component('MyComponent.js', :name => 'Hypernova The Renderer') %>

JavaScript

Finally, lets set up MyComponent.js to be server-rendered. We will be using React to render.

const React = require('react');
const renderReact = require('hypernova-react').renderReact;

function MyComponent(props) {
  return <div>Hello, {props.name}!</div>;
}

module.exports = renderReact('MyComponent.js', MyComponent);

Visit the page and you should see your React component has been server-rendered. If you’d like to confirm, you can view the source of the page and look for data-hypernova-key. If you see a div filled with HTML then your component was server-rendered, if the div is empty then there was a problem and your component was client-rendered as a fall-back strategy.

If the div was empty, you can check stderr where you’re running the node service.

Debugging

The developer plugin for hypernova-ruby is useful for debugging issues with Hypernova and why it falls back to client-rendering. It’ll display a warning plus a stack trace on the page whenever a component fails to render server-side.

You can install the developer plugin in examples/simple/config/environments/development.rb

require 'hypernova'
require 'hypernova/plugins/development_mode_plugin'

Hypernova.add_plugin!(DevelopmentModePlugin.new)

You can also check the output of the server. The server outputs to stdout and stderr so if there is an error, check the process where you ran node hypernova.js and you should see the error.

Deploying

The recommended approach is running two separate servers, one that contains your server code and another that contains the Hypernova service. You’ll need to deploy the JavaScript code to the server that contains the Hypernova service as well.

Depending on how you have getComponent configured, you might need to restart your Hypernova service on every deploy. If getComponent caches any code then a restart is paramount so that Hypernova receives the new changes. Caching is recommended because it helps speed up the service.

FAQ

Isn’t sending an HTTP request slow?

There isn’t a lot of overhead or latency, especially if you keep the servers in close proximity to each other. It’s as fast as compiling many ERB templates and gives you the benefit of unifying your view code.

Why not an in-memory JS VM?

This is a valid option. If you’re looking for a siloed experience where the JS service is kept separate, then Hypernova is right for you. This approach also lends itself better to environments that don’t already have a JS VM available.

What if the server blows up?

If something bad happens while Hypernova is attempting to server-render your components it’ll default to failure mode where your page will be client-rendered instead. While this is a comfortable safety net, the goal is to server-render every request.

Pitfalls

These are pitfalls of server-rendering JavaScript code and are not specific to Hypernova.

  • You’ll want to do any DOM-related manipulations in componentDidMount. componentDidMount runs on the browser but not the server, which means it’s safe to put DOM logic in there. Putting logic outside of the component, in the constructor, or in componentWillMount will cause the code to fail since the DOM isn’t present on the server.

  • It is recommended that you run your code in a VM sandbox so that requests get a fresh new JavaScript environment. In the event that you decide not to use a VM, you should be aware that singleton patterns and globals run the risk of leaking memory and/or leaking data between requests. If you use createGetComponent you’ll get VM by default.

Clients

See clients.md

Browser

The included browser package is a barebones helper which renders markup on the server and then loads it on the browser.

List of compatible browser packages:

Server

Starting up a Hypernova server

const hypernova = require('hypernova/server');

hypernova({
  getComponent: require,
});

Options, and their defaults

{
  // the limit at which body parser will throw
  bodyParser: {
    limit: 1024 * 1000,
  },
  // runs on a single process
  devMode: false,
  // how components will be retrieved,
  getComponent: undefined,
  // if not overridden, default will return the number of reported cpus  - 1
  getCPUs: undefined,
  // the host the app will bind to
  host: '0.0.0.0',
  // configure the default winston logger
  logger: {},
  // logger instance to use instead of the default winston logger
  loggerInstance: undefined,
  // the port the app will start on
  port: 8080,
  // default endpoint path
  endpoint: '/batch',
  // whether jobs in a batch are processed concurrently
  processJobsConcurrently: true,
  // arguments for server.listen, by default set to the configured [port, host]
  listenArgs: null,
  // default function to create an express app
  createApplication: () => express()
}

getComponent

This lets you provide your own implementation on how components are retrieved.

The most common use-case would be to use a VM to keep each module sandboxed between requests. You can use createGetComponent from Hypernova to retrieve a getComponent function that does this.

createGetComponent receives an Object whose keys are the component’s registered name and the value is the absolute path to the component.

const path = require('path');

hypernova({
  getComponent: createGetComponent({
    MyComponent: path.resolve(path.join('app', 'assets', 'javascripts', 'MyComponent.js')),
  }),
});

The simplest getComponent would be to use require. One drawback here is that your components would be cached between requests and thus could leak memory and/or data. Another drawback is that the files would have to exist relative to where this require is being used.

hypernova({
  getComponent: require,
});

You can also fetch components asynchronously if you wish, and/or cache them. Just return a Promise from getComponent.

hypernova({
  getComponent(name) {
    return promiseFetch('https://MyComponent');
  },
});

getCPUs

This lets you specify the number of cores Hypernova will run workers on. Receives an argument containing the number of cores as reported by the OS.

If this method is not overridden, or if a falsy value is passed, the default method will return the number of reported cores minus 1.

loggerInstance

This lets you provide your own implementation of a logger as long as it has a log() method.

const winston = require('winston');
const options = {};

hypernova({
  loggerInstance: new winston.Logger({
        transports: [
          new winston.transports.Console(options),
        ],
      }),
});

processJobsConcurrently

This determines whether jobs in a batch are processed concurrently or serially. Serial execution is preferable if you use a renderer that is CPU bound and your plugins do not perform IO in the per job hooks.

createApplication

This lets you provide your own function that creates an express app. You are able to add your own express stuff like more routes, middlewares, etc. Notice that you must pass a function that returns an express app without calling the listen method!

const express = require('express');
const yourOwnAwesomeMiddleware = require('custom-middleware');

hypernova({
  createApplication: function() {
    const app = express();
    app.use(yourOwnAwesomeMiddleware);

    app.get('/health', function(req, res) {
      return res.status(200).send('OK');
    });

    // this is mandatory.
    return app;
  }

API

Browser

load

type DeserializedData = { [x: string]: any };
type ServerRenderedPair = { node: HTMLElement, data: DeserializedData };

function load(name: string): Array<ServerRenderedPair> {}

Looks up the server-rendered DOM markup and its corresponding script JSON payload and returns it.

serialize

type DeserializedData = { [x: string]: any };

function serialize(name: string, html: string, data: DeserializedData): string {}

Generates the markup that the browser will need to bootstrap your view on the browser.

toScript

type DeserializedData = { [x: string]: any };
type Attributes = { [x: string]: string };

function toScript(attrs: Attributes, props: DeserializedData): string {}

An interface that allows you to create extra script tags for loading more data on the browser.

fromScript

type DeserializedData = { [x: string]: any };
type Attributes = { [x: string]: string };

function fromScript(attrs: Attributes): DeserializedData {}

The inverse of toScript, this function runs on the browser and attempts to find and JSON.parse the contents of the server generated script. attrs is an object where the key will be a data-key to be placed on the element, and the value is the data attribute's value.

The serialize function uses the attributes DATA_KEY and DATA_ID to generate the data markup. They can be used in the fromScript function to get the serialized data.

import { DATA_KEY, DATA_ID } from 'hypernova'

fromScript({
    [DATA_KEY]: key,
    [DATA_ID]: id,
 });

Server

type Files = { [key: string]: string };
type VMOptions = { cacheSize: number, environment?: () => any };
type GetComponent = (name: string) => any;

function createGetComponent(files: Files, vmOptions: VMOptions): GetComponent {}

Creates a getComponent function which can then be passed into Hypernova so it knows how to retrieve your components. createGetComponent will create a VM so all your bundles can run independently from each other on each request so they don’t interfere with global state. Each component is also cached at startup in order to help speed up run time. The files Object key is the component’s name and its value is the absolute path to the component.

type VMOptions = { cacheSize: number, environment?: () => any };
type Run = (name: string, code: string) => any;
type VMContainer = { exportsCache: any, run: Run };

function createVM(options: VMOptions): VMContainer {}

Creates a VM using Node’s vm module. Calling run will run the provided code and return its module.exports. exportsCache is an instance of lru-cache.

function getFiles(fullPathStr: string): Array<{name: string, path: string}> {}

A utility function that allows you to retrieve all JS files recursively given an absolute path.

Module is a class that mimics Node’s module interface. It makes require relative to whatever directory it’s run against and makes sure that each JavaScript module runs in its own clean sandbox.

function loadModules(require: any, files: Array<string>): () => Module? {}

Loads all of the provided files into a Module that can be used as a parent Module inside a VM. This utility is useful when you need to pre-load a set of shims, shams, or JavaScript files that alter the runtime context. The require parameter is Node.js’ require function.

hypernova's People

Contributors

agudulin avatar alexindigo avatar brieb avatar duoertai avatar goatslacker avatar greenkeeper[bot] avatar inket avatar kale-io avatar kenju avatar ljharb avatar magicmark avatar marconi1992 avatar mindera-zecarlos avatar roippi avatar schleyfox avatar sebsonic2o avatar stoikerty avatar viatsko avatar wibron avatar yesmeck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hypernova's Issues

Clarification in README

Hi all! Thanks for this awesome project!

From the README:

  // the port the app will start on
  port: 8080,
  // whether or not to run in parallel using all available cpus
  endpoint: '/batch'
  // default endpoint path
}

What config option is "whether or not to run in parallel using all available cpus" referring to? It also looks like the 'default endpoint path' should be on that line instead.

Thanks!

Any plans for creating tests for the client spec?

I'm really excited about this project. Unfortunately I'm locked into a java platform so I'd have to write a client to be able to use it. I don't mind doing that on the surface of it, but it'd be extremely useful to have a general test suite for validating the clients against the spec. That would also make it easier to write other clients in other languages.

Do any such tests exist? If not, would that be something the team would be interested in helping support if someone started it?

window, document in component

What's the best way to server side render component that checks uses window and document which are only available in the browser?

npm install keeps failing on npm v6

npm install within the hypernova repo on npm@6 keeps failing.

Steps to reproduce

npm install

...
> [email protected] build /Users/leungwi/Projects/VRT/sporza/NODE/contrib/hypernova
> babel src -d lib

src/Module.js -> lib/Module.js
src/coordinator.js -> lib/coordinator.js
src/createGetComponent.js -> lib/createGetComponent.js
src/createVM.js -> lib/createVM.js
src/environment.js -> lib/environment.js
src/getFiles.js -> lib/getFiles.js
src/index.js -> lib/index.js
src/loadModules.js -> lib/loadModules.js
src/server.js -> lib/server.js
src/utils/BatchManager.js -> lib/utils/BatchManager.js
src/utils/lifecycle.js -> lib/utils/lifecycle.js
src/utils/logger.js -> lib/utils/logger.js
src/utils/renderBatch.js -> lib/utils/renderBatch.js
src/worker.js -> lib/worker.js
up to date in 3.952s
[!] 7 vulnerabilities found [3729 packages audited]
    Severity: 5 low | 2 critical
    Run `npm audit` for more detail

npm audit

npm ERR! code EAUDITNOLOCK
npm ERR! audit Neither npm-shrinkwrap.json nor package-lock.json found: Cannot audit a project without a lockfile
npm ERR! audit Try creating one first with: npm i --package-lock-only

npm i --package-lock-only installs all the packages but doesn't create a package-lock.json because the .npmrc has package-lock disabled.

An in-range update of eslint-plugin-import is breaking the build 🚨

Version 2.4.0 of eslint-plugin-import just got published.

Branch Build failing 🚨
Dependency eslint-plugin-import
Current Version 2.3.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As eslint-plugin-import is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Commits

The new version differs by 10 commits.

  • 44ca158 update utils changelog
  • a3728d7 bump eslint-module-utils to v2.1.0
  • 3e29169 bump v2.4.0
  • ea9c92c Merge pull request #737 from kevin940726/master
  • 8f9b403 fix typos, enforce type of array of strings in allow option
  • 95315e0 update CHANGELOG.md
  • 28e1623 eslint-module-utils: filePath in parserOptions (#840)
  • 2f690b4 update CI to build on Node 6+7 (#846)
  • 7d41745 write doc, add two more tests
  • dedfb11 add allow glob for rule no-unassigned-import, fix #671

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Hypernova with Rails API

Having a Rails API as backend, can I use Hypernova to render json data retrieved from the API and use that data for server side rendering? Is there any example showing how to use Rails API with Hypernova?

getComponent reject should return http response back to client

If I return a promise from getComponent, and I decide the name is not valid currently this is the response

 ®[test-hypernova]$ http POST localhost:3030/batch < test/assets/organism.json
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 0
Date: Thu, 16 Jun 2016 20:08:45 GMT
X-Powered-By: Express

for reference, the posted json looks like:

{
  "test" : {
    "name": "/usr/bin/evil",
    "data": {
      "name": "Ryan"
    }
  }
}

a section of my getComponent looks like

    getComponent(name) {
      return new Promise((resolve, reject) => {
        // make sure the name has no funny biz
        var parts = name.split('@')
        if (parts.length !== 2) return reject('Weird name passed to us')
        if (!validate(parts[0]).validForNewPackages) return reject('invalid package')

Can we make it so the rejected promise makes a 400 status code, and maybe a json response like:

{
    "error": null,
    "results": {
        "test": {
            "duration": 268.287959,
            "error":"invalid package",
            "meta": {},
            "name": "/usr/bin/evil",
            "statusCode": 400,
            "success": false
        }
    },
    "success": false
}

An in-range update of sinon is breaking the build 🚨

Version 4.0.2 of sinon was just published.

Branch Build failing 🚨
Dependency sinon
Current Version 4.0.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

sinon is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push The Travis CI build failed Details

Commits

The new version differs by 21 commits.

  • 39e5737 Update docs/changelog.md and set new release id in docs/_config.yml
  • c2bd7b1 Add release documentation for v4.0.2
  • da24e94 4.0.2
  • cea60e8 Update History.md and AUTHORS for new release
  • d4dcfca Document the stub.reset breaking change (#1590)
  • aab1917 Merge pull request #1596 from mroderick/fix-preversion-to-use-history.md
  • 5dbe685 Update 'nise' to latest version (#1593)
  • 578b9ea Update History.md and AUTHORS for new release
  • 499b698 Fix preversion.sh to stage History.md
  • 1e5fd0f Remove unneeded characters
  • 2a69d51 fix typo in contributing
  • 6cc71ec Document how to trigger progress events (#1585)
  • e49fcf1 Fix broken test-coverage task
  • 527086a Use supports-color module to test if system supports colors
  • 78782b4 Merge pull request #1580 from mroderick/dependency-hygeine

There are 21 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

makeValidDataAttribute error for clients without support for hypernova-id

I have an issue with makeValidDataAttribute expecting to always get only defined values.

When I run an application where the hypernova server fails and the hypernova client (hypernova-python in my case) does not include the hypernova-id data attribute the call-chain from load("Component") ends up running from_script with an object like {hypernova-key: "Component", hypernova-id: null}. When that then wants to normalize the attributes it fails on hypernova-id.

By reading the commit that added the functionality of multiple copies of the same component I thought supporting hypernova-id was optional?

Context
Code is transpiled with webpack 2 and babel-loader with presets es2015 and react.

Example html:

<div data-hypernova-key="Component"></div>
<script type="application/json" data-hypernova-key="Component">
        <!--{"someData": "here"}--></script>

Error-code:

Uncaught TypeError: Cannot read property 'replace' of null
  at makeValidDataAttribute

Caching?

Does Hypernova cache components and if so what is the cache key based on? I was looking through the code and it appears like there's some caching going on but only in createVM which doesn't appear to be used unless you're using createGetComponent. I'm not using createGetComponent because I'm just bundling all of my components into a single file and calling the corresponding component given the passed in name like:

getComponent(name) {
  return require('./app/assets/build/server-bundle.js')[name];
}

An in-range update of babel-preset-airbnb is breaking the build 🚨

Version 2.3.0 of babel-preset-airbnb just got published.

Branch Build failing 🚨
Dependency babel-preset-airbnb
Current Version 2.2.3
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-preset-airbnb is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Commits

The new version differs by 6 commits.

  • 9410812 Version 2.3.0
  • 98c9c1d Merge pull request #13 from airbnb/babel-preset-env
  • a3b73f6 Switches to use babel-preset-env
  • 13da4ee [Tests] npm v4.6+ doesn’t work on node < v1
  • 3065a5c [Deps] update babel-plugin-syntax-trailing-function-commas, babel-plugin-transform-es2015-template-literals, babel-plugin-transform-es3-member-expression-literals, babel-plugin-transform-es3-property-literals, babel-plugin-transform-exponentiation-operator, babel-plugin-transform-jscript, babel-plugin-transform-object-rest-spread, babel-preset-es2015, babel-preset-react
  • bd811d3 [Dev Deps] update eslint, eslint-config-airbnb-base, eslint-plugin-import

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of eslint is breaking the build 🚨

Version 4.10.0 of eslint was just published.

Branch Build failing 🚨
Dependency eslint
Current Version 4.9.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

eslint is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes v4.10.0
  • bb6e60a Fix: Improve the doc for no-restricted-modules rule (fixes #9437) (#9495) (vibss2397)
  • c529de9 Docs: Amend rule document to correct and complete it (refs #6251). (#9498) (Jonathan Pool)
  • f9c6673 Chore: Add tests to cover array and object values and leading commas. (#9502) (Jonathan Pool)
  • 9169258 Chore: remove npm run check-commit script (#9513) (Teddy Katz)
  • 7d390b2 Docs: Revise contributor documentation on issue labels. (#9469) (Jonathan Pool)
  • d80b9d0 Fix: no-var don't fix globals (fixes #9520) (#9525) (Toru Nagashima)
  • b8aa071 Fix: allow linting the empty string from stdin (fixes #9515) (#9517) (Teddy Katz)
  • 350a72c Chore: regex.test => string.startsWith (#9518) (薛定谔的猫)
  • de0bef4 Chore: remove obsolete eslintbot templates (#9512) (Teddy Katz)
  • 720b6d5 Docs: Update ISSUE_TEMPLATE.md (#9504) (薛定谔的猫)
  • 2fa64b7 Fix: should not convert non-consecutive line comments to a single blo… (#9475) (薛定谔的猫)
  • 9725146 Fix: multiline-comment-style fix produces invalid code (fixes #9461). (#9463) (薛定谔的猫)
  • b12cff8 Fix: Expected order of jsdoc tags (fixes #9412) (#9451) (Orlando Wenzinger)
  • f054ab5 Docs: add .md to link (for github users) (#9501) (薛定谔的猫)
  • 5ed9cfc Docs: Correct violations of “Variable Declarations” in Code Conventions (#9447) (Jonathan Pool)
  • 3171097 Docs: Clears confusion on usage of global and local plugins.(#9492) (Vasili Sviridov)
  • 3204773 Chore: enable max-len. (#9414) (薛定谔的猫)
  • 0f71fef Docs: Unquote booleans in lines-between-class-members docs (#9497) (Brandon Mills)
  • b3d7532 Docs: use consistent terminology & fix link etc. (#9490) (薛定谔的猫)
  • 87db8ae Docs: Fix broken links (#9488) (gpiress)
  • 51bdb2f Docs: Incorrect link to related rule (#9477) (Gavin King)
  • 1a962e8 Docs: Add FAQ for when ESLint cannot find plugin (#9467) (Kevin Partington)
  • 8768b2d Fix: multiline-comment-style autofixer added trailing space (#9454) (Teddy Katz)
  • e830aa1 Fix: multiline-comment-style reports block comments followed by code (#9450) (Teddy Katz)
  • b12e5fe Docs: Repair broken links and add migration links. (#9473) (Jonathan Pool)
  • eca01ed Docs: Add missing info about special status of home-dir config files. (#9472) (Jonathan Pool)
  • eb8cfb1 Fix: change err report in constant condition (fixes #9398) (#9436) (Victor Hom)
  • da77eb4 Chore: Revise no-config-file test to prevent false failure. (#9443) (Jonathan Pool)
  • 47e5f6f Docs: ensure "good commit message" examples actually follow guidelines (#9466) (Teddy Katz)
  • ebb530d Update: Don't ignore comments (no-trailing-spaces) (#9416) (Chris van Marle)
  • 5012661 Build: fix npm run profile script (fixes #9397) (#9455) (Teddy Katz)
  • ecac0fd Docs: Remove blockBindings references (#9446) (Jan Pilzer)
  • 0b89865 Chore: ensure tests for internal rules get run (#9453) (Teddy Katz)
  • 052c504 Docs: suggest deleting branches after merging PRs (#9449) (Teddy Katz)
  • b31e55a Chore: move internal rules out of lib/ (#9448) (Teddy Katz)
  • a7521e3 Docs: improve examples for multiline-comment-style (#9440) (Teddy Katz)
Commits

The new version differs by 38 commits.

  • 9deb1b1 4.10.0
  • 6d19001 Build: changelog update for 4.10.0
  • bb6e60a Fix: Improve the doc for no-restricted-modules rule (fixes #9437) (#9495)
  • c529de9 Docs: Amend rule document to correct and complete it (refs #6251). (#9498)
  • f9c6673 Chore: Add tests to cover array and object values and leading commas. (#9502)
  • 9169258 Chore: remove npm run check-commit script (#9513)
  • 7d390b2 Docs: Revise contributor documentation on issue labels. (#9469)
  • d80b9d0 Fix: no-var don't fix globals (fixes #9520) (#9525)
  • b8aa071 Fix: allow linting the empty string from stdin (fixes #9515) (#9517)
  • 350a72c Chore: regex.test => string.startsWith (#9518)
  • de0bef4 Chore: remove obsolete eslintbot templates (#9512)
  • 720b6d5 Docs: Update ISSUE_TEMPLATE.md (#9504)
  • 2fa64b7 Fix: should not convert non-consecutive line comments to a single blo… (#9475)
  • 9725146 Fix: multiline-comment-style fix produces invalid code (fixes #9461). (#9463)
  • b12cff8 Fix: Expected order of jsdoc tags (fixes #9412) (#9451)

There are 38 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Creating PHP Client

Hello,

I'm working on creating a php client for hypernova. One thing that I haven't been able to figure out is what url to post to for hypernova, and how the POST params should be set up. I'm running hypernova.js locally, and have tried POST'ing to http://localhost:3030/ but am getting 404s! When I POST to http://localhost:3030/batch I get this response (below), no matter what i put in the params, and getComponent is not being called.

{ "success": true, "error": null, "results": {} }

I would appreciate a little bit more information on what the POST url is and how POST params should be passed.

Thoughts on extending the API

Hi again!

Consider a scenario where inside of getComponent, we'd like to return a React component rendered with either with renderReact or renderReactStatic, depending on the context (eg legacy reasons).

My initial thought is that we could do something funky like define NameOfComponent and NameOfComponentStatic and pass such args though the component name.

What would be even better though is to be able to define custom args; something like

{
  "NameOfComponent": {
    "name": "NameOfComponent",
    "args": {
       "renderType": "static",
    },
    "data": {
      "theseAreProps": true,
      "someOtherProps": ["one", "two", "three"]
    },
  }
}

and args gets passed alongside name to getComponent.

Does this seem reasonable? Thanks!

An in-range update of babel-preset-airbnb is breaking the build 🚨

Version 2.2.2 of babel-preset-airbnb just got published.

Branch Build failing 🚨
Dependency babel-preset-airbnb
Current Version 2.2.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-preset-airbnb is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Commits

The new version differs by 5 commits .

  • 6b64fb6 Release v2.2.2
  • a31c8fd Merge pull request #7 from airbnb/reenable-native-modules
  • 794e12c Reenable native modules.
  • 995f598 [Tests] add npm test and travis-ci
  • 1e1cd80 [Dev Deps] add npm run lint

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Rendering Blank

Hey guys,

I might be just doing something wrong but when I implemented the hypernova setup, all I see is a blank screen. This is the current source code that is getting rendered. I'm using Ruby on Rails & React.

<div data-hypernova-key="indexjs" data-hypernova-id="4d2cf94b-7e2b-4bea-8cf7-24f94af855ef"></div> <script type="application/json" data-hypernova-key="indexjs" data-hypernova-id="4d2cf94b-7e2b-4bea-8cf7-24f94af855ef"><!--{"name":"Hypernova The Renderer"}--></script>

My index.erb.html has the following code:
<%= render_react_component('index.js', :name => 'Hypernova The Renderer') %>

The react app is leveraging Webpack and the React app is fully in the 'public' folder of my Rails app. I've tried it with the index.js and AppProvider.js file in the rails configuration.

Here's my index.js source code:


import React from 'react';
import ReactDOM from 'react-dom';
import AppProvider from './app_provider';

ReactDOM.render(<AppProvider />, document.querySelector('#app'));

and this is my app_provider.js

import {renderReact} from 'hypernova-react';
import { persistStore } from 'redux-persist';
import { Provider } from 'react-redux';
import Routes from './routing/routes';
import styles from './index.scss';
import globalStyles from './styles/font-face.css';
import { store } from './util/store.js';

import LoadingSpinner from './components/Loading/loading';

class AppProvider extends Component {
    constructor(){
        super();
        this.state = {
            rehydrated: false
        };
    }
    componentDidMount(){
        persistStore(store, { blacklist: ['pagination', 'notification', 'properties', 'blog', 'navigation', 'position', 'landing', 'tagbar', 'auction', 'rainworx'] }, () => {
            this.setState({rehydrated: true});
        })
    }
    render(){
        if(!this.state.rehydrated){
            return <LoadingSpinner />
        }
        return (
            <Provider store={store}>
                <Routes />
            </Provider>
        );
    }
}

export default renderReact('AppProvider.js', AppProvider);```

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! 🎊

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml
  • The new Node.js version is in-range for the engines in 1 of your package.json files, so that was left alone

If you’re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didn’t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didn’t touch job or matrix configurations because these tend to be quite specific and complex, and it’s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what you’re doing it may require additional work or may not be applicable at all. We’re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, I’m a humble robot and won’t feel rejected 🤖


FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

getComponent support function return a Promise

I am working on vue bindings for Hypernova, but vue-server-renderer renderer pass html by callback:

const Vue = require('vue')
 
const renderer = require('vue-server-renderer').createRenderer()
 
const vm = new Vue({
  render (h) {
    return h('div', 'hello')
  }
})

renderer.renderToString(vm, (err, html) => {
  console.log(html) // -> <div server-rendered="true">hello</div> 
})

So, I'd like getComponent support a function which return a Promise, just like props => Promise.resole(html).

ES6 - Unexpected token 'import'

So I'm trying out hypernova for a new project but I already have a lengthy app built in React.

The main issue right now is that it fails with the ES6 imports.

Does this work with ES6 or how should I proceed?

EDIT I get that I need to transpile my Js but now it says window is not defined

UPDATE 2 I removed the commonChunks optimization and I tried nodeExternals but with or without node externals it just says that MyComponentName.js is not registered. So I'm a bit stumped. don't know what to do.

The ENCODE array is changed in-place every time

function decode(res) {
  const jsonPayload = ENCODE.reverse().reduce((str, coding) => {
    ...
}

Array.prototype.reverse changes the array in place, is this desirable in this case? The second time load is called (and decode too as a result), ENCODE.reverse() should have the same value as ENCODE in the beginning, i.e.

> ENCODE = ['a', 'b']
["a", "b"]
> ENCODE.reverse()
["b", "a"]
> ENCODE.reverse()
["a", "b"]

Adding sourcemaps for coverage reports

html coverage reports currently show the compiled es5

Would be nice to either:

  1. Add sourcemaps to istanbul reports
  2. Switch to nyc and compile on the fly

(2 is maybe undesirable if you want the assurance of testing against the actual dist code. fwiw though, something like this patch does the trick.)

Hypernova ignoring props sometimes

I am sorry if the description of my issue is a big vague, but I am not really sure where to start when fixing that error.
I am testing hypernova with hypernova-ruby in a Rails 4.2 environment. Server-side rendering works very well most of the time. But sometimes it seems like there are no props passed to the component for rendering (in hypernova).
I already checked the context (in getComponent function) and the props are passed to the server, anyhow the resulting string is build with the default props.

Any idea where to start on this?

Guidance needed - how to store request context?

Hi @goatslacker!

So I have a logger set up inside an express middleware, logging various things about the request.

One bit of information I'd like to add to the logs is - did the request hit a cold cache or not?

I have access to this information inside of my application code - inside of getComponent. However there's no great way that I can currently think of to thread this information along to other parts of the express app.

I'm thinking one way to do this would be to expose the express request object to the context object passed into getComponent

obj[token] = {

Or maybe there's just a better way to architect this?

Thanks!

`createGetComponent` doesn't prevent leaking data between requests

As per documentation: The most common use-case would be to use a VM to keep each module sandboxed between requests. You can use createGetComponent from Hypernova to retrieve a getComponent function that does this.

I'm using createGetComponent to load following component:

import React from 'react';
import { renderReact } from 'hypernova-react';

let meme = 25;

function SimpleComponent({ name }) {
  return <div onClick={() => alert('Click handlers work.')}>Hello, {meme++}, {name}!</div>;
}

export default renderReact('SimpleComponent', SimpleComponent);

with following getComponent function

  getComponent: createGetComponent({
    SimpleComponent: path.resolve('build/components/SimpleComponent/index.js'),
    Counter: path.resolve('build/components/Counter/index.js')
  }),

And meme counter keeps ticking:

incrementing value

Does parsed body has a limitation?

Hey team, I really appreicate you guys open source hypernova. It's awesome and flexiable that make isomorphic so convenient.

But now I encounter some weird situation, I don't know if there is something I missed.
My application is trying to render lots of html tags with server, precisely, like 13k tags. When I limited the tags rendered by server under 400, it works as expected. And when I reset limitation to about 1.2k, I got some warning like below:

 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) ">1</span></a></li><li class="tag" data-
 (server) ">1</span></a></li></ul></div></div>

After that, I raise limitation again to like 4k and server-render does not work anymore. The application is still working with fallback.

It's really frustrated.

Would you guy consider large payload for hypernova server could be a problem?

btw, here is my hypernova.js

const hypernova = require('hypernova/server');
const createGetComponent = require('hypernova/server').createGetComponent;
const path = require('path');

hypernova({
  devMode: false,
  getComponent: createGetComponent({
    SearchTag: path.resolve('./app/assets/javascripts/isomorphic/searchTag/searchTag.js'),
  }),
  port: 3030,
});

thanks.

Document `onServer`?

I'm using onServer to be able to hook into express before the batch route is added, so I can do something like this: https://stackoverflow.com/a/21858212/4396258

(Context: we want to just restart workers if they consume too much memory, but specifically at the end of a request so we don't drop drop any requests)

It's either this or adding a workerShouldExit method as a config? What do you think? Can I safely use the onServer method, or is this subject to removal?

(Also on the subject of undocumented arguments - what about documenting context too? It's useful for collecting stats.)

@ljharb @goatslacker

Promise Error on Basic Use Case

Hi, I attempted to test hypernova without loading a component from a file like this (it handles JSX because I'm compiling server JS file w/ webpack):

import hypernova from 'hypernova/server'
import { renderReact } from 'hypernova-react'

const TestComponent = () => <div>Hello Hypernova</div>

hypernova({
  devMode: true,
  getComponent: function () {
    return renderReact('TestComponent', TestComponent)
  }
})

Then when I use this from Rails:

# view
# <%= render_react_component "Test" %>

# controller
around_action :hypernova_render_support

# initializer
if Rails.env.development?
  require "hypernova/plugins/development_mode_plugin"
  Hypernova.add_plugin!(DevelopmentModePlugin.new)
end

Hypernova.configure do |config|
  config.host = "localhost"
  config.port = 8080
end

I do see hypernova's div rendered, but the content is empty:

<div data-hypernova-key="Test" data-hypernova-id="59829cc1-7a43-4c1a-a63e-e59458fb4459"></div>

On the server, I get this error:

Warning: a promise was created in a handler but was not returned from it, see http://goo.gl/rRqMUw

I'm not sure how to go about debugging this. Any help would be much appreciated.

Open to adding the ability to restart workers

Hi y'all!

First off, thank you for a really great Github project. We use it here at RTR and its added a lot of rigor around the server-side rendering from our Ruby app.

Onto the issue. Would you be open to a PR which allows the hypernova master process to restart its workers after a specific number of requests. We currently have a job calling SIGTERM on the workers due to memory leaks resulting from our not using createGetComponent.

We have a lot of top level modules and so we opted to not go that route for now and are wondering what your opinion would be on allowing for a hybrid approach, similar to what unicorn-worker-killer does for Ruby.

Thanks again!

More detailed examples

Hey,

I found the example documentation to be sufficient to understand the concepts. However, implementation was not possible.

I am intending on using Hypernova with React-Router and/or Redux. And I'm wondering if my application structure will permit this.

Something such as:

//Render components
function App (props) {
  return (
    <Router history={browserHistory}>
      <Route path="/" component={Index}/>
      <Route path="*" component={NoMatch}/>
    </Router>
  )
}

export default renderReact('App.js', App)

Does not render when you hit the desired Port of Hypernova (using the hypernova/server package).

If it's possible. Writing more detailed documentation would be fabulous as the pros of Hypernova vastly outweight the cons in terms of implementation of traditional server side rendering with template literals.

An in-range update of babel-cli is breaking the build 🚨

Version 6.22.1 of babel-cli just got published.

Branch Build failing 🚨
Dependency babel-cli
Current Version 6.22.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-cli is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • continuous-integration/travis-ci/push The Travis CI build failed Details
Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Rails 5.1 Support

Does Hypernova support Rails 5.1? I have tried to setup server side rendering but my node server doesn't respond.

Response streaming

As of React 16 a new method renderToStream() method was introduced. I first though of creating a feature request issue at airbnb/hypernova-react but after taking a look at the code it seems that more ground-work needs to be done at the server itself to support streams in the first place.

@goatslacker mentioned in #22 that there are plans to support streams and even async rendering, it would be interesting if this was already started by anyone or if we could support you guys on this feature.

In the latter case it would be nice if we could collect all ideas/hints here on how to implement this feature correctly.

security issue?

I was looking through code and found that it's vulnerable to attacks when source code uses native node modules, such as fs.

const fs = require('fs');
const testFolder = './';

fs.readdir(testFolder, (err, files) => {
    files.forEach(file => {
          console.log(file);
            });
})

These native modules are still executed in runInContext of createVM.js.

[Module] `require` will be compiled to `__webpack_require__` by webpack

when I'm using webpack to bundle the project code into one file. I find the code require in src/module will be compiled into __webpack_require__. so that I can't load the native module from node in the vm context.

code in lib/Module.js

{
    key: 'loadFile',
    value: function () {
      function loadFile(file, parent) {
        var filename = _module2['default']._resolveFilename(file, parent);

        if (parent) {
          var cachedModule = parent.cache[filename];
          if (cachedModule) return cachedModule.exports;
        }

        if (isNativeModule(filename)) {
          // eslint-disable-next-line global-require
          return require(filename);
        }
}

my project code use createVM, some sample code like this:

import * as hypernova from 'hypernova/server'
const createVM = hypernova.createVM

const vm = createVM(Object.assign({}, {
  cacheSize: 100,
}, vmOptions))

vm.run(name, `my code here`)

As a result. the code in Module.js will be bundled by webpack like this

{
    key: 'loadFile',
        value: function () {
      function loadFile(file, parent) {
        var filename = _module2['default']._resolveFilename(file, parent);

        if (parent) {
          var cachedModule = parent.cache[filename];
          if (cachedModule) return cachedModule.exports;
        }

        if (isNativeModule(filename)) {
          // eslint-disable-next-line global-require
          return __webpack_require__(187)(filename);
        }
}

so that. if I require some native module in vm.run. It cannot resolved by webpack

if I change the code in the src/Module.js then build and bundle.The result workd well.

if (isNativeModule(filename)) {
  // eslint-disable-next-line global-requir
  return eval("require")(filename);
}

Any suggestion?

devMode does not reload the components / invalidate the require cache

I just tried out the hypernova stack and found that the devMode does not reload the component on each request as documented.

Example

hypernova.js

const hypernova = require('hypernova/server');

hypernova({
  devMode: true,
  port: 3030,
  getComponent: name => require(`./${name}.js`)
});

app.js

const React = require('react');
const {renderReact} = require('hypernova-react');

function App(props) {
  return React.createElement('div', null, `Hello ${props.name}`);
}

module.exports = renderReact('app', App);

server.js

const express = require('express');
const Renderer = require('hypernova-client');
const devModePlugin = require('hypernova-client/plugins/devModePlugin');

const app = express();

const renderer = new Renderer({
  url: 'http://localhost:3030/batch',
  plugins: [
    devModePlugin,
  ],
});

app.get('/', (req, res) => {
  const jobs = {
    app: { name: req.query.name || 'Stranger' }
  };

  renderer.render(jobs).then(html => res.send(html));
});

app.listen(8080, () => console.log('Now listening'));

What happens

When requesting localhost:8080 you will be greeted as configured by Hello Stranger but when changing the returned string of the App, e.g. into Hello foo bar ${props.name} the supernova server still renders the old cached component and returns Hello stranger again.

What should happen

When passing a truthy devMode option to hypernova, the server should invalidate the Node caches on each request.

I also searched for references of devMode in the server code, but haven't found anything except for the cluster setup.

Maybe I just missed something, but to me it seems this functionality isn't implemented or was removed in a recent commit?

fallback in case of hypernova server didn't respond

Hey all

<div id="root">{{ html }}</div>

If hypernova server fails by any reason and the html content would be empty, then the renderReact('Component', Component) wouldn't work either returns blank page and I have to call:

ReactDOM.hydrate(
    <Component />,
    document.getElementById('root')
  )

In this case how could I know my root is empty? because this condition throws error due to undefined document object:
document.getElementById('root') !== null && document.getElementById('root').hasChildNodes()

TypeError: ((!(null === document.getElementById(...))) && document.getElementById(...).hasChildNodes(...)) is not a function

Why is React hydration data within a script tag, commented out?

I'm working on an issue to optimize open source library for server rendering: github.com/shakacode/react_on_rails/pull/660.

We're considering breaking away from placing react hydration data in a meta tag and moving into maybe a script tag.

Why does Airbnb puts react hydration data inside of an <script type=“application/json” data-key=“foobar”><!--{json}--></script> per the screen shots below? Is this related to XSS or performance reasons?

view-source:https://www.airbnb.com/s/Panorama--BC--Canada?guests=10&adults=10&children=0&infants=0&checkin=12%2F18%2F2017&checkout=12%2F25%2F2017&ss_id=19nvfbwh&ss_preload=true&source=bb&page=1&s_tag=pMJm3GqR&allow_override%5B%5D=

2017-02-13_15-04-16

2017-02-13_15-34-39

CC: @goatslacker

An in-range update of eslint is breaking the build 🚨

Version 4.15.0 of eslint was just published.

Branch Build failing 🚨
Dependency eslint
Current Version 4.14.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

eslint is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Release Notes v4.15.0
  • 6ab04b5 New: Add context.report({ messageId }) (fixes #6740) (#9165) (Jed Fox)
  • fc7f404 Docs: add url to each of the rules (refs #6582) (#9788) (Patrick McElhaney)
  • fc44da9 Docs: fix sort-imports rule block language (#9805) (ferhat elmas)
  • 65f0176 New: CLIEngine#getRules() (refs #6582) (#9782) (Patrick McElhaney)
  • c64195f Update: More detailed assert message for rule-tester (#9769) (Weijia Wang)
  • 9fcfabf Fix: no-extra-parens false positive (fixes: #9755) (#9795) (Erin)
  • 61e5fa0 Docs: Add table of contents to Node.js API docs (#9785) (Patrick McElhaney)
  • 4c87f42 Fix: incorrect error messages of no-unused-vars (fixes #9774) (#9791) (akouryy)
  • bbabf34 Update: add ignoreComments option to indent rule (fixes #9018) (#9752) (Kevin Partington)
  • db431cb Docs: HTTP -> HTTPS (fixes #9768) (#9768) (Ronald Eddy Jr)
  • cbf0fb9 Docs: describe how to feature-detect scopeManager/visitorKeys support (#9764) (Teddy Katz)
  • f7dcb70 Docs: Add note about "patch release pending" label to maintainer guide (#9763) (Teddy Katz)
Commits

The new version differs by 14 commits.

  • e14ceb0 4.15.0
  • 2dfc3bd Build: changelog update for 4.15.0
  • 6ab04b5 New: Add context.report({ messageId }) (fixes #6740) (#9165)
  • fc7f404 Docs: add url to each of the rules (refs #6582) (#9788)
  • fc44da9 Docs: fix sort-imports rule block language (#9805)
  • 65f0176 New: CLIEngine#getRules() (refs #6582) (#9782)
  • c64195f Update: More detailed assert message for rule-tester (#9769)
  • 9fcfabf Fix: no-extra-parens false positive (fixes: #9755) (#9795)
  • 61e5fa0 Docs: Add table of contents to Node.js API docs (#9785)
  • 4c87f42 Fix: incorrect error messages of no-unused-vars (fixes #9774) (#9791)
  • bbabf34 Update: add ignoreComments option to indent rule (fixes #9018) (#9752)
  • db431cb Docs: HTTP -> HTTPS (fixes #9768) (#9768)
  • cbf0fb9 Docs: describe how to feature-detect scopeManager/visitorKeys support (#9764)
  • f7dcb70 Docs: Add note about "patch release pending" label to maintainer guide (#9763)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Alternative Server Architecture

I've been looking into this project and I am really excited about it. I am curious if there has been any talk about having the flexibility to use a server environment that is not express. Namely the use-case I find most interesting would be the ability to run hypernova as a lambda, which would require a more stateless implementation.

Thanks!

I'd like to be able to add my own log transports

I see that I have the ability to add a logger property to the config object passed in to the hypernova initializer. However, it looks like this only gives me the ability to override these defaults:

{
  level: 'info',
  colorize: true,
  timestamp: true,
  prettyPrint: process.env.NODE_ENV !== 'production',
}

What I'd really like to be able to do is pass in my own transports to Winston so I can hook in to my remote logging service. Any plans to add this feature?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.