SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS [email protected], !...

105
ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS [email protected], @MATTITAHVONEN, GITHUB.COM/MSTAHV

Transcript of SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS [email protected], !...

Page 1: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

A D V E N T U R E S I N

S E O A N D S I N G L E - P A G E W E B A P P S

M AT T I @ V A A D I N . C O M , ! @ M AT T I TA H V O N E N , G I T H U B . C O M / M S TA H V

5

S T O R Y A N D P H I L O S O P H Y

Software is eating the world and what most of us see of it is the user interface. The user

interface has become the key component of how the users experience the business

behind it. Competition is lost or won due to user experience. Simplicity is king and the

users get frustrated by anything ugly, slow or not working on the device they happen to

use at the time. We at Vaadin fight for simplicity and invite everyone to join this fight.

Together we want to build a user interface that puts a smile on the user’s face.

Vaadin is the technology that empowers developers to build the best web-apps for

business purposes. Our priority over everything else is developer productivity because

we believe that by simplifying the developer experience and saving the developer’s

time, they are best able to focus on building great user interfaces.

Our brand is what we want everyone to think about us. When everyone - both us and

the people around us - have a consistent understanding of what Vaadin is and what we

stand for, it enables that image to spread and amplify. This book defines what we want

that image to be. It defines what the Vaadin brand is.

I hope that You are as excited and proud of living and breathing the Vaadin brand as

I am. You are the one who is shaping what everyone thinks about Vaadin - using this

brand as a tool and a guideline every day.

Let’s fight for simplicity for both the users and the developers!

Joonas Lehtinen

Founder & CEO

Vaadin

I N T R O D U C T I O N

Page 2: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 3: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Why this topic?

Over 10 years at Vaadin with SPAs

Over 20 years hacking web

Nicolas Fränkel

Page 4: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

things you'll learn

1. What are SPAs and why they are problematic with search engines?

2. You learn to consider if SPAs is really the best fit for your requirements. *)

3. Traditional and modern ways to make your SPA cope with search engines

4. SPAs can be search engine compatible!

*) I hope I don’t get fired questioning SPAs 😜

Page 5: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

SEO?

• Lot of things affect how well your page is found, too wide subject for conference presentation

• Cheating or helping search engines and users?

• In this session:

• On-Page SEO (in SPAs)

• SoMe social media integration (related)

Page 6: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

do you need SEO?

• Not necessarily!

• Web app vs web site

• Often quite black and white

• 71.3% of vaadin.com visitors come via search engines!

Page 7: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

S I N G L E - P A G E W E B A P P S ?

Page 8: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

A single-page application (SPA)

• No page reloads, “full AJAX” web apps

• JavaScript powered client side “rendering”

• New data (or views) loaded with XHR/JSONP/Websocket

• Faster interaction -> desktop like UX

Page 9: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

demo.vaadin.com/dashboard

Page 10: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

MyController.java my-view.template.html

my-view.css

my-view.js

@RestController @RequestMapping("/analytics") public class AnalyticsController {

@Autowired PatientsRepository patientsRepository;

@RequestMapping(path = "/age", method = RequestMethod.GET) public Response getByAge() { ... }

@RequestMapping(path = "/length", method = RequestMethod.GET) public Response getByLength() { ... } ... ...

<nav> <a href="/analytics/age" routerLinkActive="active">Age</a> <a href="/analytics/doctor" routerLinkActive="active">Doctor</a> <a href="/analytics/gender" routerLinkActive="active">Gender</a> </nav> ...

nav { justify-content: center; text-transform: uppercase; margin-bottom: 50px; } ...

getAnalytics(grouping: string = 'age') { return this.http .get(`${this.config.API_URL}/analytics/${grouping}`) .map(res=>res.json()); } ...

Page 11: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

F F SF I G H T F O R S I M P L I C I T Y

Page 12: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

new TextField(); new Button("Click me");

Page 13: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

new HorizontalLayout( new TextField(), new Button("Click me") );

Page 14: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

new VerticalLayout( new TextField(), new Button("Click me") );

Page 15: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

layout = new VerticalLayout(); textField = new TextField(); button = new Button("Click Me");

button.addClickListener(click -> layout.addComponent( new Label(textField.getValue()) ));

Page 16: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

TextField name = new TextField(); Button button = new Button("Greet"); layout.addComponents(name, button);

button.addClickListener(click -> { Notification.show("Hi, " + name.getValue()); });

Page 17: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Initial HTML CSS JavaScript

(provided by the Framework)

~300k

Page 18: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 19: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

{name: {value: 'Marcus'}, button: {event: 'clicked'}}

261 bytes

Page 20: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

TextField name = new TextField(); Button button = new Button("Greet"); layout.addComponents(name, button);

button.addClickListener(click -> { Notification.show("Hi, " + name.getValue()); });

Page 21: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

{name: {value: 'Marcus'}, button: {event: 'clicked'}}

261 bytes

{new: [ {notification: 'Hi, Marcus'} ]}

267 bytes

Page 22: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

save = new Button("Save", e -> { Notification.show(person.toString()); });

private TextField firstName; private TextField lastName;

person = new Person();

binder = new Binder<>( Person.class);

binder.bindInstanceFields(this);

Page 23: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

@Autowired private PersonService service;

Grid<Person> grid = new Grid<>();

// If you want custom columns grid.addColumn("First name", Person::getFirstName); grid.addColumn("Last name", Person::getLastName); grid.addColumn("Email", Person::getEmail);

grid.setItems(service.getPeople());

Page 24: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

@Autowired private PersonService service;

Grid<Person> grid = new Grid<>();

grid.addColumn("First name", Person::getFirstName); grid.addColumn("Last name", Person::getLastName); grid.addColumn("Email", Person::getEmail);

grid.setDataSource( new BackEndDataSource<>( q -> service.getPeople( q.getOffset(), q.getLimit()) .stream(), q -> service.count()));

Page 25: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

nav = new Navigator(this, navOutlet); nav.addView("", new DemoView("Hello, I'm view 1")); nav.addView("view2", new DemoView("Hello, I'm view 2"));

navBar = new HorizontalLayout(); navBar.addComponent( new Button("view1", click -> nav.navigateTo(""))); navBar.addComponent( new Button("view2", click -> nav.navigateTo("view2")));

CssLayout navOutlet = new CssLayout(); addComponents(navBar, navOutlet);

Page 26: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

$v-background-color: hsl(210, 0%, 100%);

Page 27: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

$v-background-color: hsl(210, 0%, 33%);

Page 28: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

$v-background-color: hsl(210, 0%, 100%); $v-border: 2px solid v-shade; $v-border-radius: 0; $v-bevel: false; $v-gradient: false; $v-shadow: false;

Page 29: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

SPA challenges

• Initial load time

• Multiple languages • Except in Vaadin’s approach

• Client-Server programming model • Except in Vaadin’s approach

• Back button support

• Deep linking

• Analytics

• Search engine optimisation

Page 30: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

SPA is not always the best solution!

• Site vs app

• Public vs private

• Sweet spot is private web app

• Consider “hybrid solutions”

App

Public Private

Site

Page 31: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 32: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 33: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 34: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 35: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

S P A ⚡ S E O

W H Y ?

Page 36: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

SPA ⚡ SEO

• Crawling + JavaScript

• Deep linking

• DOM in SPAs

Page 37: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Crawling + JavaScript rendering

• Traditionally no JS support at all in bot

• Bots are getting better, e.g. content in Vaadin apps today:

• Google ✅

• Bing/Yahoo ✅

• Yandex 🚫

• Related : most social media integrations 🚫

Page 38: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Deep linking

• Happens automatically in traditional web sites

• SPAs have no real page changes, no natural URLs

• Traditionally hacked with URI fragments (with hack² for SEO)

• HTML5 History API solves this

• IE 11+ & other modern browsers

Page 39: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

DOM in SPAs

• Components libraries often used in SPAs don’t necessarily use tag names relevant for bots (A, H1/H2…, TITLE, META tags)

• Navigating to another view might not happen with a link click, but with other element click, scrolling, gesture…

• Some content/links not always visible

Page 40: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

S P A & S E O

H O W ?

Page 41: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

SPA SEO techniques• Generic SEO techniques apply,

• Helping bots to crawl your site: • deep linking

• “hashbang” • History API

• Sitemaps • Content:

• Providing extra data for bots • <noscript>,<title> <meta> tags • serving custom non-SPA content for bots

• Pre-rendering

Page 42: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

# ! H A S H B A N G !

Page 43: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Curiosity

#1 search engine company is probably the #1 SPA advocate.

Page 44: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Hashbang technique1. special syntax of hash part of url means SE

should consider it as a “page”

2. Special hacks in browser (with iframes) to add entries to browser’s history (back button support)

3. special rules to convert hash into query parameter

4. special rules for the server side to render the same content for SE

Page 45: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Server will never get the part starting from #

Page 46: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 47: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

#! ⬌ ?_escaped_fragment_=

1. Bot detects #! urls as logical pages

2. Bot converts #! into special query parameter ?_escaped_fragment_=

3. Server returns a “pre-rendered” version for _escaped_fragement_ parameters

4. Search engine displays hashbang URLs

Page 48: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Escaped fragment rendering:

Page 49: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Hashbang technique• Kind of solves the SPAs SEO incompatibility

• Heavy to implement

• Invented by Google in 2009

• Deprecated by Google in 2015 (but still functional)

• GoogleBot (and some other crawlers) understand JS and actually render the page

• HTML5 History API and normal URLs!

Page 50: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

H T M L 5 H I S T O R Y A P I

Page 51: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

History API

• JS API to access browsers history (with certain limitations of course)

• history.back(), history.forward()

• supports adding new entries and listening to changes

• browser support since IE 10

Page 52: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

History API: pushState method

• Adds new entry to history

• parameters:

• state object

• title

• URL

Page 53: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

History API: replaceState method

• Modifies the current entry in history

• otherwise like pushState

Page 54: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

History API: PopState event

• Technically in window: window.onpopstate

• catch back/forward button click

• Naturally can be used to track just “in-page” navigation

Page 55: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• Much cleaner solution than hashbang style

• You should use it today, unless really old browsers needs to be supported

• Together with possible JS support in bots, no server side hacks or pre-rendering needed

History API for SPA deep linking

Page 56: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• Vaadin Framework 7: History add-on

• Low level support

• Navigator support: automatic modern SPA deep linking

• Will be supported by default in Vaadin 8

• Code examples…

History API: usage example

Page 57: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

H O W A B O U T M E TA TA G S ? A K A

W E S T I L L N E E D T H E S E R V E R - S I D E

Not just with Vaadin Framework :-)

Page 58: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Meta tags?• Provides extra details for crawlers and other

bots

Page 59: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• GoogleBot at least sometimes seems to pick up dynamically generated meta tags

• No-go with social media bots like Twitter and Google

• For perfect SEO, you’ll still need the server side.

Meta tags and bots

Page 60: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• The code…

Meta tags example

Page 61: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

S P A S E O : T I P S A N D T R I C K S

Page 62: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• If you want to see what a certain page looks like for bots, paste the URL directly to browser

• All relevant state for a logical page must be in URL for the server

Tip 1: Think like the bot

Page 63: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• SPAs often contain dynamic content

• Menus

• Lazy loaded content

• Bots most probably never see dynamically loaded content!

• SPAs don’t necessarily use A elements for navigation

Tip 2: Ensure pages are referred

Page 64: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• Standard xml files that describe your site content

• Submitted to search engines manually or preferably with a hint in robots.txt file

• Easiest way to ensure your whole SPA is indexed

Tip 3: Sitemaps

Page 65: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• Not all search engine bots support JavaScript either, you’ll get at least something relevant for the index

• For most social media meta tags, only server side generated tags are valid (open graph, twitter etc)

Tip 4: Server generated meta tags

Page 66: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

• Heavy to implement, consider if you aim for best possible SEO

• Strategies:

• Manually with server side code, user agent detection or hash bang urls

• “Shadow URL” with redirect to SPA

• PhantomJS pre-rendering, prerender.io

• https://github.com/greengerong/prerender-java

Tip 5: Server side pre-rendering

Page 67: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

T H A N K Y O U5

S T O R Y A N D P H I L O S O P H Y

Software is eating the world and what most of us see of it is the user interface. The user

interface has become the key component of how the users experience the business

behind it. Competition is lost or won due to user experience. Simplicity is king and the

users get frustrated by anything ugly, slow or not working on the device they happen to

use at the time. We at Vaadin fight for simplicity and invite everyone to join this fight.

Together we want to build a user interface that puts a smile on the user’s face.

Vaadin is the technology that empowers developers to build the best web-apps for

business purposes. Our priority over everything else is developer productivity because

we believe that by simplifying the developer experience and saving the developer’s

time, they are best able to focus on building great user interfaces.

Our brand is what we want everyone to think about us. When everyone - both us and

the people around us - have a consistent understanding of what Vaadin is and what we

stand for, it enables that image to spread and amplify. This book defines what we want

that image to be. It defines what the Vaadin brand is.

I hope that You are as excited and proud of living and breathing the Vaadin brand as

I am. You are the one who is shaping what everyone thinks about Vaadin - using this

brand as a tool and a guideline every day.

Let’s fight for simplicity for both the users and the developers!

Joonas Lehtinen

Founder & CEO

Vaadin

I N T R O D U C T I O N

M AT T I @ V A A D I N . C O M , ! @ M AT T I TA H V O N E N , G I T H U B . C O M / M S TA H V

Page 68: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

40% of Fortune 100 companies use Vaadin

150k+ active developers

#2 Java Web Frameworkaccording to Open HUB stats

Apache 2.0

Page 69: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

things you'll learn

1. What it takes to build a modern web app

2. The building blocks of Vaadin

3. How to build a full stack app in 30 minutes

Page 70: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

M O D E R N W E B A P P S

Page 71: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

demo.vaadin.com/dashboard

Page 72: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

MyController.java my-view.template.html

my-view.css

my-view.js

@RestController @RequestMapping("/analytics") public class AnalyticsController {

@Autowired PatientsRepository patientsRepository;

@RequestMapping(path = "/age", method = RequestMethod.GET) public Response getByAge() { ... }

@RequestMapping(path = "/length", method = RequestMethod.GET) public Response getByLength() { ... } ... ...

<nav> <a href="/analytics/age" routerLinkActive="active">Age</a> <a href="/analytics/doctor" routerLinkActive="active">Doctor</a> <a href="/analytics/gender" routerLinkActive="active">Gender</a> </nav> ...

nav { justify-content: center; text-transform: uppercase; margin-bottom: 50px; } ...

getAnalytics(grouping: string = 'age') { return this.http .get(`${this.config.API_URL}/analytics/${grouping}`) .map(res=>res.json()); }

Page 73: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

F F SF I G H T F O R S I M P L I C I T Y

Page 74: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

new TextField(); new Button("Click me");

Page 75: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

new HorizontalLayout( new TextField(), new Button("Click me") );

Page 76: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

new VerticalLayout( new TextField(), new Button("Click me") );

Page 77: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

layout = new VerticalLayout(); textField = new TextField(); button = new Button("Click Me");

button.addClickListener(click -> layout.addComponent( new Label(textField.getValue()) ));

Page 78: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

save = new Button("Save", e -> { // try-catch binder.writeBean(person);

Notification.show( person.toString()); });

private TextField firstName; private TextField lastName;

person = new Person();

binder = new BeanBinder<>( Person.class);

binder.bindInstanceFields(this);

Page 79: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

@Autowired private PersonService service;

Grid<Person> grid = new Grid<>();

grid.addColumn("First name", Person::getFirstName); grid.addColumn("Last name", Person::getLastName); grid.addColumn("Email", Person::getEmail);

grid.setItems(service.getPeople());

Page 80: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

@Autowired private PersonService service;

Grid<Person> grid = new Grid<>();

grid.addColumn("First name", Person::getFirstName); grid.addColumn("Last name", Person::getLastName); grid.addColumn("Email", Person::getEmail);

grid.setDataSource( new BackEndDataSource<>( q -> service.getPeople( q.getOffset(), q.getLimit()) .stream(), q -> service.count()));

Page 81: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

nav = new Navigator(this, navOutlet); nav.addView("", new DemoView("Hello, I'm view 1")); nav.addView("view2", new DemoView("Hello, I'm view 2"));

navBar = new HorizontalLayout(); navBar.addComponent( new Button("view1", click -> nav.navigateTo(""))); navBar.addComponent( new Button("view2", click -> nav.navigateTo("view2")));

CssLayout navOutlet = new CssLayout(); addComponents(navBar, navOutlet);

Page 82: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

$v-background-color: hsl(210, 0%, 100%);

Page 83: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

$v-background-color: hsl(210, 0%, 33%);

Page 84: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

$v-background-color: hsl(210, 0%, 100%); $v-border: 2px solid v-shade; $v-border-radius: 0; $v-bevel: false; $v-gradient: false; $v-shadow: false;

Page 85: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 86: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 87: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

[insert code here]

Page 88: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

" github.com/vaadin-marcus/spring-boot-todo

Page 89: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

TextField name = new TextField(); Button button = new Button("Greet"); layout.addComponents(name, button);

button.addClickListener(click -> { Notification.show("Hi, " + name.getValue()); });

Page 90: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

Initial HTML CSS JavaScript

~300k

Page 91: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 92: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

{name: {value: 'Marcus'}, button: {event: 'clicked'}}

261 bytes

Page 93: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

TextField name = new TextField(); Button button = new Button("Greet"); layout.addComponents(name, button);

button.addClickListener(click -> { Notification.show("Hi, " + name.getValue()); });

Page 94: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

{name: {value: 'Marcus'}, button: {event: 'clicked'}}

261 bytes

{new: [ {notification: 'Hi, Marcus'} ]}

267 bytes

Page 95: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 96: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

.v-ui[width-range~="0-800px"]{ /* Styles for small devices */ } .v-ui[width-range~="801px-"]{ /* Styles for large devices */ }

getPage().addBrowserWindowResizeListener( newSize -> { if (newSize.getWidth() > LARGE_DEVICE_WIDTH){ setupLargeLayout(); } else { setupSmallLayout(); } });

Page 97: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

W E B S O C K E T S

public class VaadinUI extends UI { ...

}

@Push

ui.access(() -> Notification.show("Alert!"));

Page 98: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

�����

Page 99: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

S T R O N G S E C U R I T Y#

Page 100: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

T H E J V M♥

Page 101: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

E X T E N D A B L E%

Page 102: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 103: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 104: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what
Page 105: SINGLE-PAGE WEB APPS · ADVENTURES IN SEO AND SINGLE-PAGE WEB APPS MATTI@VAADIN.COM, ! @MATTITAHVONEN, GITHUB.COM/MSTAHV 5 STORY AND PHILOSOPHY Software is eating the world and what

We'd be happy to help you.