@financial-times/x-engine
Advanced tools
Comparing version 1.0.0-5 to 1.0.0-6
{ | ||
"name": "@financial-times/x-engine", | ||
"version": "v1.0.0-5", | ||
"version": "v1.0.0-6", | ||
"description": "A consolidation library to render x- components with any compatible runtime.", | ||
@@ -11,3 +11,3 @@ "main": "src/server.js", | ||
"dependencies": { | ||
"resolve": "^1.6.0" | ||
"assign-deep": "^0.4.7" | ||
}, | ||
@@ -20,3 +20,3 @@ "engines": { | ||
}, | ||
"gitHead": "dd548b14646b8edd854e0818191753addb75c2b0" | ||
"gitHead": "8e02e84062aeaa69a4c9b8eb898ae1aba1d964c4" | ||
} |
@@ -22,13 +22,11 @@ # x-engine | ||
- [React](https://reactjs.org/) | ||
- [VHTML](https://github.com/developit/vhtml)<sup>†</sup> | ||
- [VDO](https://github.com/DylanPiercey/vdo) | ||
\* Usage of Hyperapp depends on a small modification to higher-order components to accept `children` as a second argument rather than receiving them appended to `props`. | ||
† The current release of the VHTML module has compatibility issues and is therefore not viable for production use without modification. | ||
## Configuration | ||
To start you must specify your runtime configuration within `package.json`. This instructs `x-engine` which modules to load for both the server and for the browser environments. | ||
To start you must specify your runtime configuration within `package.json`. This instructs `x-engine` which modules to load for your environment. You may specify different runtimes for server and browser rendering depending on your needs. | ||
You only need to specify the environments you need and you may specify different runtimes depending on your needs. | ||
This module includes several presets for popular tools and frameworks including React, Preact, and Hyperons. For example to use Hyperons on the server and Preact in the browser you may use the name of their preset: | ||
@@ -39,5 +37,17 @@ ```json | ||
"engine": { | ||
"server": "vhtml", | ||
"browser": { | ||
"runtime": "react", | ||
"server": "hyperons", | ||
"browser": "preact" | ||
} | ||
} | ||
} | ||
``` | ||
But if your chosen tool does not have a preset then the configuration for it can be provided with the expanded configuration format. The example below shows how to load the VDO module and use its `createElement` factory function<sup>\*</sup>: | ||
```json | ||
{ | ||
"x-dash": { | ||
"engine": { | ||
"server": { | ||
"runtime": "vdo", | ||
"factory": "createElement" | ||
@@ -50,6 +60,2 @@ } | ||
If your chosen runtime module returns a factory function<sup>\*</sup> you only need to specify the module name but if the module exposes multiple methods then you must specify the appropriate method to use. | ||
With the configuration added you will now be able to include and render `x-` components. | ||
\* A JSX factory function is a variadic function<sup>†</sup> with the signature `fn(element, properties, ...children)`, examples include `React.createElement` and `Preact.h`. See the [FAQ section](#faq) for more information. | ||
@@ -63,3 +69,3 @@ | ||
If your chosen runtime factory returns a string (e.g. the `vhtml` package) then you can pass properties to the component and immediately use the returned value: | ||
If your chosen runtime factory returns a string then you can pass properties to the component and immediately use the returned value: | ||
@@ -75,7 +81,7 @@ ```js | ||
But if your factory method returns a node (this will be the case if you're using `react/preact/inferno/rax/nerv`) then you'll need to load their specific methods to convert the node into a string or stream: | ||
But if your factory method returns a framework-specific intermediary code then you'll need to load the specified render method to render the node into a string or stream: | ||
```js | ||
const { render } = require('@financial-times/x-engine'); | ||
const { Teaser } = require('@financial-times/x-teaser'); | ||
const { renderToString } = require('react/server'); | ||
@@ -85,3 +91,3 @@ app.get('/teaser', (request, response) => { | ||
const nodes = Teaser(properties); | ||
response.send(renderToString(nodes)); | ||
response.send(render(nodes)); | ||
}); | ||
@@ -108,3 +114,3 @@ ``` | ||
```jsx | ||
import React from 'react'; | ||
import { h } from '@financial-times/x-engine'; | ||
import { Teaser } from '@financial-times/x-teaser'; | ||
@@ -135,3 +141,3 @@ | ||
Whichever one you want! React, Preact, Rax, and Nerv are all largely compatible with one another. If you don't want the overhead of a framework, or are rendering static HTML, then it's worth investigating the VHTML or Hyperons modules. | ||
Whichever one you want! React, Preact, Rax, and Nerv are all largely compatible with one another. If you don't want the overhead of a framework, or are rendering static HTML, then it's worth investigating the Hyperons or VDO modules. | ||
@@ -138,0 +144,0 @@ ### What about Hyperscript? |
// This module is just a placeholder to be re-written at build time. | ||
const runtime = require(X_ENGINE_RUNTIME); | ||
module.exports = X_ENGINE_RESOLVE; | ||
const runtime = require(X_ENGINE_RUNTIME_MODULE); | ||
const render = require(X_ENGINE_RENDER_MODULE); | ||
module.exports.h = X_ENGINE_FACTORY; | ||
module.exports.render = X_ENGINE_RENDER; | ||
module.exports.Component = X_ENGINE_COMPONENT; |
@@ -0,1 +1,3 @@ | ||
const presets = require('./presets'); | ||
/** | ||
@@ -9,3 +11,7 @@ * Format Config | ||
if (typeof config === 'string') { | ||
config = { runtime: config, factory: null }; | ||
if (presets.hasOwnProperty(config)) { | ||
config = presets[config]; | ||
} else { | ||
config = { runtime: config, factory: null }; | ||
} | ||
} | ||
@@ -21,3 +27,7 @@ | ||
if (!config.renderModule) { | ||
config.renderModule = config.runtime; | ||
} | ||
return config; | ||
}; |
@@ -0,8 +1,9 @@ | ||
const resolve = require('resolve-cwd'); | ||
const deepGet = require('./concerns/deep-get'); | ||
const loadManifest = require('./concerns/load-manifest'); | ||
const resolvePkg = require('./concerns/resolve-pkg'); | ||
const resolvePeer = require('./concerns/resolve-peer'); | ||
const formatConfig = require('./concerns/format-config'); | ||
const resolveModule = require('./concerns/resolve-module'); | ||
// 1. try to load the application's package manifest | ||
const pkg = loadManifest(); | ||
const pkg = require(resolvePkg()); | ||
@@ -20,7 +21,18 @@ // 2. if we have the manifest then find the engine configuration | ||
// 4. if this module is a linked dependency then resolve required runtime to CWD | ||
const runtime = resolveModule(config.runtime); | ||
const runtime = require(resolvePeer(config.runtime)); | ||
// 5. if we've loaded the runtime then find it's create element factory function | ||
// 5. if we've loaded the runtime then find its create element factory function | ||
const factory = config.factory ? runtime[config.factory] : runtime; | ||
module.exports = factory; | ||
// 6. if we've loaded the runtime then find its Component constructor | ||
const component = config.component ? runtime[config.component] : null; | ||
// 7. if the rendering module is different to the runtime, load it | ||
const renderModule = config.renderModule ? require(resolvePeer(config.renderModule)) : runtime; | ||
// 8. if we've got the render module then find its render method | ||
const render = config.render ? renderModule[config.render] : renderModule; | ||
module.exports.h = factory; | ||
module.exports.render = render; | ||
module.exports.Component = component; |
@@ -0,9 +1,10 @@ | ||
const assignDeep = require('assign-deep'); | ||
const deepGet = require('./concerns/deep-get'); | ||
const loadManifest = require('./concerns/load-manifest'); | ||
const resolvePkg = require('./concerns/resolve-pkg'); | ||
const resolvePeer = require('./concerns/resolve-peer'); | ||
const formatConfig = require('./concerns/format-config'); | ||
const resolveModule = require('./concerns/resolve-module'); | ||
module.exports = function() { | ||
// 1. try to load the application's package manifest | ||
const pkg = loadManifest(); | ||
const pkg = require(resolvePkg()); | ||
@@ -20,11 +21,36 @@ // 2. if we have the manifest then find the engine configuration | ||
// 4. if this module is a linked dependency then resolve Webpack instance to CWD | ||
const webpack = resolveModule('webpack'); | ||
// 4. if this module is a linked dependency then resolve Webpack & runtime to CWD | ||
const webpackResolution = resolvePeer('webpack'); | ||
const runtimeResolution = resolvePeer(config.runtime); | ||
const renderResolution = resolvePeer(config.renderModule); | ||
// The define plugin performs direct text replacement | ||
// <https://webpack.js.org/plugins/define-plugin/> | ||
return new webpack.DefinePlugin({ | ||
'X_ENGINE_RUNTIME': `"${config.runtime}"`, | ||
'X_ENGINE_RESOLVE': config.factory ? `runtime["${config.factory}"]` : 'runtime' | ||
}); | ||
const webpack = require(webpackResolution); | ||
return { | ||
apply(compiler) { | ||
// 5. alias the runtime name to the resolved runtime path | ||
assignDeep(compiler.options, { | ||
resolve: { | ||
alias: { | ||
[config.runtime]: runtimeResolution, | ||
[config.renderModule]: renderResolution, | ||
}, | ||
}, | ||
}); | ||
const replacements = { | ||
'X_ENGINE_RUNTIME_MODULE': `"${config.runtime}"`, | ||
'X_ENGINE_FACTORY': config.factory ? `runtime["${config.factory}"]` : 'runtime', | ||
'X_ENGINE_COMPONENT': config.component ? `runtime["${config.component}"]` : 'null', | ||
'X_ENGINE_RENDER_MODULE': `"${config.renderModule}"`, | ||
'X_ENGINE_RENDER': config.render ? `render["${config.render}"]` : 'null', | ||
}; | ||
// The define plugin performs direct text replacement | ||
// <https://webpack.js.org/plugins/define-plugin/> | ||
const define = new webpack.DefinePlugin(replacements); | ||
define.apply(compiler); | ||
} | ||
}; | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
10760
10
148
139
8
+ Addedassign-deep@^0.4.7
+ Addedassign-deep@0.4.8(transitive)
+ Addedassign-symbols@0.1.1(transitive)
+ Addedis-primitive@2.0.0(transitive)
+ Addedkind-of@5.1.0(transitive)
- Removedresolve@^1.6.0
- Removedfunction-bind@1.1.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedis-core-module@2.15.1(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedresolve@1.22.8(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)