Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

als-render

Package Overview
Dependencies
Maintainers
0
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

als-render

Lightweight JS library for transforming JSX into raw HTML, enabling both server-side and client-side rendering without a virtual DOM. It offers a simplified component model with automated event handling and global state management.

  • 3.3.0
  • latest
  • npm
  • Socket score

Version published
Weekly downloads
16
decreased by-94.98%
Maintainers
0
Weekly downloads
 
Created
Source

als-render Documentation

Introduction

als-render is a frontend framework that offers a comprehensive solution for building dynamic components (components with dynamic state and hooks), importing them, integrating them with each other, with the ability to use a single global context, and with the ability to use a JSX-like syntax. The framework works on the fly both in the browser and on the server, offering SSR on the fly and allowing you to use the same files both on the server and in the browser. On the server, you can connect the browser part via routes in Express and do it on the fly. The framework also has the ability to localize for translation into pre-defined languages.

What's New in Version 3.0.0

The version 3.0.0 does not have backward compatibility. No build method and publics and routes not available inside components any more.

  • No publics and routes available inside components anymore
  • The resultFn not running, on build without parameters any more
  • New Lang version with add and merge methods
  • No build method
  • props
    • was {data,lang}
    • now data
  • Available context.lang

Installation and Setup

Installation

You can install als-render via npm or use a CDN for quick testing in the browser:

  • npm (recommended for full development):
npm install als-render
  • CDN (for browser usage):
    • Minified: https://www.unpkg.com/als-render@2.0.0/render.min.js
    • Unminified: https://www.unpkg.com/als-render@2.0.0/render.js

Requirements

  • Browser: ES6 support is required.
  • Node.js: Compatible with all Node.js versions supporting ES6.

Quick Start

Components example

App.js:

const Counter = require('./Counter');

class App extends Component {
   constructor(props) { super(props)}
   render(props) {
      const { data } = props;
      return (
         <div>
            <Counter count={data.count} />
         </div>
      );
   }
}

module.exports = App;

Counter.js:

class Counter extends Component {
   constructor(props) { super(props)}
   render({ count }) {
      return (
         <div>
            <button onclick={() => this.update({ count: count + 1 })}>
               { 'Increase' }
            </button>
            <span>{ count }</span>
            <button onclick={() => this.update({ count: count - 1 })}>
               { 'Decrease' }
            </button>
         </div>
      );
   }
}

module.exports = Counter;

Browser Example

Here’s a minimal example of using als-render in the browser to create a counter component:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <script src="https://www.unpkg.com/als-render@3.0.0/render.min.js"></script>
   <title>Counter</title>
</head>
<body>
   <div component="App"></div>
</body>
<script>
   render('./App', { count: 0 });
</script>
</html>
Node.js Example (Server-Side Rendering)

You can use the same components for server-side rendering (SSR). Here’s an example:

Server Code:

const Render = require('als-render');
const fs = require('fs');

const rendered = new Render('./App');
const rawHtml = rendered.render({ count: 0 });
const html = `<!DOCTYPE html>
<html lang="en">
<head><title>Counter</title></head>
<body>${rawHtml}</body></html>
`
fs.writeFileSync('./counter.html', rawHtml, 'utf-8');
Example with Express

For dynamic SSR integration with Express:

const express = require('express');
const Render = require('als-render');
const app = express();

const rendered = new Render('./App');
Render.publish(app, express); // Adds bundle and public routes.

app.get('/', (req, res) => {
   const html = rendered.render({ count: 0 }, 'ru');
   res.send(`<!DOCTYPE html>
      <html lang="en">
      <head><title>Counter</title></head>
      <body>${html}</body>
   </html>`);
});

app.listen(3000, () => console.log('Server is running on http://localhost:3000'));

In the browser: The server dynamically generates the same HTML structure as the browser example and serves it, including all component functionalities.

Components

als-render uses als-component to create reactive components that work seamlessly in both server and browser environments. Components support lifecycle hooks, event handling, and state management.

For detailed information on component usage, refer to the als-component documentation.

By default the Component class available as global variable for rendered components.

It can be used like this:

class App extends Component {
   constructor(props) { super(props) }
   render({ count = 0 }) {
      return `
         <div>
            <button click="${this.action('click', () => this.update({ count: count - 1 }))}">-</button>
            <span>${count}</span>
            <button click="${this.action('click', () => this.update({ count: count + 1 }))}">+</button>
         </div>
      `;
   }
}

Or like this if options.jsx = true (true by default):

class App extends Component {
   constructor(props) { super(props) }
   render({ count = 0 }) {
      return (
         <div>
            <button onclick={() => this.update({ count: count - 1 })}>-</button>
            <span>{count}</span>
            <button onclick={() => this.update({ count: count + 1 })}>+</button>
         </div>
      );
   }
}

The Component has hooks mount and unmount and onload event:

this.on('mount', () => console.log('Component mounted'));
this.on('unmount', () => console.log('Component unmounted'));

3.2 Localization

als-render includes built-in localization support through a global _() function, available in every component. This function retrieves the appropriate translation for the current language.

Example:

Define your localization settings:

const langs = { 
   langs: ['en', 'ru'],
   dictionary: {
      Increase: ['Increase', 'Увеличить'],
      Decrease: ['Decrease', 'Уменьшить']
   }
}
const options = { langs,lang: 'ru'};

In your component:

class Counter extends Component {
   render({ count }) {
      return (
         <div>
            <button>{ _('Increase') }</button>
            <span>{ count }</span>
            <button>{ _('Decrease') }</button>
         </div>
      );
   }
}

In browser:

<script>
render('./App', {count:0}, { langs,lang: 'ru'});
</script>

On server:

const rendered = new Render('./App', {langs});
const lang = 'ru';
const rawHtml = rendered.render({ count: 0 }, lang);

Global variables

By default, there are few global variables which available for all components:

  1. context - is the object which passed from outside and available as global for all components
    1. isBrowser - true in browser and false in NodeJs
  2. _ - the localization function as showed above
  3. Custom variables added by developer

context

const rendered = new Render('./App');
const context = {some:'Value for node'}
const browserContext = {some:'Value for browser'}
const lang = 'en'
const rawHtml = rendered.render({ count: 0 },lang,{context,browserContext});
class App extends Component {
   constructor(props) { super(props) }
   render({ count = 0 }) {
      if(context.isBrowser) {
         const existCount = localstorage.getItem('count')
         if(existCount == undefined) localstorage.setItem('count',count)
         else this.props.count = Number(existCount)
      }
      return (
         <div>
            {context.some}
            <button onclick={() => this.update({ count: this.props.count - 1 })}>-</button>
            <span>{this.props.count}</span>
            <button onclick={() => this.update({ count: this.props.count + 1 })}>+</button>
         </div>
      );
   }
}

Custom variables and scripts

New renderOptions and bundleRenderOptions in Constructor

Updated Constructor Interface

const renderInstance = new Render('./components/App', {
   langs: { langs: ['ru'], dictionary: { hello: ['привет'] } },
   includebundle: true,
   renderOptions: {
      parameters: [], // Additional parameters for server-side rendering
      scriptBefore: '', // Scripts executed before server-side rendering
      scriptAfter: '' // Scripts executed after server-side rendering
   },
   bundleRenderOptions: {
      parameters: [], // Additional parameters for the browser bundle
      scriptBefore: '', // Scripts executed before the browser bundle
      scriptAfter: '' // Scripts executed after the browser bundle
   }
});
Parameters

The parameters should be strings and can include default value, like ['some="test"',now=Date.now()].

Behavior of scriptBefore and scriptAfter
  • scriptBefore - script for execution before requiring files.
    • For example const SOME_TOKEN="token";. Now SOME_TOKEN available anywhere in rendered code.
  • scriptAfter - script for execution after requiring files.
    • For example you have access to modules and result (MainComponent class) variables.

!imprtant Server bundle function builded twice to get publics and routes. On first run custom parameters are not available and scriptBefore and scriptAfter can throw error

Method render

render(data, lang, options = {}) {
   const { 
      context = {}, // Context for server-side rendering
      browserContext = {}, // Context for browser-side rendering
      parameters = [], // Parameters for server-side rendering
      bundleParameters = [] // Parameters for browser-side rendering (must be strings)
   } = options;
}
  • parameters - can be any js parameter from server. Even request and response variables.
  • bundleParameters - must be strings (e.g., through JSON.stringify) because they are passed to the browser bundle.

Example

const renderInstance = new Render('./components/App', {
   langs: { langs: ['ru'], dictionary: { hello: ['привет'] } },
   includebundle: true,
   renderOptions: {
      parameters: ['customParam'],
      scriptAfter: 'if(customParam) customParam.test = true;'
   },
   bundleRenderOptions: {
      parameters: ['customBundleParam'],
      scriptAfter: 'customBundleParam.test = true;'
   }
});

const customParam = { test: false };
const customBundleParam = { test: false };

const result = renderInstance.render(
   { key: 'value' }, 
   'ru', 
   {
      context: { user: 'test' },
      browserContext: { browser: true },
      parameters: [customParam],
      bundleParameters: [JSON.stringify(customBundleParam)]
   }
);

console.log(customParam.test); // true
console.log(result.includes('customBundleParam.test = true')); // true

SSR

There are few options for server side rendering.

  1. Don't include bundle for browser (set options.includebundle = false)
  2. Include bundle for browser (set options.includebundle = true, or leave it, cause it's true by default)
    1. Include bundle for browser as script inside page (default option)
      1. This option adds js code directly to html which encreasing the page size for download
    2. Include bundle as Express route
      1. This option, adds route to express routes (app.get...) and use bundle as script[src]
      2. Recomended for production, because bundle cached by browser
        1. You can add version to bundle in (options.version) for renewing the cache

Example:

const express = require('express');
const app = express();

const Render = require('als-render');
Render.env.bundleAsRoute = true
Render.publics['/app/styles.css'] = './styles.css'
Render.routes['main-style.css'] = `body {margin:0}`

const rendered = new Render('./App',{ includebundle:true, version:'1.0.0' });
Render.publish(app, express); // Adds bundle and public routes.

Configuration Options

Render Class Interface

class Render {
   static Require: typeof Require;
   static publics: Record<string, string>; // Static public files or folders
   static routes: Record<string, string>; // Static routes for Express
   static env: {
      bundleAsRoute: boolean; // Add bundle as route (default: false)
      minify: boolean; // Minify the bundle (default: false)
      jsx: boolean; // Enable JSX (default: true)
      bundleName: string; // Name of the bundle function (default: 'bundleFn')
   };

   static publish(app: Express, express: typeof import('express')): void;

   constructor(path: string, options?: {
      includebundle?: boolean; // Include bundle in the result (default: true)
      langs?: { langs: string[], dictionary: Record<string, string[]> };
      defaultLang?: string; // Default language for `_()` (optional)
      cyclicDependencies?: boolean; // Allow cyclic dependencies (default: false)
      version:undefined; // Adds ?version={version} to bunlde as src
      renderOptions: {
         parameters?: string[], // Additional parameters for server-side rendering
         scriptBefore?: string='', // Scripts executed before server-side rendering
         scriptAfter?: string='' // Scripts executed after server-side rendering
      },
      bundleRenderOptions: {
         parameters?: string[], // Additional parameters for the browser bundle
         scriptBefore?: string='', // Scripts executed before the browser bundle
         scriptAfter?: string=''// Scripts executed after the browser bundle
      }
   });

   render(data: Record<string, any>, lang: string, options = {}) {
   const { 
         context = {}, // Context for server-side rendering
         browserContext = {}, // Context for browser-side rendering
         parameters = [], // Parameters for server-side rendering
         bundleParameters = [] // Parameters for browser-side rendering (must be strings)
      } = options;
   }
}

Browser render() Function Interface

async function render(
   path: string,
   data?: Record<string, any>,
   options?: {
      selector?: string; // CSS selector for root component
      version?: string; // Cache-busting version string (optional)
      jsx?: boolean; // Enable JSX syntax (default: true)
      context?: Record<string, any>; // Global context object (default: {})
      langs?: { langs: string[], dictionary: Record<string, string[]> }; // Localization settings
      lang?: string; // Current language for `_()`
      cyclicDependencies?: boolean; // Allow cyclic dependencies (default: false)
      logger?: Console; // Logger for debugging (default: console)
      parameters = {}; // must be {key:value}
      scriptBefore = '';
      scriptAfter = '';
   }
): Promise<void>;

Keywords

FAQs

Package last updated on 30 Dec 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc