-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathindex.html
More file actions
491 lines (320 loc) · 23.7 KB
/
Copy pathindex.html
File metadata and controls
491 lines (320 loc) · 23.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
<!DOCTYPE html>
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8">
<title>Getting Started With FW/1 - FW/1 - The Invisible Framework</title>
<meta name="author" content="Sean Corfield">
<meta name="description" content="Getting Started With FW/1 Jun 30th, 2015 This is the latest (3.1 – develop) documentation – for the current stable release, read the 3.0 …">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="http://framework-one.github.io/documentation/3.1">
<link href="/favicon.png" rel="icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<link href="/atom.xml" rel="alternate" title="FW/1 - The Invisible Framework" type="application/atom+xml">
<script src="/javascripts/modernizr-2.0.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="./javascripts/libs/jquery.min.js"%3E%3C/script%3E'))</script>
<script src="/javascripts/octopress.js" type="text/javascript"></script>
<!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
<link href="//fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
</head>
<body >
<header role="banner"><hgroup>
<h1><a href="/">FW/1 - The Invisible Framework</a></h1>
<h2>Framework One and friends...</h2>
</hgroup>
</header>
<nav role="navigation"><ul class="subscription" data-subscription="rss">
<li><a href="/atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
</ul>
<form action="https://www.google.com/search" method="get">
<fieldset role="search">
<input type="hidden" name="q" value="site:framework-one.github.io" />
<input class="search" type="text" name="q" results="0" placeholder="Search"/>
</fieldset>
</form>
<ul class="main-navigation">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
<li><a href="/documentation">Documentation</a></li>
</ul>
</nav>
<div id="main">
<div id="content">
<div>
<article role="article">
<header>
<h1 class="entry-title">Getting Started With FW/1</h1>
<p class="meta">
<time datetime="2015-06-30T15:00:00-07:00" pubdate data-updated="true">Jun 30<span>th</span>, 2015</time></p>
</header>
<p><em>This is the latest (3.1 – develop) documentation – for the current stable release, read the <a href="/documentation/3.0/">3.0 master documentation</a>.</em></p>
<p>FW/1 was created in July 2009 as a reaction against complexity and bloat in other frameworks in the CFML community. FW/1 itself is a single file, and provides a simple, convention-based approach to MVC (Model-View-Controller) applications. Whilst it has become more sophisticated over time, it has remained a single file, focused on getting out of your way and providing the intuitive plumbing you need. For historical background, you can read the <a href="http://framework-one.github.io/blog/2009/07/19/introducing-framework-one/">introductory blog post</a> from July 2009.</p>
<p>As of release 3.1, FW/1 also includes DI/1 – a simple, convention-based Dependency Injection framework – and AOP/1 – a simple, convention-based Aspect-Oriented Programming framework. If those phrases don’t mean anything to you, don’t worry, you won’t need to know anything about them to get started.</p>
<h2>Requirements & Supported Platforms</h2>
<p>FW/1 3.1 supports Adobe ColdFusion 9.0.2 or later (not 9.0.0 or 9.0.1), Lucee 4.5.0 or later, and Railo 4.1 or later. I recommend using <a href="http://lucee.org/downloads.html">Lucee 4.5.0</a> or later since it’s free, open source, and fast, with a small footprint. If you’re using Adobe ColdFusion, I recommend upgrading to the latest version (ColdFusion 11 as of August 2014) to take advantage of the huge improvements in the core language since ColdFusion 9.0.2 (closures, member functions, full cfscript support, etc) — although there are quite a few bugs in several areas of ColdFusion 11 (even as of June 2015).</p>
<p>If you’re on ColdFusion 9.0.1, FW/1 3.1 should work but there may be some edge cases in <code>Application.cfc</code> lifecycle behavior that may trip you up.</p>
<p>If you’re on ColdFusion 9.0.0 or earlier, or still using Open BlueDragon, you’ll need to stick with FW/1 1.3. Sorry, but supporting those versions is just too painful!</p>
<h2>Your First FW/1 Application</h2>
<p>FW/1 itself consists of a single CFC: <code>framework.one</code>, i.e., <code>framework/one.cfc</code>. Your <code>Application.cfc</code> will extend that and your application’s “pages” will live under a <code>views</code> folder inside a subfolder for each <em>section</em> of your application.</p>
<p>When you download FW/1 (or check it out from Github), it’s a complete web application. <strong>The <code>framework</code> folder should either be copied to your webroot (the simplest way to get started) or else made accessible via a mapping for <code>/framework</code>.</strong> Since <code>Application.cfc</code> extends <code>framework.one</code>, you have to add that mapping in your CFML admin – you cannot use a per-application mapping.</p>
<p><em>Note: do not install FW/1 into a subfolder that contains . in the name as this may prevent CFC resolution from working!</em></p>
<p>The simplest FW/1 application comprises:</p>
<ul>
<li><code>Application.cfc</code> which extends <code>framework.one</code></li>
<li>Empty <code>index.cfm</code> (this file is required but the content is ignored)</li>
<li><code>views</code> folder containing a <code>main</code> subfolder containing <code>default.cfm</code> – your initial application view</li>
</ul>
<p>See the <code>1helloworld</code> example in the <code>examples</code> folder which is this same minimal application.</p>
<p>Create <code>Application.cfc</code> containing:</p>
<pre><code>component extends=framework.one {
}
</code></pre>
<p>Create an empty <code>index.cfm</code> file.</p>
<p>Create <code>views/main/default.cfm</code> containing:</p>
<pre><code><p>Hello FW/1!</p>
</code></pre>
<p>When you access the application, it should say <code>Hello FW/1!</code></p>
<h3>Linking Pages Together</h3>
<p>FW/1 provides a convenient method for generating links between pages. We’re going to use that to link two pages together.</p>
<p>Edit <code>views/main/default.cfm</code> and wrap the content in <code>cfoutput</code> since we’re going to be executing CFML code now:</p>
<pre><code><cfoutput>
<p>Hello FW/1</p>
</cfoutput>
</code></pre>
<p>Now we’ll add a link to a new page – a new <em>section.item</em> – using the <code>buildURL()</code> function FW/1 provides. Edit <code>default.cfm</code> so it looks like this:</p>
<pre><code><cfoutput>
<p>Hello FW/1</p>
<p><a href="#buildURL('main.other')#">Go away</a>!</p>
</cfoutput>
</code></pre>
<p>This will generate a link with an <code>action</code> of <code>main.other</code>. Now we’ll create <code>views/main/other.cfm</code> with this content:</p>
<pre><code><cfoutput>
<p>Goodbye FW/1</p>
<p><a href="#buildURL('main')#">Come back</a>!</p>
</cfoutput>
</code></pre>
<p>This will generate a link with an <code>action</code> of <code>main</code>, which is equivalent to <code>main.default</code> as we’ll see in the next section.</p>
<p>Reload your application in your browser: you should see a <code>Go away!</code> link after <code>Hello FW/1!</code>. Click it and you should go to a URL with <code>?action=main.other</code> which should display <code>Goodbye FW/1!</code> and a link back to your default page. Click that <code>Come back</code> link and you should see your original page. Note that FW/1 realized that the <code>main</code> action is the default and omitted it from the URL completely: this helps keep URLs unique for search engines.</p>
<p>See the <code>2hellolinked</code> example in the <code>examples</code> folder which is this simple two page application.</p>
<h3>An Aside on URL Structure</h3>
<p>Pages are accessed using <code>?action=section.item</code> in the URL which will display the <code>views/section/item.cfm</code> file. The default action is <code>main.default</code>, as you might have guessed from the examples above! If you specify just the section name – <code>?action=section</code> then the item has the value <code>default</code>, in other words, <code>?action=section</code> is equivalent to <code>?action=section.default</code>.</p>
<p>If your application server supports it, so-called SES (Search Engine Safe) URLs can be used with FW/1:</p>
<ul>
<li><code>index.cfm/section</code> – equivalent to <code>?action=section</code></li>
<li><code>index.cfm/section/item</code> – equivalent to <code>?action=section.item</code></li>
<li><code>index.cfm/section/item/name/value</code> – equivalent to <code>?action=section.item&name=value</code></li>
</ul>
<p>To use <em>name/value</em> pairs in SES URLs, you must specify both the <em>section</em> and <em>item</em> parts of the action. A trailing <em>name</em> with no <em>value</em> is equivalent to <em>&name=</em> in a normal URL.</p>
<p>You can tell FW/1 to generate URLs like this from <code>buildURL()</code> through a configuration setting we’ll look at later. You can also tell FW/1 to omit <code>index.cfm/</code> from the generated URL (although you’ll need web server URL rewrites in place to add <code>index.cfm/</code> back in so the requests are processed correctly by your CFML application server).</p>
<h3>Adding a Controller to Your Application</h3>
<p>When you ask for <code>action=section.item</code> FW/1 also looks for <code>section.cfc</code> in a <code>controllers</code> folder and, if present, invokes the <code>item()</code> method on it (and then displays the matching view). We’re going to change our view to display a variable and add a controller to set that variable.</p>
<p>Change <code>views/main/default.cfm</code> to contain:</p>
<pre><code><cfoutput>Hello #rc.name#!</cfoutput>
</code></pre>
<p>Add <code>controllers/main.cfc</code> with a method, <code>default()</code>, that takes a single struct argument called <code>rc</code> (for request context) like this:</p>
<pre><code>component {
function default( struct rc ) {
param name="rc.name" default="anonymous";
}
}
</code></pre>
<p>Note that controller CFC names must be all lowercase.</p>
<p>When you access the application now, it should say <code>Hello anonymous!</code> but if you put <code>?name=Sean</code> on the URL, it should say <code>Hello Sean!</code> The request context passed to the controller method contains all the URL and form variables from the browser and is also made available to the view directly, as <code>rc</code>.</p>
<p>See the <code>3hellocontroller</code> example in the <code>examples</code> folder which is this simple controller example.</p>
<p>Controllers are cached. Add <code>?reload=true</code> to the URL to reload your controllers if you make changes.</p>
<h3>Adding a Layout to Your Application</h3>
<p>When you ask for <code>action=section.item</code> FW/1 looks for <code>layouts/section/item.cfm</code> to find a specific layout (it also knows how to look for default layouts for sections and for an application-wide layout – we’ll cover that next). The basic view is passed in as a variable called <code>body</code>. Let’s try this for our default action, <code>main.default</code>:</p>
<p>Create <code>layouts/main/default.cfm</code> containing:</p>
<pre><code><h1>Welcome to FW/1!</h1>
<cfoutput>#body#</cfoutput>
</code></pre>
<p>Layout filenames, like view filenames, must be all lowercase.</p>
<p>When you access the application now, it should have <code>Welcome to FW/1!</code> as a heading above the previous output.</p>
<p>FW/1 also looks for a section-specific layout in <code>layouts/section.cfm</code> and an application-wide layout in <code>layouts/default.cfm</code>. Let’s create those just to see them in action!</p>
<p>Create <code>layouts/main.cfm</code> containing:</p>
<pre><code><cfoutput><div style="border: solid blue 1px;">#body#</div></cfoutput>
</code></pre>
<p>When you access the application, you should see a blue box around the output you had before. Note that if you ask for <code>action=main.other</code> you’ll get the blue box but you won’t get <code>Welcome to FW/1!</code> because that came from a layout specific to the <code>main.default</code> action.</p>
<p>Now create <code>layouts/default.cfm</code> containing:</p>
<pre><code><cfoutput>
<div style="border: solid green 2px; padding: 20px;">
#body#
</div>
</cfoutput>
</code></pre>
<p>When you access the application now, you should see a green box added around the blue box that was there before.</p>
<div style="border: solid green 2px; padding: 20px;">
<div style="border: solid blue 1px;">
<h1>Welcome to FW/1!</h1>
<p>Hello anonymous!</p>
</div>
</div>
<p>You can see how the layouts nest (and hopefully your artistic skills with CSS and HTML can produce something that looks a lot nicer than this example!).</p>
<p>The <code>4hellolayout</code> example in the <code>examples</code> folder corrsponds to what you should have at this point.</p>
<h3>Adding a Service to Your Application</h3>
<p>Whilst you can keep adding functionality to your controllers, a well-structured MVC application tries to keep the controllers lightweight and delegate all the business logic to the “Model” of your application. The Model is generally exposed to your controllers through a service layer, including smart objects that represent the problem domain, known as domain objects.</p>
<p>You can manage service CFCs yourself if you want but FW/1 ships with an easy to use “bean factory” that makes it easy to create service CFCs, have them automatically wired into your controllers, and then call their methods directly.</p>
<p>Let’s create a greeting service that we can call from our controller. Create a <code>model</code> folder, with a <code>services</code> subfolder, and inside that we’ll put our <code>greeting.cfc</code>:</p>
<pre><code>component {
function greet( string name ) {
return "so-called " & name;
}
}
</code></pre>
<p>FW/1 automatically looks in the <code>model</code> folder for CFCs to create and it expects domain objects to be in a <code>beans</code> subfolder and treats everything else as singletons, creating only a single unique instance.</p>
<p>Now we need to tell our controller about this service so we will add <code>accessors=true</code> to the <code>component</code> tag (so that CFML will automatically provide set and get methods for our properties), and we will add a <code>property</code> for our greeting service like this:</p>
<pre><code>component accessors=true {
property greetingService;
function default( struct rc ) {
param name="rc.name" default="anonymous";
}
}
</code></pre>
<p>Then <code>Service</code> suffix is just a convention that FW/1 and DI/1 use so that you don’t have to worry about CFCs with the same name in different parts of your application model – the subfolder is used as the suffix.</p>
<p>Now we’ll add a call to the <code>greet()</code> method of that service:</p>
<pre><code>component accessors=true {
property greetingService;
function default( struct rc ) {
param name="rc.name" default="anonymous";
rc.name = variables.greetingService.greet( rc.name );
}
}
</code></pre>
<p>When you access the application, you’ll see it says <code>Hello so-called anonymous!</code> so FW/1 has automatically found our service, <em>injected</em> it into our controller, and made it available for us to call in our <code>default()</code> method! This is called <em>Dependency Injection</em> and as we mentioned right at the start of this page, you mostly don’t need to worry about what it means or how it works: you just declare a <code>property</code> for each service you <em>depend on</em> and FW/1 and DI/1 work together to <em>inject</em> it for you.</p>
<p>If you access the application with <code>?name=Sean</code> in the URL, it should say <code>Hello so-called Sean!</code> so you can see how URL variables are passed into the controller and can be passed as arguments to service calls.</p>
<p>Your application at this point corresponds to the <code>5helloservice</code> example in the <code>examples</code> folder.</p>
<h2>What’s Next?</h2>
<p>Once you’ve read this Getting Started guide, you’ll want to move on to the <a href="/documentation/3.1/developing-applications.html">Developing Applications Manual</a> and when you need to look things up, use the <a href="/documentation/3.1/reference-manual.html">Reference Manual</a>. You may also want to learn about <a href="/documentation/3.1/using-subsystems.html">Using Subsystems</a> which allows FW/1 applications to be combined as modules of a larger FW/1 application, or <a href="/documentation/3.1/using-di-one.html">DI/1</a>, a simple, convention-based dependency injection framework.</p>
<p>You probably also want to <a href="http://groups.google.com/group/framework-one/">join the FW/1 mailing list</a> on Google Groups,
<a href="http://cfml-slack.herokuapp.com">join the CFML Slack team</a> for the <a href="https://cfml.slack.com/messages/fw1/">#fw1 channel on Slack</a>,
or <a href="http://twitter.com/search/%23FW1">follow the #FW1 twitter stream</a>; you may also find help and inspiration in the <a href="https://github.com/framework-one/fw1/wiki/FW-1-Site-Showcase">FW/1 Site Showcase</a>, a directory of sites created with FW/1. To read about what’s coming in the future, take a look at the <a href="/documentation/3.1/roadmap.html">Roadmap</a>.</p>
<footer>
<p class="meta">
<time datetime="2015-06-30T15:00:00-07:00" pubdate data-updated="true">Jun 30<span>th</span>, 2015</time>
</p>
</footer>
</article>
</div>
<aside class="sidebar">
<section>
<h1>About FW/1</h1>
<p>FW/1 - Framework One - is a family of small, lightweight, convention-over-configuration frameworks, primarily for CFML. FW/1 itself provides MVC, DI/1 provides dependency injection (a.k.a. inversion of control), and AOP/1 provides aspect-oriented programming features on top of DI/1.</p>
<p>In addition, the family includes cfmljure, an easy way to integrate Clojure code into your CFML application, and a port of FW/1 to Clojure as well as a Leiningen template for creating FW/1 projects in Clojure.</p>
</section>
<section>
<h1>3.1 Documentation (develop)</h1>
<a href="/documentation">Getting Started Guide</a><br />
<a href="/documentation/developing-applications.html">Developing Applications Guide</a><br />
<a href="/documentation/using-aop-one.html">Using AOP/1</a><br />
<a href="/documentation/using-di-one.html">Using DI/1</a><br />
<a href="/documentation/using-subsystems.html">Using Subsystems</a><br />
<a href="/documentation/reference-manual.html">Reference Manual</a><br />
<a href="/documentation/roadmap.html">Roadmap</a><br />
</section>
<section>
<h1>3.0 Documentation (stable - master)</h1>
<a href="/documentation/3.0">Getting Started Guide</a><br />
<a href="/documentation/3.0/developing-applications.html">Developing Applications Guide</a><br />
<a href="/documentation/3.0/using-di-one.html">Using DI/1</a><br />
<a href="/documentation/3.0/using-subsystems.html">Using Subsystems</a><br />
<a href="/documentation/3.0/reference-manual.html">Reference Manual</a><br />
<a href="/documentation/3.0/roadmap.html">Roadmap</a><br />
</section>
<section>
<h1>3.5 Documentation (upcoming - clojure)</h1>
<a href="/documentation/3.5">Getting Started Guide</a><br />
<a href="/documentation/3.5/developing-applications.html">Developing Applications Guide</a><br />
<a href="/documentation/3.5/using-aop-one.html">Using AOP/1</a><br />
<a href="/documentation/3.5/using-di-one.html">Using DI/1</a><br />
<a href="/documentation/3.5/using-subsystems.html">Using Subsystems</a><br />
<a href="/documentation/3.5/reference-manual.html">Reference Manual</a><br />
<a href="/documentation/3.5/roadmap.html">Roadmap</a><br />
</section>
<section>
<h1>Recent Posts</h1>
<ul id="recent_posts">
<li class="post">
<a href="/blog/2015/07/07/fw1-3-1-rc-2/">FW/1 3.1 Release Candidate 2 Available!</a>
</li>
<li class="post">
<a href="/blog/2015/06/28/fw1-3-1-rc-1/">FW/1 3.1 Release Candidate 1 Available!</a>
</li>
<li class="post">
<a href="/blog/2015/06/20/fw1-3-1-beta-2/">FW/1 3.1 Beta 2 Available!</a>
</li>
<li class="post">
<a href="/blog/2015/05/14/fw1-3-1-beta-1/">FW/1 3.1 Beta 1 Available!</a>
</li>
<li class="post">
<a href="/blog/2015/05/09/fw1-2-5-1-2-2-2-important/">FW/1 2.5.2 & 2.2.3 - Important Updates!</a>
</li>
<li class="post">
<a href="/blog/2015/05/09/fw1-3-0-1-important/">FW/1 3.0.2 - Important Update!</a>
</li>
<li class="post">
<a href="/blog/2015/03/21/fw1-3-1-begins/">FW/1 3.1 Begins...</a>
</li>
<li class="post">
<a href="/blog/2015/02/24/fw1-3-0-released/">FW/1 3.0 Released!</a>
</li>
<li class="post">
<a href="/blog/2015/02/06/fw1-3-0-rc-2-available/">FW/1 3.0 RC 2 Available</a>
</li>
<li class="post">
<a href="/blog/2015/01/29/lucee-fw1/">Lucee and FW/1</a>
</li>
</ul>
</section>
<section>
<h1>GitHub Repos</h1>
<ul id="gh_repos">
<li class="loading">Status updating...</li>
</ul>
<a href="https://github.com/framework-one">@framework-one</a> on GitHub
<script type="text/javascript">
$(document).ready(function(){
if (!window.jXHR){
var jxhr = document.createElement('script');
jxhr.type = 'text/javascript';
jxhr.src = '/javascripts/libs/jXHR.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(jxhr, s);
}
github.showRepos({
user: 'framework-one',
count: 0,
skip_forks: true,
target: '#gh_repos'
});
});
</script>
<script src="/javascripts/github.js" type="text/javascript"> </script>
</section>
<section>
<a href="https://github.com/seancorfield">@seancorfield</a> on GitHub
</section>
</aside>
</div>
</div>
<footer role="contentinfo"><p>
Copyright © 2015 - Sean Corfield -
<span class="credit">Powered by <a href="http://octopress.org">Octopress</a></span>
</p>
</footer>
<script type="text/javascript">
(function(){
var twitterWidgets = document.createElement('script');
twitterWidgets.type = 'text/javascript';
twitterWidgets.async = true;
twitterWidgets.src = '//platform.twitter.com/widgets.js';
document.getElementsByTagName('head')[0].appendChild(twitterWidgets);
})();
</script>
</body>
</html>