惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
Lohrmann on Cybersecurity
Martin Fowler
Martin Fowler
Engineering at Meta
Engineering at Meta
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Azure Blog
Microsoft Azure Blog
G
Google Developers Blog
TaoSecurity Blog
TaoSecurity Blog
博客园_首页
Vercel News
Vercel News
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
The Exploit Database - CXSecurity.com
量子位
Project Zero
Project Zero
A
Arctic Wolf
小众软件
小众软件
NISL@THU
NISL@THU
C
CERT Recently Published Vulnerability Notes
有赞技术团队
有赞技术团队
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
News and Events Feed by Topic
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
P
Privacy & Cybersecurity Law Blog
Security Latest
Security Latest
B
Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
Schneier on Security
Schneier on Security
The Hacker News
The Hacker News
K
Kaspersky official blog
C
Check Point Blog
Hacker News: Ask HN
Hacker News: Ask HN
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Webroot Blog
Webroot Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
人人都是产品经理
人人都是产品经理
AI
AI
Cisco Talos Blog
Cisco Talos Blog
MyScale Blog
MyScale Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
S
Schneier on Security
P
Palo Alto Networks Blog

Ember.js Blog

Ember 7.0 Released Announcing the Official TypeScript Types Public Preview Accessibility Working Group Update The 2020 Ember Roadmap Countdown to The New Year - Built-in Addons Countdown to The New Year - Ember Exam Countdown to The New Year - Ember Code Snippet Countdown to The New Year - Ember Changeset Countdown to The New Year - Ember In Viewport Countdown to The New Year - Ember CLI Update Countdown to The New Year - Ember Template Invocation Location Countdown to The New Year - Ember CLI TypeScript Countdown to The New Year - Ember Bootstrap and Ember Paper Countdown to The New Year - Ember CSS Modules Countdown to The New Year - Ember Mapbox GL Countdown to The New Year - Ember Shepherd Countdown to The New Year - Ember Template Lint Countdown to The New Year - Ember Composable Helpers Countdown to The New Year - Ember Leaflet Countdown to The New Year - Ember Intl Countdown to The New Year - Ember Test Selectors Countdown to The New Year - Ember Power Select Countdown to The New Year - Ember Simple Auth Countdown to The New Year - Ember SVG Jar Countdown to The New Year - Ember Page Title Countdown to The New Year- Ember A11Y Testing Countdown to The New Year - Ember Angle Brackets Codemod Countdown to The New Year - Ember CLI Sass Countdown to The New Year - Ember Animated Countdown to The New Year - Ember Auto Import Countdown to The New Year - Ember Concurrency Countdown to The New Year - Ember Tether Countdown to The New Year - Ember Modifier Countdown to The New Year - Ember CLI Mirage Countdown to The New Year - Ember Sortable Coming Soon in Ember Octane - Part 5: Glimmer Components Coming Soon in Ember Octane - Part 4: Modifiers Coming Soon in Ember Octane - Part 3: Tracked Properties Coming Soon in Ember Octane - Part 2: Angle Brackets & Named Arguments Preview Weekend: 2019 Ember Community Survey Coming Soon in Ember Octane - Part 1: Native Classes First Annual DecEmber Event! 2018 Ember Community Survey 2017 Ember Community Survey Announcing The Glimmer 2 Alpha Upcoming deprecation of baseURL in Ember CLI 2.7 2016 Ember Community Survey Announcing Ember Core Team Face to Face, January 2016 Ember.js 1.13.0 and 2.0 Beta Released Another Ember 2.x Status Update Ember.js 1.12 and 1.13 Beta (Glimmer!) Released Ember.js 1.11.1 Released Ember.js 1.11.0 and 1.12 Beta Released Ember.js 1.10.0 and 1.11 Beta Released Compiling templates with Ember 1.10 Core Team Meeting Minutes - 2014/08/01 Core Team Meeting Minutes - 2014/08/14 Core Team Meeting Minutes - 2014/09/12 Cleaning Up Github Issues Core Team Meeting Minutes - 2014/07/11 Core Team Meeting Minutes - 2014/07/25 Core Team Meeting Minutes - 2014/06/13 Core Team Meeting Minutes - 2014/06/20 Core Team Meeting Minutes - 2014/06/27 Core Team Meeting Minutes - 2014/06/06 Core Team Meeting Minutes - 2014/04/25 Core Team Meeting Minutes - 2014/04/04 Ember 1.5.0 and 1.6 Beta Released Core Team Meeting Minutes - 2014/03/07 Core Team Meeting Minutes - 2014/03/14 Core Team Meeting Minutes - 2014/03/21 Core Team Meeting Minutes - 2014/02/28 Core Team Meeting Minutes - 2014/02/21 Core Team Meeting Minutes - 2014/02/14 Ember 1.4.0 and 1.5 Beta Released Core Team Meeting Minutes - 2014/01/27 Core Team Meeting Minutes - 2014/01/31 Core Team Meeting Minutes - 2014/02/07 Core Team Meeting Minutes - 2014/01/17 Core Team Meeting Minutes - 2014/01/03 Ember 1.3.0 and 1.4 Beta Released Core Team Meeting Minutes - 2013/12/20 Core Team Meeting Minutes - 2013/12/06 Ember 1.2.0 and 1.3 Beta Released Ember 1.1.2 Released Ember 1.1.1 and 1.2 Beta Released Ember 1.0 Released Ember 1.0 RC8 Released Ember 1.0 RC7 Released Ember 1.0 RC6.1, RC5.1, RC4.1, RC3.1, RC2.1 RC1.1 Released Ember 1.0 RC6 Ember 1.0 RC5 Ember 1.0 RC4 Ember 1.0 RC3 Announcing the Ember.js Security Policy Ember 1.0 RC2 Ember 1.0 RC Ember 1.0 Prerelease 2 Ember 1.0 Prerelease
Inside FastBoot: The Road to Server-Side Rendering
2014-12-22 · via Ember.js Blog

Using JavaScript to write fast, interactive web applications has exploded in popularity over the past few years. JavaScript apps offer many strengths over traditional server-rendered applications. Most notably, rich interactions and lightning-fast responses to user clicks allow for UIs that previously were only the domain of native apps.

The first JavaScript-heavy applications were productivity apps, and the experience of loading an app on the web, even with a spinner, was far better than the equivalent experience of downloading and installing a native app.

Increasingly, though, content-rich destinations such as news or video sites are starting to move to JavaScript to gain the benefits of improved interactivity. Unlike productivity apps, where the user logs in once at the beginning of the day and stays logged in, content sites are loaded many times per day, often via search engines or social sharing.

In this context, where the JavaScript app looks like a "normal" web page, loading spinners or long delays feel out-of-place and not very web-like. Indeed, this is the reason that Twitter migrated from a client-side JavaScript approach back to server-rendered content.

Being able to boot JavaScript apps on the server and "rehydrate" in the browser has been considered a Holy Grail for some time. However, most attempts have focused solely on rendering the view layer on the server into HTML. This is an important step, but this alone does not sufficiently solve the problem.

Solving the whole problem involves not only the view layer, but also the entire lifecycle of booting an application: routing, fetching models, and rendering. By leaning heavily on Ember's conventional application structure, we can move this complexity out of each application and into the framework.

We are building this feature into Ember.js, and we're calling it FastBoot.

FastBoot will allow you to deliver the HTML and CSS for a page in your Ember app right away, then allow the JavaScript to take over once it has finished loading. Your Ember app will behave no differently than server-rendered apps when it comes to search engines, mobile users, cURL, or users who turned off JavaScript.

For everyone else, you'll still have the responsiveness and interactivity users have come to expect from Ember apps.

Because of the Ember community's strong focus on conventional app structure, we believe that we can make server rendering so simple to enable and deploy that, in the long run, very few Ember apps would choose not to use it.

In this series of blog posts, we will demystify our efforts, and talk about implementation details. We will also give you a sense of our progress. Like every Ember feature, FastBoot will be landing a bit at a time, so every new release will unlock more capabilities. As features land, we will talk about how you can take advantage of them in your own apps.

The Journey So Far

From the beginning, we knew that we would eventually want to tackle running JavaScript apps on the server, but we didn't want to bet Ember on a boil-the-ocean effort to solve every aspect of client-side development at once.

That being said, we have always kept this feature in mind as we were architecting the framework. We carefully isolated all parts of the system that depend on a full-fledged browser environment.

Even during the most recent HTMLBars effort, which is inherently a DOM-based rendering engine, we made sure to use an abstraction whenever we touched the DOM, so that we could swap it out for something else on the server. Similarly, when we designed the router, all communication with the URL went through a "location" abstraction, instead of touching the URL bar directly. The routing microlibraries we built (router.js and route-recognizer) were designed from the beginning to be decoupled from the DOM.

Because of this, we were able to get the Ember framework executing in Node in one day, and were able to get an app completely booted and routing in under a week.

Abstracting Feature Detection

One of the first problems we encountered when trying to execute Ember in node was top-level feature detection. Because Ember previously assumed it was running inside a browser, it inadvertently relied on the existence of basic DOM APIs, like window, the document and navigator.

While the vast majority of the subsequent code was resilient to environments without a DOM, the feature detection and helpful assertion messages ("you're using an old version of jQuery") was sloppy because it historically wasn't expecting to run in Node.

To address this issue, we moved all top-level assumptions into an environment abstraction. If you look at it, it's really boring; it lets top-level code throughout the framework quickly short-circuit if basic DOM facilities are missing.

The Container and Session

Ember's powerful dependency injection ("DI") system has been a boon for managing application state, supporting the transition from globals to modules, and ensuring tests are fast and robust.

Rather than storing application state globally (either in a global variable or as a property on a global object like App), all state in an idiomatic Ember app is stored inside an object called the "container". As a result, state can be thrown away between each automated test, ensuring you're testing what you think you're testing and not the side-effects of a previous test. It also improves the speed of tests, allowing you to run your test suite as you develop instead of waiting hours for a CI server.

The container also serves as a registry of your application code, and its "resolver" paved the way for Ember to move from globals-based code to JavaScript modules by abstracting lookups (e.g. Ember asking for a controller named "users") from the actual location of code.

The good news is that this means that the internals of Ember always look up (and create) objects through the container.

Unfortunately, we made a minor mistake in our original design. Currently, every application has only a single container. This assumption works fine when running your application in the browser, since you only load and run the application once per browser page load.

This also works fine in tests, with the exception that we are doing more work than absolutely necessary between each test run. In essence, we conflated the "code registry" and "application state" responsibilities into the same container object. Between test runs, we throw away the container to reset application state, but by also throwing out the code registry, which doesn't change between tests, we are throwing the baby out with the bath water.

Architecture diagram showing state and code registry inside same Application object

When running on the server, however, we realized that a single Ember application needs to be able to continue serving requests even if a previous request is waiting for an async operation (such as fetching a model) to complete.

This means that we needed to tweak our approach and allow applications to host multiple of what we call "sessions" at a time. Sessions allow us to separate the code registry (which doesn't change once the app is booted) from the application state.

Architecture diagram showing state extracted into Session objects

This approach also has a side-benefit for testing: it allows us to reduce the amount of work we need to do between each test.

Both of these efforts (breaking out an environment and the design of the session) are incremental pieces that provide value on their own, and have already landed on master branch thanks to the tireless work of Dan Gebhardt. Working with LinkedIn and Bustle closely has helped us to work through the initial requirements, and identify steps that we could take that would help enterprising teams make progress while we take the next steps.

Next Steps

In the coming weeks, we are going to dive head-first into HTMLbars, getting it ready for its new life running inside a Node.js environment. We'll start by making sure that the DOMHelper abstraction is used everywhere that interacts with the DOM, providing us a chokepoint to implement a fake DOM on the server that builds up strings of HTML instead of interacting with a real DOM.

We plan on keeping you updated with more posts in the Inside FastBoot series as we continue to make progress, so please stay tuned for more!