Research
Security News
Kill Switch Hidden in npm Packages Typosquatting Chalk and Chokidar
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
als-render
Advanced tools
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.
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.
The version 3.0.0 does not have backward compatibility. No
build
method andpublics
androutes
not available inside components any more.
build
method{data,lang}
data
context.lang
You can install als-render
via npm or use a CDN for quick testing in the browser:
npm install als-render
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;
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>
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');
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.
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'));
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.
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);
By default, there are few global variables which available for all components:
context
- is the object which passed from outside and available as global for all components
isBrowser
- true in browser and false in NodeJs_
- the localization function as showed abovecontext
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>
);
}
}
renderOptions
and bundleRenderOptions
in Constructorconst 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()]
.
scriptBefore
and scriptAfter
scriptBefore
- script for execution before requiring files.
const SOME_TOKEN="token";
. Now SOME_TOKEN available anywhere in rendered code.scriptAfter
- script for execution after requiring files.
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
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.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
There are few options for server side rendering.
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.
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;
}
}
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>;
FAQs
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.
The npm package als-render receives a total of 15 weekly downloads. As such, als-render popularity was classified as not popular.
We found that als-render demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
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.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.
Product
Socket now supports uv.lock files to ensure consistent, secure dependency resolution for Python projects and enhance supply chain security.