view release on metacpan or search on metacpan
devdata/https_mojolicious.io_blog_2018_12_02_automatic-reload-for-rapid-development_ view on Meta::CPAN
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/development/">development</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_04_testing-hooks-and-helpers_ view on Meta::CPAN
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/testing/">testing</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
},
},
},
};
</code></pre>
<p>If we run our app (<code>perl myapp.pl daemon</code>) and go to
<code>http://127.0.0.1:3000/yancy</code>, we can edit the list data.</p>
<p><img alt="Browser window showing a form to edit a list
entry" src="editor-form-screenshot.png"></p>
<p>Now Santa's data entry elves get to work entering the data for all the
people in the universe!</p>
<p><img alt="Browser window showing the list of data entered
in" src="editor-list-screenshot.png"></p>
<h1>Step 2: View The List</h1>
<p>With our data entry Neptunians working hard, we can build a way to view
the list. With four arms, they can enter data twice as fast!</p>
<p><img alt="Three Futurama Neptunians in front of baby strollers containing
one-eared rabbit dolls" src="neptunians.png"></p>
<p>Yancy comes with controllers that let us easily list our data just by
configuring a route and creating a template to render. First we
configure the route to use <a href="https://metacpan.org/pod/Yancy::Controller::Yancy#list">Yancy::Controller::Yancy <code>list</code>
method</a>:</p>
<pre><code># Display the naughty rows of the list
get '/', {
controller => 'yancy',
action => 'list',
devdata/https_mojolicious.io_blog_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
</ul>
</code></pre>
<h1>Step 3: Complete Delivery</h1>
<p>Santa's a busy robot, and all that ordnance is expensive. Once he's done
a delivery, he needs to mark it as done so he can move on to all the
other deserving people.</p>
<p><img alt="Santa Robot (from Futurama) writing on his list with a quill
pen" src="editing-list.png"></p>
<p>Stopping to check people off manually really slows down the murder and
mayhem.</p>
<p>Yancy makes it easy to update the data, this time with the <a href="https://metacpan.org/pod/Yancy::Controller::Yancy#set">"set" action
in Yancy::Controller::Yancy</a>:</p>
<pre><code># Set the delivered state of a list row
post '/deliver/:id', {
controller => 'yancy',
devdata/https_mojolicious.io_blog_2018_12_06_making-a-list-with-yancy_ view on Meta::CPAN
$(this).parents("form").submit();
} );
% end
</code></pre>
<p>Now our webapp looks like this:</p>
<p><img alt="A browser window showing the completed webapp. A set of rows with name
and address on the left, and a Delivered button with Yes and No options
on the right. Some rows have the No button checked, others the Yes
button" src="finished-screenshot.png"></p>
<p>We can view our entire list, and check off the ones who we've delivered to already!
<a href="myapp.pl">View the entire app here</a>.</p>
<p><img alt="Santa Robot in his sleigh with burning buildings in the foreground and
background" src="success.png"></p>
<p>Another successful Xmas, powered by <a href="http://mojolicious.org">Mojolicious</a>!</p>
</section>
<small><p><a href="https://pxhere.com/en/photo/1263707">Banner image</a> CC0 Public Domain</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/yancy/">yancy</a>,
<a href="/blog/tag/example/">example</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_09_add-a-theme-system-to-your-mojolicious-app_ view on Meta::CPAN
$self->static->paths([$self->home->rel_file('themes/default/public')]);
# Put the new theme first
unshift @{$self->renderer->paths}, $self->home->rel_file('themes/christmas/templates');
unshift @{$self->static->paths}, $self->home->rel_file('themes/christmas/public');
</code></pre>
<p>By doing that way, we can overload the default files.</p>
<p>You don't have to modify each file of the default theme to have a new theme: just copy the files you want to overload in your new theme directory and it will be used instead of the default one.</p>
<p>Let's say that you have a <code>background.png</code> file in your default theme:</p>
<pre><code>$ cd themes/default
$ tree public templates
public
âÂÂâÂÂâ background.png
âÂÂâÂÂâ index.html
templates
âÂÂâÂÂâ example
âÂÂààâÂÂâÂÂâ welcome.html.ep
âÂÂâÂÂâ layouts
âÂÂâÂÂâ default.html.ep
2 directories, 4 files
</code></pre>
<p>In order to overload it, you just have to have this:</p>
<pre><code>$ cd themes/christmas
$ tree public templates
public
âÂÂâÂÂâ background.png
templates
0 directories, 1 files
</code></pre>
<h2>Using Mojolicious::Plugin::Config plugin</h2>
<p><a href="https://mojolicious.org/perldoc/Mojolicious/Plugin/Config">Mojolicious::Plugin::Config</a> comes with Mojolicious itself and is a great way to let users configure your application.
Why not using it to let them choose the theme they want?
In our example, the setting will unsurprisingly be named <code>theme</code>.</p>
devdata/https_mojolicious.io_blog_2018_12_09_add-a-theme-system-to-your-mojolicious-app_ view on Meta::CPAN
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/theme/">theme</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="/static/ldidry.png">
</div>
<div class="about">
<h5>Luc Didry</h5>
<p>Luc Didry is a sysAdmin and Perl developer, in love with Perl since he discovered it 10 years ago, and a Mojolicious enthusiast.</p>
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_10_minion-stands-alone_ view on Meta::CPAN
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/minion/">minion</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_11_who-watches-the-minions_ view on Meta::CPAN
the <a href="https://mojolicious.org/perldoc/Mojolicious/Command/daemon">Mojolicious <code>daemon</code>
command</a>.</p>
<pre><code>$ perl myapp.pl daemon
Server available at http://127.0.0.1:3000
</code></pre>
<p>Now I can access the Minion UI:</p>
<p><img alt="A web browser showing the main Minion UI screen with charts showing
the status of running jobs" src="01-main.png"></p>
<p>The main page shows the current status. The links at the top show lists
of jobs in the given state, any locks that exist, and the workers.</p>
<p><img alt="A web browser showing a list of jobs in the "finished"
state" src="02-job-list.png"></p>
<p>When looking at a list of jobs, I can click the buttons on top left to
manage the job queue, or click on the caret on the right of each job row
to view the details of that job (the same as the <code>job</code> command shows).</p>
<p><img alt="A web browser showing the details of a single Minion job as
JSON" src="03-job-details.png"></p>
<p>The Minion Admin UI is a great addition to a great tool! <a href="minion.pl">View the entire
source of the Minion app</a></p>
</section>
<small><p>Original artwork by Doug Bell, released under CC-BY-SA 4.0. It includes
the Minion logo (CC-BY-SA 4.0)</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/minion/">minion</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_14_a-practical-example-of-mojo-dom_ view on Meta::CPAN
<link href="/theme/css/default.css" rel="stylesheet">
<link href="/theme/css/layout.css" rel="stylesheet">
<link href="/theme/css/media-queries.css" rel="stylesheet">
<link href="/theme/css/statocles.css" rel="stylesheet">
<!-- twitter and opengraph -->
<meta content="summary" name="twitter:card">
<meta content="https://mojolicious.io/blog/2018/12/14/a-practical-example-of-mojo-dom/" property="og:url">
<meta content="Day 14: A Practical Example of Mojo::DOM" property="og:title">
<meta content="Use Mojo::DOM to parse XML" property="og:description">
<meta content="https://mojolicious.io/blog/2018/12/14/a-practical-example-of-mojo-dom/banner.png" property="og:image">
<meta content="summary_large_image" name="twitter:card">
<script src="/theme/js/modernizr.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/sunburst.min.css" rel="stylesheet">
<title>Day 14: A Practical Example of Mojo::DOM - mojolicious.io</title>
<meta content="Chris Seigman" name="author">
<meta content="Statocles 0.093" name="generator">
<link href="/static/favicon.ico" rel="shortcut icon">
devdata/https_mojolicious.io_blog_2018_12_14_a-practical-example-of-mojo-dom_ view on Meta::CPAN
<time class="date" datetime="2018-12-14">Dec 14, 2018</time>
</p>
</div>
<div class="post-thumb">
<!-- theme suggests 1300x500 -->
<img alt="A typical industrial platform model overlaid with a laser scan" src="/blog/2018/12/14/a-practical-example-of-mojo-dom/banner.png">
</div>
<div class="post-content">
<section id="section-1">
<p>With recent versions of Mojolicious, <a href="https://mojolicious.org/perldoc/Mojo/DOM">Mojo::DOM</a> gained a lot of power that I have been excited to try, but haven't had the time for. Recently, I had a problem at my real ...
</section>
<section id="section-2">
<h2>The task - simple, but tedious.</h2>
devdata/https_mojolicious.io_blog_2018_12_14_a-practical-example-of-mojo-dom_ view on Meta::CPAN
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/xml/">xml</a>,
<a href="/blog/tag/non-web/">non-web</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="/static/seigman.png">
</div>
<div class="about">
<h5>Chris Seigman (maschine)</h5>
<p>Chris has been using Perl to develop websites and other tools for more than 20 years, but mostly as a hobby. Since discovering Mojolicious, his Perl skills have improved dramatically, and he has expanded beyond simple CGI ...
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_16_browser-diet_ view on Meta::CPAN
<p>which produces</p>
<pre><code><script defer src="/path/to/script.js"></script>
</code></pre>
<p>If you want it in the <code><head></code>, you'll have to put it in your layout
otherwise the template will do.</p>
<h2>... and finally, there was a <a href="https://metacpan.org/author/LDIDRY">Man in a Hat</a></h2>
<p><img alt="Luc Didry gravatar" class="pull-right" src="/static/ldidry.png"></p>
<p>"But the JavaScript needs to load <strong>FIRST</strong>!", squeaked the nut-botherer.</p>
<p>Sigh - this really is one demanding Sciurus vulgaris.</p>
<p>Well ... it <em>is</em> Christmas, but you'll need to install the
<a href="https://metacpan.org/pod/Mojolicious::Plugin::StaticCache">StaticCache plugin</a>
written for you only last year by
<a href="https://fiat-tux.fr/">Luc Didry</a>.
It sets the <code>Control-Cache</code> header for all static files served by Mojolicious.
With the <strong>nut.js</strong> and <strong>nut.css</strong> files in the <code>public</code> directory
(properly <a href="https://www.minifier.org/">minified</a> of course),
they should only be downloaded once and use the cached version until it expires.
The default <strong>max-age</strong> is 30 days and
if you want you can even cache during development with <code>even_in_dev => 1</code>.</p>
<p><img class="pull-right" src="speedtest_before_StaticCache.png"></p>
<p>The magpies in the forest had cluttered the calendar with 3 JavaScript libraries,
3 CSS files and 4 logos. Sure, the biggest and shiniest was only 66 kB
and the whole collection was a paltry 164 kB, but bandwidth is precious in the wilderness.
Before using the StaticCache plugin, the calendar rated a
<strong>92</strong> on Google's PageSpeed Insights.</p>
<p>With the StaticCache plugin loaded</p>
<pre><code>sub startup {
my $self = shift;
$self->plugin('StaticCache' => { even_in_dev => 1 });
...
}
</code></pre>
<p><img class="pull-left" src="speedtest_with_StaticCache.png"></p>
<p>page speeds are now <strong>93</strong> <strong>!!!!</strong>
WOW! It's <a href="https://xkcd.com/670">one faster!</a> said Nutgel Tufty-tail
and everyone in the forest cheered.</p>
<p>And <em>that</em>, dear readers, is how the squirrel learned to store nuts for the winter
... in a <em>cache</em>. Good night, little kids, good niiiight.</p>
<h2>Try it out for yourself</h2>
devdata/https_mojolicious.io_blog_2018_12_17_a-website-for-yancy_ view on Meta::CPAN
},
};
</code></pre>
<p>Now we can create some pages. I can start up the app with <code>perl myapp.pl
daemon</code>, and then edit my content by visiting
<code>http://127.0.0.1:3000/yancy</code>. The site will especially need an index
page, so I'll create one.</p>
<p><img alt="Screenshot showing the Yancy editor adding an "index"
page" src="edit-index.png">
<img alt="Screenshot showing the Yancy editor listing the index page in the
database" src="list-index.png"></p>
<p>With our content created, I need to add a route to display it. Using the
<a href="https://mojolicious.org/perldoc/Mojolicious/Guides/Routing#Wildcard-placeholders"><code>*</code> wildcard
placeholder</a>,
the route will match any path. I can then look up the page requested
from the database using the <a href="https://metacpan.org/pod/Yancy::Controller::Yancy/get">Yancy controller <code>get</code>
action</a>. I set
a default of "index" to pull our index page when users visit "/". Last,
the route will need a little bit of a template just to display the
page's HTML and a layout with some useful links and maybe some
devdata/https_mojolicious.io_blog_2018_12_17_a-website-for-yancy_ view on Meta::CPAN
</main>
%= javascript '/yancy/jquery.js'
%= javascript '/yancy/popper.js'
%= javascript '/yancy/bootstrap.js'
</body>
</html>
</code></pre>
<p>Now I can open my website and see the index page I created!</p>
<p><img alt="Screenshot showing the index page for the site" src="view-index.png"></p>
<p>Now I have a basic website! <a href="myapp.pl">Here's the code so far</a>. This is
a good start, but I'll need more if it's going to be useful...</p>
</section>
<small><p>Banner image CC0 Public Domain</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/yancy/">yancy</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_18_a-view-to-a-pod_ view on Meta::CPAN
<pre><code>use Mojolicious::Lite;
plugin 'PODViewer', {
default_module => 'Yancy',
allow_modules => [qw( Yancy Mojolicious::Plugin::Yancy )],
};
app->start;
</code></pre>
<p>There, now the Yancy docs are shown on the front page.</p>
<p><img alt="Screenshot of Yancy module documenation" src="okay-docs.png"></p>
<p>Finally, let's make it look a bit nicer: The documentation definitely
needs to use the default site layout, and a little additional CSS will
also make the documentation look a lot better!</p>
<pre><code>use Mojolicious::Lite;
plugin 'PODViewer', {
default_module => 'Yancy',
allow_modules => [qw( Yancy Mojolicious::Plugin::Yancy )],
layout => 'default',
devdata/https_mojolicious.io_blog_2018_12_18_a-view-to-a-pod_ view on Meta::CPAN
<title><%= title %></title>
</head>
<body>
%= content
</body>
</html>
</code></pre>
<p>Now our documentation looks good!</p>
<p><img alt="Screenshot of Yancy module documenation with new style" src="good-docs.png"></p>
<p><a href="myapp.pl">Here's the full source</a>. Now that I have a beautiful
website, I just need to deploy the new site to the Internet...</p>
</section>
<small><p>Banner image CC0 Public Domain</p>
</small>
<p class="tags">
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/documentation/">documentation</a>,
<a href="/blog/tag/yancy/">yancy</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_19_you-only-export-twice_ view on Meta::CPAN
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/command/">command</a>,
<a href="/blog/tag/yancy/">yancy</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="https://secure.gravatar.com/avatar/4bdc4922059d58a0fcbf8f35652dc254.png">
</div>
<div class="about">
<h5>Doug Bell</h5>
<p>Doug (<a href="http://preaction.me">preaction</a>) is a long time Perl user.
He is the current maintainer of <a href="http://www.cpantesters.org/">CPAN Testers</a> and the author of many <a href="https://metacpan.org/author/PREACTION">CPAN modules</a> including the <a href="http://preaction.me/statocles/">Statocles</a> blog e...
</div>
</div>
devdata/https_mojolicious.io_blog_2018_12_22_use-carton-for-your-mojolicious-app-deployment_ view on Meta::CPAN
<span>Tagged in </span>:
<a href="/blog/tag/advent/">advent</a>,
<a href="/blog/tag/deployment/">deployment</a>,
<a href="/blog/tag/carton/">carton</a>
</p>
<div class="bio cf">
<div class="gravatar">
<img alt="author image" src="/static/ldidry.png">
</div>
<div class="about">
<h5>Luc Didry</h5>
<p>Luc Didry is a sysAdmin and Perl developer, in love with Perl since he discovered it 10 years ago, and a Mojolicious enthusiast.</p>
</div>
</div>
<ul class="post-nav cf">
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
[Sat Dec 15 13:08:52 2018] [info] Manager 38209 started
[Sat Dec 15 13:08:52 2018] [info] Creating process id file "/Users/Sachin/workspace/project/mojo_angular/mojo_angular_app/script/hypnotoad.pid"
[Sat Dec 15 13:08:52 2018] [info] Worker 38210 started
[Sat Dec 15 13:08:52 2018] [info] Worker 38211 started
[Sat Dec 15 13:08:52 2018] [info] Worker 38213 started
[Sat Dec 15 13:08:52 2018] [info] Worker 38212 started
</code></pre>
<p>Let's open browser and have a look at our mojo app.</p>
<p><img alt="basic Mojolicious full app" src="mojo_app.png"></p>
<h2>Generate Angular App</h2>
<p>Angular Version 7 is used for this demo, but should work for versions back to 4+. Demos on how to install Angular and CLI will be way too boring for this blog and there are plenty of resources for this in internet.</p>
<p>Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications.
Let's use the Angular CLI to generate a new app, <code>ng new app-name</code>.</p>
<pre><code>Sachin@01:18 PM[~/workspace/project/mojo_angular]$ ng new NgDemo
? Would you like to add Angular routing? Yes
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
chunk {main} main.js, main.js.map (main) 11.5 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 223 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.08 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 16.3 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.67 MB [initial] [rendered]
ï½¢wdmï½£: Compiled successfully.
</code></pre>
<p>Open the browser to check Angular app:</p>
<p><img alt="basic angular app" src="angular_app.png"></p>
<p>Note that this page's content is coming from <code>NgDemo/src/index.html</code> where <code>app-root</code> selector html is content coming from <code>NgDemo/src/app/app.component.html</code>. Later we will be modifying <code>app.component.htm...
<h2>Make Mojolicious app serve an Angular app?</h2>
<p>First we'll compile the Angular app from <a href="https://www.typescriptlang.org/docs/home.html">TypeScript</a> to standard JavaScript.
<code>ng build</code> compiles an Angular app into an output directory named <code>dist</code> at the given output path.
Run <code>ng build</code> with <code>--base-href=./</code> so that base url inside the Angular app is set to the current directory for the application being built. This is very important so that later you do not waste time figuring out why Angular ro...
<pre><code>Sachin@02:06 PM[~/workspace/project/mojo_angular/NgDemo]$ ng build --base-href=./
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
[Sat Dec 15 14:49:03 2018] [info] Listening at "http://*:8080"
Server available at http://127.0.0.1:8080
[Sat Dec 15 14:49:03 2018] [info] Manager 40633 started
[Sat Dec 15 14:49:03 2018] [info] Creating process id file "/Users/Sachin/workspace/project/mojo_angular/mojo_angular_app/script/hypnotoad.pid"
[Sat Dec 15 14:49:03 2018] [info] Worker 40634 started
[Sat Dec 15 14:49:03 2018] [info] Worker 40635 started
[Sat Dec 15 14:49:03 2018] [info] Worker 40637 started
[Sat Dec 15 14:49:03 2018] [info] Worker 40636 started
</code></pre>
<p><img alt="mojolicious serving angular SPA" src="mojo_serving_angular.png"></p>
<p>Congratulations! we have served angular app with Mojolicious. Please note that the URL will be <code>http://localhost:8080/NgDemo/</code>.</p>
<h2>Integrating the Apps Further</h2>
<p>To show how the applications can interact, we'll now build a simple demo to show an api call to a Mojolicious backend routes from the Angular frontend and display the result in Angular.
Since, this is not an Angular blog I will not go too deep explaining Angular; there are plenty of resources in internet for that.</p>
<h3>Create a new route in the Mojo App</h3>
devdata/https_mojolicious.io_blog_2018_12_23_mojolicious-and-angular_ view on Meta::CPAN
<h4>Build the Angular app</h4>
<p>Run <code>ng serve</code> command(as earlier) to see if angular app is looking good.
Then run <code>ng build --base-href=./</code> and copy <code>dist</code> folder content to mojolicious app's <code>public</code> directory as shown earlier.</p>
<h2>Try it out!</h2>
<p>Finally run <code>hypnotoad</code> as shown earlier
Visit <code>localhost:8080/NgDemo</code> in browser to witness wedding of Mojolicious and Angular:</p>
<p><img alt="final mojolicious serving angular SPA" src="final_mojo_angular_app.png"></p>
<p>That's all you need for simple single page app with angular and mojo. Take it further and see what is possible!</p>
<h2>Further Reading</h2>
<p>This was just a quick example, if you're interested, keep going with these resourses:</p>
<ul>
<li><a href="https://angular.io/docs">Angular guide</a></li>
<li><a href="https://angular.io/tutorial">Angular tutorial</a></li>