Project is continued at PuzzleJs
TyStream is a layout service that generates web pages from asynchronous fragments. It is a friendly and fast library that helps you optimizing your web pages with progressive rendering. TyStream has built-in integration with ExpressJs .
Pull requests are welcome!
We create component because of their reusabilities. We can use them anywhere we want, in a search bar, in a login popup or anything else. But fragments are encapsulated modules with specific business. Like an header, product container, footer. They are all independent from each other.
TyStream is designed to stream fragments asynchronously to the clients. Without any single XHR from browser, all fragments are delivered to clients when their data is ready. Like single page application but fully server side rendered. So it makes it SEO friendly and great for e-commerce websites. TyStream shows placeholders on the clients browser while it fetches your data then replaces placeholder with real content. So it is really improving your time to first byte
You can easily improve your Speed Index!
This is not a valid TyStream usage, please see usage details below
Whenever user provides a html to TyStream, TyStream converts it to stream friendly format and flushes to user asynchronously.
Lets assume that our header service responds in 300 ms and product service in 140ms.
<html>
<head>
<milla-head></milla-head>
</head>
<body>
<fragment name="header" css="pathtocss" js="pathtojs"></fragment>
<div>A static content</div>
<fragment name="product" css="pathtocss" js="pathtojs"></fragment>
</body>
</html>
Converted:
<html>
<head>
<style>/* Fragment styles */</style>
<script>/*Really small TyStream js. 118bytes*/</script>
</head>
<body>
<div id="p_0">Header placeholder</div>
<div>A static content</div>
<div id="p_1">Product placeholder</div>
<!-- User started load html dependencies, css files etc and your website is already rendered -->
... 140ms
<!-- TyStream recieved product data and flushed product content and js -->
<div id="c_1" hidden></div>
<script>/*use head script to change c_1 p_1; run header script */</script>
<!-- Product is ready to be used -->
... 160ms
<!-- TyStream recieved header data and flushed product content and js -->
<div id="c_1" hidden></div>
<script>/*use head script to change c_1 p_1; run header script */</script>
<!-- header is ready to be used -->
</body>
</html>
TyStream closes the stream.
Using npm
npm install TyStream --save
Using yarn
yarn add milla
You can check out demo folder
First of all, you should create a page html file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TyStream Title</title>
<milla-head></milla-head>
</head>
<body>
<fragment name="header" js="../test/dependencies/8.js" css="../test/dependencies/8.css"></fragment>
<div>Middle Content</div>
<fragment name="product" js="../test/dependencies/8_1.js"></fragment>
</body>
</html>
Then use your page file in your express route.
const TyStream = require('milla');
/* Optional, you can find default configs under src/configuration */
TyStream.config.set({
minifyJs: false,
minifyCss: false,
minifyHtml: false
});
/* Create express route */
app.get('/', TyStream.express({
htmlFile: path.join(__dirname, '../test/html/test8.html'), //Html with fragments
data: { //fragment datas. You can use () => {}, {}, () => new Promise. TyStream will handle them in most efficient way.
header: (req) => {
return {
header: {
menu: ['Item 1', 'Item 2', 'Item 3']
}
}
},
product: (req) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({product:{name:'Test'}});
}, 4000 * Math.random())
});
}
},
fragments: { //Fragment rendering functions. (input) is coming from data. You can use your favorite template engine here (anything that returns string).
header: {
content: (input) => JSON.stringify(input)
},
product: {
placeholder: () => '<div>Product placeholder</div>',
content: (input) => {
return JSON.stringify(input);
}
}
}
}));
Thats all! You have a great progressive rendering now.