# Cycle.js Deploy & Usage Guide
A comprehensive guide for building and deploying applications with Cycle.js, a functional and reactive JavaScript framework.
## 1. Prerequisites
- **Node.js**: Version 14.x or higher (LTS recommended)
- **Package Manager**: npm 6+ or Yarn 1.22+
- **TypeScript**: Version 4.0+ (required for type definitions)
- **Build Tool**: Webpack, Rollup, Vite, or Parcel (for bundling)
- **Git**: For cloning examples and version control
## 2. Installation
### New Project Setup
Create a new project and install core dependencies:
```bash
mkdir my-cycle-app && cd my-cycle-app
npm init -y
npm install @cycle/run @cycle/dom xstream
Install TypeScript and build tools (optional but recommended):
npm install -D typescript webpack webpack-cli webpack-dev-server ts-loader html-webpack-plugin
Framework Development (Contributing)
To work on the Cycle.js source code:
git clone https://github.com/cyclejs/cyclejs.git
cd cyclejs
npm install
This installs dependencies for the monorepo and links local packages.
3. Configuration
TypeScript Configuration
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2015",
"module": "ES2015",
"moduleResolution": "node",
"strict": true,
"jsx": "react",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
Webpack Configuration (Example)
Create webpack.config.js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{ test: /\.ts$/, use: 'ts-loader', exclude: /node_modules/ }
]
},
plugins: [
new HtmlWebpackPlugin({ template: 'index.html' })
],
devServer: {
port: 8080,
hot: true
}
};
Debug Configuration (Optional)
For reactive stream debugging, install the devtool:
npm install -D @cycle/devtool
Add to your application entry point:
import {run} from '@cycle/run';
// DevTool automatically detects and visualizes streams when included in build
4. Build & Run
Development Mode
Start the development server:
npx webpack serve --mode development
Or with Vite (faster alternative):
npm install -D vite
# Create vite.config.ts with @cycle/dom plugin support
npx vite
Production Build
Create optimized bundle:
npx webpack --mode production
Output will be in dist/ directory ready for deployment.
Basic Application Structure
Create src/index.ts:
import {run} from '@cycle/run';
import {makeDOMDriver, div, button, h1} from '@cycle/dom';
import xs from 'xstream';
interface Sources {
DOM: any;
}
interface Sinks {
DOM: any;
}
function main(sources: Sources): Sinks {
const decrement$ = sources.DOM.select('.dec').events('click').mapTo(-1);
const increment$ = sources.DOM.select('.inc').events('click').mapTo(+1);
const count$ = xs.merge(decrement$, increment$)
.fold((acc, curr) => acc + curr, 0);
const vdom$ = count$.map(count =>
div([
button('.dec', 'Decrement'),
button('.inc', 'Increment'),
h1(`Count: ${count}`)
])
);
return { DOM: vdom$ };
}
run(main, {
DOM: makeDOMDriver('#app')
});
Create index.html:
<!DOCTYPE html>
<html>
<head>
<title>Cycle.js App</title>
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
5. Deployment
Static Hosting (Recommended)
Cycle.js applications compile to static JavaScript bundles suitable for any static host:
Netlify:
npm run build
netlify deploy --prod --dir=dist
Vercel:
Create vercel.json:
{
"version": 2,
"builds": [
{ "src": "package.json", "use": "@vercel/static-build" }
]
}
GitHub Pages:
Push dist/ folder to gh-pages branch or use GitHub Actions.
Server-Side Rendering (SSR)
For SEO or initial load performance, use @cycle/html:
npm install @cycle/html @cycle/run xstream
Server entry (server.ts):
import {run} from '@cycle/run';
import {makeHTMLDriver} from '@cycle/html';
import {app} from './app';
run(app, {
DOM: makeHTMLDriver((html) => {
// Send html to HTTP response
console.log(html);
})
});
Deploy to Node.js hosting (Heroku, Railway, AWS Elastic Beanstalk).
Docker Deployment
Create Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 8080
CMD ["npx", "serve", "-s", "dist", "-l", "8080"]
Build and run:
docker build -t cyclejs-app .
docker run -p 8080:8080 cyclejs-app
6. Troubleshooting
Event Delegation Issues
Events not firing? Check the event type bubbles. Non-bubbling events (focus, blur, load, etc.) require special handling:
// Use capture phase for non-bubbling events
sources.DOM.select('input').events('focus', {useCapture: true})
Full list of non-bubbling events: blur, canplay, canplaythrough, durationchange, emptied, ended, focus, load, loadeddata, loadedmetadata, mouseenter, mouseleave, pause, play, playing, ratechange, reset, scroll, seeked, seeking, stalled, submit, suspend, timeupdate, unload, volumechange, waiting.
Memory Leaks
Always return sinks to ensure proper stream disposal:
// Bad - stream not returned
xs.periodic(1000).subscribe({ next: console.log });
// Good - managed by framework
return { DOM: xs.periodic(1000).map(i => div(`${i}`)) };
Isolation Boundaries
Components not receiving events? Ensure proper isolation