zombiebox
Version:
ZombieBox is a JavaScript framework for development of Smart TV and STB applications
178 lines (119 loc) • 6.79 kB
Markdown
# Version 2.0.0
This version introduced a major change in code structure: Dependency management was switched from google Closure (`goog.require` and `goog.provide`) to ECMAScript modules (`import` and `export`).
As a result, this version is completely incompatible with old projects and addons.
Additionally, some other breaking changes were introduced.
## Config changes
Application config was reworked and requires serious migration. See [configuration](../configuration.md) for details.
## Aliases
As ZombieBox consists of multiple components (framework, extensions and platforms) that are separate from each other aliases were introduced to tie them together and allow importing modules from other components.
Each project has the following aliases:
Buil-in aliases:
* `zb` – ZombieBox code; Root: ZombieBox `zb` directory
* `generated` – Code generated by ZombieBox and extensions; Root: `generatedDirectory` config field
Project alias: Name: `project.name`; Root: `project.module`.
Addon aliases: Name: Addon name; Root: Addon source root.
Custom aliases: As defined in `aliases` config field.
Examples:
```js
import Timeout from 'zb/timeout';
import ENVIRONMENT from 'generated/define';
import ScrollBar from 'ui/widgets/scroll-bar/scroll-bar';
```
## Migrating to modules
Migrating the code base is pretty straightforward: `goog.require` must be replaced with corresponding `import` statements and `goog.provide` with `export` and project configuration should be updated.
A special alias `generated` points to code generated by framework and its addons, namely:
* `generated/app` – Application instance, formerly global `app`
* `generated/define` – Compile-time defines, formerly `zb.define`
* `generated/package-info` – `package.json` contents, formerly `zb.packageInfo`
Some caveats of ZombieBox modules implementation:
* GCC will only compile files that are added to the list of sources. If it's imported, but not added to sources it will be ignored.
* For dev-server (`zb run`) import paths are rewritten by backend on the fly to be relative.
* `import` does not resolve `index.js` files automatically.
Note that modules introduce other changes that may complicate the process:
* Modules are scoped, so accessing other modules through global scopes is no longer possible.
* Modules are always `strict mode`.
Combining `import` and `goog.require` is possible, but might lead to weird consequences. Combining `export` and `goog.provide` is not possible.
### Development server
Development server (`zombiebox run`) now runs modules natively without compilation or transpilation. However, as the browsers only support local modules, imports are rewritten in files upon serving from aliases to file-system paths.
All project modules are served under web path `/modules/`, then alias name and then file path under alias root. For example, `http://localhost:1337/modules/zb/events/event-publisher` will serve `EventPublisher` class from ZombieBox.
### Global `app`
`app` variable is no longer exposed to global scope. Instead, it's exported by `generated/app` module.
```js
import app from 'generated/app';
```
### dev script
`dev.js` script (`web/dev.js`) was replaced by `devServer.backdoor` config option.
Its path is no longer hard-coded, so you can place it anywhere. If it uses some other components, it now should import them.
Examples:
Old `web/dev.js`:
```js
zb.device.platforms.pc.Info._getLocale = () => 'ru-RU';
```
New `devServer.backdoor`:
```js
import Info from 'pc/info';
Info.prototype._getLocale = () => 'ru-RU';
```
### Accessing modules in runtime
Previously all modules were exposed in global scope in namespaces which allowed for easier debugging. Now that modules are properly scoped it's no longer possible.
Instead, you can import them from developer console with [dynamic import](https://developers.google.com/web/updates/2017/11/dynamic-import):
```js
import('/modules/generated/app').then((module) => window.app = module);
import('/modules/zb/console/console').then((zbConsole) => zbConsole.log('Hello'));
```
## Changes not related to modules
### CuteJS
CuteJS was decoupled from ZombieBox and `zombiebox-extension-cutejs` was introduced. See MIGRATION.md in extension.
### Abstract Addons
Addon interfaces were replaced with Abstract classes. This should only affect extensions and platforms and they should migrate from implementing `IZBAddon` to inheriting `AbstractAddon`.
### Package `main` field
`require('zombiebox')` previously returned `ZBApplication` class which server as entry point ot server-side ZombieBox tools. From 2.0.0 it returns an object containing several classes including `ZBApplication` (now renamed to simply `Application`).
Old usage:
```js
const ZBApplication = reuquire('zombiebox');
```
New usage:
```js
const ZBApplication = reuquire('zombiebox').Application;
// or
const {Application} = require('zombiebox');
```
### `postcss-cssnext` replaced with `postcss-preset-env`
[cssnext](https://moox.io/blog/deprecating-cssnext/) was deprecated a while ago. In 2.0 it was replaced with [postcss-preset-env](https://preset-env.cssdb.org/) and `cssnextOptions` config field was replaced with `presetEnvOptions`.
The two solve the same problem, but are not fully compatible, see article above.
Additionally, only Stage 3 features are enable by default while cssnext had a lot of earlier stages. Use `postcss.presetEnvOptions.stage` to change stage or enable features in case-by-case basis. Other functionality can be restored by configuring preset-env or adding new plugins with `postcss.plugins` option.
### zb CLI moved to ZombieBox
Global CLI from `zb-cli` was deprecated and re-implemented as part of ZombieBox itself. Use `npx` to access it from projects, i.e. `npx zb buld pc`
### `AbstractTransport` template
`AbstractTransport` now has a `REQUEST_PARAMS` template. `doRequest` and `doPersistentRequest` accept it as the only argument. Error handler now also receives it.
This change is partially backwards compatible: `AbstractTransport` implementations that only had one parameter in `doRequest` will continue to work the same, while implementations that had several arguments will break as additional arguments are now ignored.
Simplest way to migrate is to pack all your `doRequest` parameters into an object:
Fore example, given:
```js
class Transport extends AbstractTransport {
/**
* @override
*/
doRequest(hostname, apiVersion, method) {}
}
```
New approach:
```js
/**
* @typedef {{
* hostname: string,
* apiVersion: string,
* method: string
* }}
*/
let RequestParams;
/**
* @extends {AbstractTransport<RequestParams>}
*/
class Transport extends AbstractTransport {
/**
* @override
*/
doRequest(params) {}
}
```