suchitadoshi
suchitadoshi1987
suchita009
suchita009#4368
xinganwang
xg-wang
xinganwang
xg-wang#5846
Thomas
xinganwang
xg-wang
xinganwang
xg-wang#5846
Suchita
image credits:
http://www.themarketingsage.com/wp-content/uploads/2015/08/about-me-leon-severan-we-buy-houses.jpg
suchitadoshi
suchitadoshi1987
suchita009
suchita009#4368
Gardening
Cricket
Mechanical
Keyboards ❤️
Suchita
image credits:
https://i.gifer.com/CVU.gif
Gardening
Suchita
image credits:
https://i.gifer.com/CVU.gif
Know the team their requirements
Know the team their requirements
Server side rendering powered by FastBoot
Know the team their requirements
Server side rendering powered by FastBoot
Build time optimization with Embroider
Know the team their requirements
Server side rendering powered by FastBoot
Build time optimization with Embroider
Roadmap for FastBoot
An enthusiastic Ember developer.
An awesome company that uses Ember JS
Recently upgraded to Ember Octane
image credits:
https://media.slid.es/uploads/1278854/images/8238706/PinClipart.com_company-clipart_11891.png
Faster content to the end user
image credits:
https://i.gifer.com/41C.gif
Faster content to the end user
Improved user engagement
image credits:
https://i.gifer.com/41C.gif
https://qph.fs.quoracdn.net/main-qimg-e980c1173022b1e27482699556c1afce
Faster content to the end user
Improved user engagement
Improved search indexing
image credits:
https://i.gifer.com/41C.gif
https://qph.fs.quoracdn.net/main-qimg-e980c1173022b1e27482699556c1afce
https://images.squarespace-cdn.com/content/v1/sign.gif
(SSR)
SSR Solution for Ember JS
ember install ember-cli-fastboot
image credits:
web.dev/vitals/
image credits:
web.dev/vitals/
LCP
app js
api requests
vendor js
HTML + CSS
HTML + CSS
LCP
vendor js
app js
📦
ember install ember-cli-fastboot
ember s/** @pintomodule */
import {Request as AsyncRequest} from 'google3/javascript/apps/wiz/async/async';
import {Controller} from 'google3/javascript/apps/wiz/controller/controllerbase';
import {registerController} from 'google3/javascript/app';
export class MqnXScrollAreaController extends Controller {
private syncService: SyncScrollService|null = null;
private aestheticScrollBar: AestheticScrollBar|null = null;
private readonly dragController: MqnXDraggableScrollController;
static override deps(): AsyncRequest {
return {
controller: {
dragController: xid('drag'),
}
};
}
constructor(response: mqnXScrollAreaControllerWiz.Response) {
super(response.superResponse);
this.dragController = response.controller.dragController;
}
onRender() {
console.log('Transformers Prototype: MqnXScrollAreaController.onRender');
const moduleElement = this.getRoot().el() as HTMLElement;
}
override disposeObject() {
super.disposeObject();
}
}
const ATTR = {
CONTENTS: 'mqn-scroll-bar-contents',
BAR: 'mqn-scroll-bar',
};
registerController(mqnXScrollAreaControllerWiz.id, MqnXScrollAreaController);import {MqnController} from '../mqn-controller';
import {MqnXDraggableScrollController} from './mqn-x-draggable-scroll';
import {MqnAestheticScrollBarController} from './mqn-aesthetic-scroll-bar';
import {SyncScrollService} from '../mqn-lib/sync-scroll-service';
export class MqnXScrollAreaController extends MqnController {
private readonly aestheticScrollBar: MqnAestheticScrollBarController;
private readonly subControllers: MqnController[];
private readonly syncService: SyncScrollService;
constructor(
moduleElement: HTMLElement,
scrollAreas: HTMLElement[],
scrollBar?: HTMLElement
) {
super(moduleElement, 'xScrollAreaCtrl');
// The Scrollbar and Dragging are separated so they can be
// used separately as needed.
// They are synced via a shared service instance.
this.syncService = new SyncScrollService(scrollAreas);
this.aestheticScrollBar = null;
this.subControllers = [
new MqnXDraggableScrollController(
moduleElement,
'xDraggableScroll',
scrollAreas,
this.syncService
),
];
}
public updateDom(): void {
this.aestheticScrollBar?.updateDom();
}
public dispose(): void {
super.dispose();
this.subControllers.forEach(ctrl => ctrl.dispose());
this.syncService.dispose();
}
}child controllers
wombat module
wiz component
Faster content to the end user
Improved user engagement
Improved search indexing
image credits:
https://i.gifer.com/41C.gif
https://qph.fs.quoracdn.net/main-qimg-e980c1173022b1e27482699556c1afce
https://images.squarespace-cdn.com/content/v1/sign.gif
Faster content to the end user
Improved user engagement
Improved search indexing
image credits:
https://i.gifer.com/41C.gif
https://qph.fs.quoracdn.net/main-qimg-e980c1173022b1e27482699556c1afce
https://images.squarespace-cdn.com/content/v1/sign.gif
Faster content to the end user
Improved user engagement
Improved search indexing
image credits:
https://i.gifer.com/41C.gif
https://qph.fs.quoracdn.net/main-qimg-e980c1173022b1e27482699556c1afce
https://images.squarespace-cdn.com/content/v1/sign.gif
Faster content to the end user
Improved user engagement
Improved search indexing
image credits:
https://i.gifer.com/41C.gif
https://qph.fs.quoracdn.net/main-qimg-e980c1173022b1e27482699556c1afce
https://images.squarespace-cdn.com/content/v1/sign.gif
image credits:
https://media2.giphy.com/media/3o6Mbl0kpk4i9G2GCQ/source.gif
media credits:
https://www.nick.com/
a modern build system for EmberJS apps
yarn add --dev @embroider/core @embroider/compat @embroider/webpack @embroider/router// ember-cli-build.js
const { Webpack } = require('@embroider/webpack');
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function (defaults) {
let app = new EmberApp(defaults, {});
return require('@embroider/compat').compatBuild(app, Webpack, {
staticAddonTestSupportTrees: true,
staticAddonTrees: true,
staticHelpers: true,
staticComponents: true,
splitAtRoutes: [
'editor',
'settings',
'register',
'login',
'articles',
'profile'
],
});
};// app/router.js
import EmberRouter from '@embroider/router';
import config from 'ember-realworld/config/environment';
export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
}
Router.map(function () {
this.route('editor', function () {
this.route('edit', { path: ':id' });
});
this.route('settings');
this.route('register');
this.route('login');
this.route('articles', function () {
this.route('article', { path: ':id' });
});
this.route('profile', { path: 'profile/:id' }, function () {
this.route('favorites');
});
});
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { htmlSafe } from '@ember/template';
export default class ArticleContentComponent extends Component {
@tracked marked = null;
constructor() {
super(...arguments);
import('marked').then((module) => {
this.marked = module.default;
});
}
get safeMarkup() {
return htmlSafe(this.marked?.(this.args.article.body));
}
}Impact of enabling Embroider on a LinkedIn application
Impact of enabling Embroider on a LinkedIn application
| Initial JavaScript | Transferred Size | Parsed Size |
|---|---|---|
| Classic (baseline) | 1.77MB | 9.25MB |
| Embroider | 1.15MB(-35%) | 5.03MB(-46%) |
| Loading Time | Estimated improvement | Percentage |
|---|---|---|
| Total page load time | -256ms [-400ms to -140ms] | -6.89% [-10.75% to -3.77%] |
| Time to JS execution | -258ms [-342ms to -197ms] | -12.69% [-16.83% to -9.72%] |
cpuThrottleRate: 4, network: fast-3g
Impact of enabling Embroider on a LinkedIn application
| Build Time | Cold Start | Warm Start | Live Reload |
|---|---|---|---|
| Classic (baseline) | 139s | 80s | 3.5s |
| Embroider | 59s (-58%) | 58s (-28%) | 0.7s(-80%) |
✂️ Less code shipped to users
🚀 Faster page load time
⚡ Faster build speed
image credits:
https://media2.giphy.com/media/3o6Mbl0kpk4i9G2GCQ/source.gif
image credits:
https://i1.wp.com/www.smartprix.com/bytes/wp-content/uploads/2020/11/ShrillWildFruitfly-size_restricted.gif
image credits:
https://media3.giphy.com/media/IeXz4ljIbZHS1BUkR3/giphy.gif