<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[INNOMIZE - Medium]]></title>
        <description><![CDATA[INNOMIZE is a leading offshore development and global IT consulting company based in Vietnam. From cloud solutions to software development and offshore development center, we deliver tailored solutions that drive business growth - Medium]]></description>
        <link>https://medium.com/innomizetech?source=rss----2b737588f380---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>INNOMIZE - Medium</title>
            <link>https://medium.com/innomizetech?source=rss----2b737588f380---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 30 May 2026 09:18:52 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/innomizetech" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Continuous Delivery — Deploying a Node.js app to AWS EC2 using Ansible]]></title>
            <link>https://medium.com/innomizetech/continuous-delivery-deploying-a-node-js-app-to-aws-ec2-using-ansible-39bdab26f02a?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/39bdab26f02a</guid>
            <category><![CDATA[ansible]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[aws-ec2]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Hoang Le]]></dc:creator>
            <pubDate>Mon, 03 Feb 2020 03:50:12 GMT</pubDate>
            <atom:updated>2023-07-28T01:38:44.255Z</atom:updated>
            <content:encoded><![CDATA[<h3>Continuous Delivery — Deploying a Node.js app to AWS EC2 using Ansible</h3><p>The main key point for all our projects is trying to automate all things, it helps to reduce errors (e.g. human mistake), fast and easy to deploy / rollback, and improves customer satisfaction.</p><figure><img alt="Continuous Delivery and Automation are Key" src="https://cdn-images-1.medium.com/proxy/0*RBJGZPYN8d8R2BuB" /><figcaption><a href="https://www.google.com.vn/url?sa=i&amp;source=images&amp;cd=&amp;ved=2ahUKEwiJ2rKF0bfeAhXYaN4KHcZ_D8QQjhx6BAgBEAM&amp;url=https%3A%2F%2Fwww.slideshare.net%2Fdcjuengst%2Fcloudbeesjenkinsplatform2016&amp;psig=AOvVaw1RxLgKUvrZis9gBgTe1LLi&amp;ust=1541314216834361">Images Sources</a></figcaption></figure><p>We do have some approaches to automate the deployment process that we have been applying to our projects such as using <a href="https://aws.amazon.com/elasticbeanstalk/">Amazon Elastic BeanStalk</a> or <a href="https://aws.amazon.com/ecs/">Amazon Elastic Container Service</a>. However, in some cases, our customers don’t want to use those approaches because they don’t use AWS, they’ve already had the servers to run the app, and they want to keep their app on their On-Prime Data Center and have their IT guys manage it. It led us to have to find out another approach to automate our delivery process. And we have chosen Ansible as the tool to implement our Continuous Delivery pipeline.</p><p>So I would like to write this article to share with you and outline our workflow and provide a brief introduction along with sample code to build this flow.</p><h4>The Tools</h4><ul><li><a href="https://jenkins.io/doc/">Jenkins</a>: Jenkins is a self-contained, open-source automation server that can be used to automate all sorts of tasks related to building, testing, and delivering or deploying software.</li><li><a href="https://www.ansible.com/">Ansible</a>: Ansible is an open-source automation platform. Ansible can help you with configuration management, application deployment, and task automation. It can also do IT orchestration, where you have to run tasks in sequence and create a chain of events that must happen on several different servers or devices.</li><li><a href="https://slack.com/">Slack</a>: a cloud-based set of proprietary team collaboration tools and services.</li></ul><h4>Why Ansible?</h4><p>As you know, there are a lot of tools for infrastructure automation (infrastructure as code) such as Terraform, Chef, Ansible, Juju, and more. But there are a few reasons that make me select Ansible as below:</p><ul><li>It is very, <a href="https://docs.ansible.com/ansible/2.7/installation_guide/intro_installation.html">very simple to set up </a>and yet powerful.</li><li>Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications.</li><li>Automate in a language that approaches plain English, using SSH, with no agents (like Puppet or Chef) to install on remote systems.</li><li>Easy to integrate with our CI/CD pipeline using the Jenkins server.</li></ul><h4>The Steps</h4><p>What we are going to build is the following deployment flow:</p><ol><li>Launch EC2 instance(s) (optional).</li><li>Update OS and install needed dependencies such as install Node.js.</li><li>Deploy the Node.js app to EC2 instance(s).</li><li>Configure DNS (optional).</li><li>Smock test.</li></ol><h4>Let’s code…</h4><p><strong>Project Structure</strong></p><p>When doing any coding stuff, the <em>project structure</em> is one of the most important things I pay attention to. If you have experience working with Ansible, you should know how to organize the Ansible project. I followed the alternative approach mentioned in <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html#directory-layout">this</a> article, feel free to select your own approach.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*XDd8mVzdG7WMvJ4N" /></figure><p>My project contains the following root directories/files:</p><ul><li><em>scripts</em>: it contains a shell <em>setup</em> script to install Ansible, Ansible Galaxy, and generate a self-signed certificate to run our Node.js app in secure mode (HTTPS).</li><li><em>cert</em>: directory to keep a self-signed certificate.</li><li><em>ansible</em>: put all Ansible code into this directory including playbooks, roles, var files, etc.</li><li><em>Jenkinsfile</em>: the Jenkins pipeline code for CI/CD pipeline.</li></ul><p><strong>Role</strong></p><blockquote><em>In Ansible, the role is the primary mechanism for breaking a playbook into multiple files. This simplifies writing </em><strong><em>complex playbooks</em></strong><em>, and it makes them easier to reuse. The breaking of playbook allows you to logically break the playbook into reusable components.</em></blockquote><p>Here are the following roles we will use on this project:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/530/0*06lE-LHgszRKN8ph" /></figure><ul><li><em>apache-server</em>: we don’t use this role on this project but I wanted to keep it here. This role will configure the Apache using our own <em>httpd.conf</em> template file. To install Apache, we can use <a href="https://github.com/geerlingguy/ansible-role-apache">geerlingguy.apache</a> role.</li><li><em>common</em>: put all your comment stuff into this role such as updating your OS to ensure your server(s) are up to date.</li><li><em>launch-ec2</em>: this role to launch EC2 instance(s) to deploy our app.</li><li><em>node-server</em>: contains all needed steps to deploy and run the Node.js app</li><li><em>nodejs</em>: install the Node.js runtime.</li></ul><h3>Conclusion</h3><p>Using Ansible, you can easy to provision and install software to run your application automatically, you can manage your infrastructure as code (IaC). However, running your software is not simple as this demo, you will need to do more things such as setup the network, configure the firewall, and auto-scaling. To do those things, you might need to combine them with other tools. For example, you can use the AWS CDK framework to provide your AWS infrastructure (network, database, EC2 instances, and auto-scaling), then use Ansible to provision your EC2 instances and configure your applications.</p><p>I hope this post will bring some ideas to you to design and deploy your application. If you have any issues or need help, just let me know by adding comments to this post.</p><p>Thank you for reading!</p><p>This post is originally published on <a href="https://innomizetech.com/blog/continuous-delivery-deploying-a-node-js-app-to-aws-ec2-using-ansible">our blog</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=39bdab26f02a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/continuous-delivery-deploying-a-node-js-app-to-aws-ec2-using-ansible-39bdab26f02a">Continuous Delivery — Deploying a Node.js app to AWS EC2 using Ansible</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Do You Need an MVP for Your Business?]]></title>
            <link>https://medium.com/innomizetech/why-do-you-need-an-mvp-for-your-business-9d0714050c23?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/9d0714050c23</guid>
            <category><![CDATA[product-development]]></category>
            <category><![CDATA[mvp]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[minimum-viable-product]]></category>
            <dc:creator><![CDATA[Phong Trần]]></dc:creator>
            <pubDate>Tue, 31 Dec 2019 09:16:57 GMT</pubDate>
            <atom:updated>2023-07-28T01:41:40.644Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BIoSAwL9TenGDbHxqmyl1w.jpeg" /></figure><p><em>In this article, I will let you know what is MVP and benefits that MVP development can offer to your business.</em></p><h3>What is a Minimum Viable Product (MVP)?</h3><blockquote>“The minimum viable product is that version of a new product which allows a team to collect the maximum amount of validated learning about customers with the least effort.” by Eric Ries</blockquote><p>MVP is the basic version of the new product with a certain set of core features to resolve a specific issue of the targeted customers. Companies such as Facebook, Twitter, Uber, Dropbox, Zappos started out with an MVP and become the largest applications and influential today.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HAN8BBnf3Jv8W3nN-YGLpg.jpeg" /></figure><h3>So, why a business should start with an MVP?</h3><h4>1. Minimum time to market</h4><p>Building a full-blown application that would require overcoming extreme technical hurdles and months of development. Instead, MVP development takes only a couple of months, which allows you to roll out your product fast and thus have better chances to prosper on the market.</p><h4>2. Early Feedback From Users</h4><p>The original idea of <strong>Instagram</strong> was to allow people to check-in where they are on their mobile web app. But after it was launched, the leaders decided to change the concept to meet the expectations of users.</p><p>Don’t wait until your application has full-blown features because your idea might not meet the expectations of users. Starting with an MVP and early get feedback and then improve your application.</p><h4>3. <strong>Reduce rework and minimize development costs</strong></h4><p>Turning an idea into a full-blown application and meet the user’s expectation will take a humungous amount of effort. Rework can never be totally eliminated. However, with the MVP approach, you can make it as less as possible. You know features that customers don’t want and improve from an early stage. So rather than revamping the entire product from scratch, you just need to make the basic fundamental changes to the product. By doing so, you ensure the smooth execution of your product then save much cost.</p><p><strong>4. Attract Investors</strong></p><p>With an idea in your head and you are looking for investors. Believe me, it may sound not very promising for investors. One of the benefits of an MVP development is that you will have a rather serious perspective than just your thoughts to show to investors interested in funding you. This will definitely escalate your chances of being noticed and heard.</p><h3>Takeaways</h3><p><strong>MVP</strong> development is always a safe and wise way to launch a new product. it helps you test your ideas in your chosen market before you create the full product. It also allows you to speed up time-to-market, maximize your budget, get early feedback, provide you valuable improvement ideas and analytical data.</p><h3>Ready to develop an MVP for your idea?</h3><p>At <a href="https://www.innomizetech.com/"><strong>Innomize</strong></a><strong>, </strong>we offer full consultations for a minimum viable project. Are you interested in developing your MVP with us? Don’t hesitate to get in touch.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9d0714050c23" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/why-do-you-need-an-mvp-for-your-business-9d0714050c23">Why Do You Need an MVP for Your Business?</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Perform the File Upload Operation with Protractor on Docker?]]></title>
            <link>https://medium.com/innomizetech/how-to-perform-the-file-upload-operation-with-protractor-on-docker-e8de947e16ad?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/e8de947e16ad</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[automazione-endtoend]]></category>
            <category><![CDATA[automation-testing]]></category>
            <category><![CDATA[protractor]]></category>
            <dc:creator><![CDATA[Anh Hoang]]></dc:creator>
            <pubDate>Tue, 17 Dec 2019 10:49:04 GMT</pubDate>
            <atom:updated>2019-12-17T10:49:04.746Z</atom:updated>
            <content:encoded><![CDATA[<h3>How to perform the file upload operation with Protractor on Docker?</h3><h3>Problems</h3><p>One of the features of automated application testing is uploading files. You can easily create a file in the workspace and upload it to the web applications by protractor when running locally. But when you try to run your test on docker, a problem occurred. There is a message: “Failed: invalid argument: File not found: /home/headless-auto/data/abc.txt”. It means the webdriver server is not able to reach the folder contains the file abc.txt.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/624/1*qMj9VsHor0c5HwZzreZtmQ.png" /></figure><p>This is because when we run protractor in docker, the Selenium server and Protractor are running in 2 individual containers, so the Selenium server container cannot get the file was created and saved in protractor container, to put to the web application.</p><ul><li>Is there any way to get a file in a container from another container?</li></ul><p>Yes! It is not actually getting a file in a container from another container, but it still helps to solve the problem above. The docker supports us to share the folder between containers by using volume. All files in the shared folder will be synchronized with the volume. So the selenium server can get all files in the shared folder in the protractor container, then able to execute the uploading files.</p><h3>Jump to coding</h3><p>Let get the idea by the example below:</p><p>Protractor needs two files to run, a spec file and a configuration file.</p><p>Let prepare an uploading test script:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/969/1*RVOiVNyiXi0aXU1lm6szKw.png" /><figcaption>upload.spec.ts</figcaption></figure><p>The Describe and Its syntax are from the Jasmine framework. Browser is a global created by Protractor, use <em>path.resolve</em> helper function to resolve the relative path to an absolute path.</p><ul><li>Configuration file:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/999/1*ifp7FG3c9f8kjMj2qwWZkw.png" /><figcaption>protractor.config.ts</figcaption></figure><p>This configuration file means:</p><ul><li>The default browser is Chrome (The protractor also supports Firefox, IE, Safari..)</li><li>The address of running the selenium server is http://localhost:4444/wd/hub. The Protractor can test directly against Chrome and Firefox without using a Selenium server. To use this, in your config file set <strong>directConnect: true</strong>.</li><li>The framework is Jasmine. Protractor supports two behavior-driven development (BDD) test frameworks out of the box: Jasmine and Mocha.</li><li>“specs” option tells to protractor where is test files.</li></ul><p>Start the Protractor test:</p><p>We need to run <em>tsc</em> command to compile into javascript that node.js can understand.</p><p>Run “webdriver-manager update” to download the necessary binaries. Then start up the selenium server: “webdriver-manager start”.</p><p>Now we can execute “protractor output/protractor.config.js” to run the protractor test. For now, we are able to open the web application and then uploading the file.</p><p>To run on docker, add the Dockerfile and docker-compose.yml files like below to the workspace.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/621/1*by7scr8e08k3_JLg2GW4qA.png" /><figcaption>Dockerfile</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/1*6zR91e_Xqkfukrht3Zl9ew.png" /><figcaption>package.json</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/938/1*ZhVzSyTlU7mvadQ5TUbQpA.png" /><figcaption>docker-compose.yml</figcaption></figure><p>Docker-compose use “selenium/standalone-chrome:3.141.59-dubnium” as selenium server so we need to change the seleniumAddress in <em>protractor.config.ts</em> file to<strong> http://selenium-chrome-standalone:4444/wd/hub</strong></p><p>We will share all files and folder in <em>/home/headless-auto</em> directory of protractor and selenium server containers into “data-volume” volume.</p><p>Now we can run the test in docker by executing <em>docker-compose up</em> command. Then you will able to upload the file to the website without any issue.</p><h3>Conclusion</h3><p>Running the end-to-end test on Docker is an easy way to implement the automation tests. With Docker run can your tests on cloud-based such as AWS Fargate or even AWS Lambda. I hope this post will help you and save your time!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8de947e16ad" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/how-to-perform-the-file-upload-operation-with-protractor-on-docker-e8de947e16ad">How to Perform the File Upload Operation with Protractor on Docker?</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A brief summary of JavaScript Learning Path]]></title>
            <link>https://medium.com/innomizetech/a-brief-summary-of-javascript-learning-path-ecaeb2adf285?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/ecaeb2adf285</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[how-to]]></category>
            <dc:creator><![CDATA[Hoang Le]]></dc:creator>
            <pubDate>Tue, 17 Dec 2019 10:37:36 GMT</pubDate>
            <atom:updated>2023-07-28T01:39:43.136Z</atom:updated>
            <content:encoded><![CDATA[<h3>A Brief Summary of JavaScript Learning Path</h3><p>JavaScript is a popular language among web developers which gave rise to several frameworks that simplify your code. According to the largest online developer communities, <a href="https://insights.stackoverflow.com/survey/">StackOverflow</a> in their 2019 survey of the most sought-after programming languages shed some light on what to expect in the coming year:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*KLF1hRYGP1R3pzhE" /><figcaption><em>Top Programming Languages in 2019</em></figcaption></figure><p>As you can see, <a href="https://stackoverflow.com/jobs?sort=i&amp;q=javascript">JavaScript</a> is the most commonly used programming language. So how to learn <strong>JavaScript</strong>, how to up-level your programming language skills, and what is the path for learning JavaScript from the beginning? If you don’t know how to get started, then you should read this post.</p><h4>Step 1 — Learn basic and fundamentals</h4><p>Firstly, you need to understand the basic concepts and fundamentals of JavaScript, you can learn from</p><ul><li><a href="https://www.w3schools.com/js/">W3 Schools</a></li><li><a href="https://javascript.info/">Javascript.info</a></li></ul><p><a href="https://github.com/getify/You-Dont-Know-JS">You-Dont-Know-JS</a> is a series of books diving deep into the core mechanisms of the JavaScript language. You should read this to get more overview and advanced concepts of JavaScript such as Scope &amp; Closures, Objects &amp; Classes, Sync &amp; Async, ES.Next &amp; Beyond.</p><h4>Step 2 — Learn modern JavaScript</h4><p>Learning basic isn’t enough, you need to learn more about advanced and modern JavaScript concepts/syntax, it helps you write code efficiently, quickly, and high performance</p><ul><li><a href="https://es6.io/">ES6 for Everyone</a></li><li><a href="https://eloquentjavascript.net/">Eloquent JavaScript</a></li></ul><h4>Step 3 — Coding Style and Convention</h4><p>Coding standards (also sometimes known as ‘Coding Conventions’ or ‘Coding Rules’) are a set of guidelines that a group of developers stick to, to ensure that they all essentially follow the same style.</p><ul><li><a href="https://github.com/airbnb/javascript">Airbnb JavaScript Style Guide</a></li><li><a href="https://google.github.io/styleguide/jsguide.html#features-this">Google JavaScript Style Guide</a></li><li><a href="https://contribute.jquery.org/style-guide/js/">jQuery Style Guide</a></li></ul><p>Read about <a href="https://prettier.io/">prettier</a> and see how to configure it in order to format your code and save time.</p><h4>Step 4 — Review your knowledge</h4><p>Now is the time to review your understanding of JavaScript by answering interview questions</p><ul><li><a href="https://www.edureka.co/blog/interview-questions/javascript-interview-questions/">Top 50 JavaScript Interview Questions You Must Prepare in 2020</a></li><li><a href="https://www.guru99.com/javascript-interview-questions-answers.html">Top 85 JavaScript Interview Questions &amp; Answers</a></li><li><a href="https://www.toptal.com/javascript/interview-questions">37 Essential JavaScript Interview Questions</a></li></ul><h4>Step 5 — Practices</h4><ul><li>Learning JavaScript libraries (e.g. Lodash, ReactJS, Moment, jQuery, Ramda, and a lot more)</li><li>Learn JavaScript Frameworks such as Angular, VueJS, EmberJS)</li><li>Task runner (e.g. Gulp, Grunt) and module bunder (e.g. Webpack, Browserify)</li></ul><h4>Step 6 — Be an expert</h4><ul><li>Continue learning core concepts in JavaScript such as Closure, Hosting, Scope, Coercion, Prototypes</li><li>Learn OOP, <a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0">Functional Programming</a></li><li>Read this book <a href="https://addyosmani.com/resources/essentialjsdesignpatterns/book/">Learning JavaScript Design Patterns</a> or <a href="https://www.dofactory.com/javascript/design-patterns">design-patterns</a></li></ul><p>If you want to become a web, backend or full-stack developer, JavaScript isn’t enough, you need to learn more. Check out this roadmap and pick your path <a href="https://github.com/kamranahmedse/developer-roadmap">Web Developer Roadmap 2019</a> and keep yourself up to date.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ecaeb2adf285" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/a-brief-summary-of-javascript-learning-path-ecaeb2adf285">A brief summary of JavaScript Learning Path</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to build serverless cursor-based pagination service on the AWS Cloud]]></title>
            <link>https://medium.com/innomizetech/how-to-build-an-api-with-aws-lambda-to-paginate-data-using-serverless-41c4b6b676a4?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/41c4b6b676a4</guid>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[lambda]]></category>
            <category><![CDATA[api-gateway]]></category>
            <category><![CDATA[pagination]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Andy Nguyen]]></dc:creator>
            <pubDate>Wed, 20 Nov 2019 04:24:19 GMT</pubDate>
            <atom:updated>2019-11-20T05:51:08.011Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Serverless Cursor-based Pagination on AWS" src="https://cdn-images-1.medium.com/max/1024/1*XoYwpXuDQvjvTdZZN4weew.png" /></figure><p>In this port, I’ll be guiding you on how to build an API with AWS Lambda and API Gateway to paginate data using the <a href="https://serverless.com/">Serverless</a> framework.</p><h3>Technologies stack</h3><ul><li><a href="https://aws.amazon.com/lambda/"><strong>AWS Lambda</strong></a> for running code without provisioning or managing servers. You can utilize free-tier to run your service with <strong>zero</strong> cost.</li><li><a href="https://aws.amazon.com/api-gateway/"><strong>AWS API Gateway</strong></a> to create, publish, and secure Rest APIs.</li><li><a href="https://serverless.com/framework/docs/providers/aws/guide/intro/"><strong>Serverless</strong></a><strong> </strong>framework to build and deploy your backend services on the cloud, you can build and deploy a serverless function in minutes.</li></ul><h3>Prerequisites</h3><ul><li>An AWS account:<a href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/"> </a><a href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/">https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/</a></li><li>Have some experiences on AWS Cloud computing and the Serverless framework.</li></ul><h3>Cursor-based Pagination</h3><p>Have you ever heard this concept, it just is simple a pagination technique but it does not work the same with the classic pagination. Yes, the classic pagination that I think you will be familiar with, it works based on the <strong>offset-limit</strong> concept. An offset is a number that specifies the number of rows to skip before starting to return rows from the query. For simplicity, you want to see the data on page 3 with page size is 10, just skip 20 rows and return the next 10 rows as the result.</p><p><strong>Offset-limit</strong> is one of the most commonly used techniques for data paging. However, there are several drawbacks of using this approach:</p><ul><li>With a database that has large datasets, the offset clause makes slower querying as the number of records increases because the database still read up all records before skipping with offset records and return it.</li><li>In datasets that change frequently, the paged data becomes <strong>unreliable</strong> and possibility returns <strong>duplicate</strong> results.</li></ul><p><strong>Cursor-based pagination</strong> (aka keyset pagination<strong>)</strong> works based on a <strong>cursor</strong> that is a unique identifier for a specific record in datasets. We will deal with the cursor as the pointer of the next record that we will receive on the next page. And on subsequent requests, the server returns the cursor until there is no record on the next page.</p><p>There are a couple of approaches to implement cursor-based pagination, below are some interesting articles that I think you should take a look to get more details:</p><ul><li><a href="https://www.sitepoint.com/paginating-real-time-data-cursor-based-pagination/">Evolving API Pagination at Slack</a></li><li><a href="https://jsonapi.org/profiles/ethanresnick/cursor-pagination/">“Cursor Pagination” Profile</a></li><li><a href="https://slack.engineering/evolving-api-pagination-at-slack-1c1f644f8e12">Evolving API Pagination at Slack</a></li></ul><p><strong>Advantages</strong>:</p><ul><li>Prevent many of the drawbacks of classic pagination that I have mentioned above.</li><li>Scale well with the large datasets.</li></ul><p><strong>Disadvantages</strong>:</p><ul><li>The end-user cannot see the total number of items in the list.</li><li>The end-user cannot jump to a specific page or back to the previous page.</li></ul><p>With the above benefits, I chose <strong>cursor-based pagination</strong> for this implementation.</p><p>In this demo, I will show you how to implement cursor-based pagination using a unique and sequential column of the table (i.e. auto-increment column). Yeah, it is pretty simple and easy to understand.</p><h3>Serverless</h3><blockquote>The Serverless Framework helps you develop and deploy your AWS Lambda functions, along with the AWS infrastructure resources they require. It’s a CLI that offers structure, automation and best practices out-of-the-box, allowing you to focus on building sophisticated, event-driven, serverless architectures, comprised of <a href="https://serverless.com/framework/docs/providers/aws/guide/intro/#functions">Functions</a> and <a href="https://serverless.com/framework/docs/providers/aws/guide/intro/#events">Events</a>.</blockquote><p>There are ways to create and deploy an AWS Lambda function by using AWS Cloudformation or AWS Console. But I chose serverless because of its convenience, automation and the ability to increase development time.</p><p>One most of my favorite Serverless feature is the <a href="https://serverless.com/plugins/">plugin</a>, some of the plugins I recommend to use in this <a href="https://blog.innomizetech.com/2019/11/06/top-serverless-plugins-we-are-using/">article</a>. In this guide, I will use <a href="https://github.com/prisma-labs/serverless-plugin-typescript">serverless-plugin-typescript</a> and <a href="https://github.com/dherault/serverless-offline">serverless-offline</a> for building Serverless applications.</p><ul><li><a href="https://github.com/prisma-labs/serverless-plugin-typescript"><strong>serverless-plugin-typescript</strong></a><strong>:</strong> this plugin helps us to compile typescript during development and deployment. I like this plugin in usage with zero-configuration but there is an issue that I can’t solve during using this plugin is <a href="https://www.typescriptlang.org/docs/handbook/module-resolution.html"><strong>path resolver</strong></a>. You have to use relative import and make your code becomes lacking in aesthetics. To use non-relatitve import you can use another option such as <a href="https://github.com/serverless-heaven/serverless-webpack">https://github.com/serverless-heaven/serverless-webpack</a>.</li><li><a href="https://github.com/dherault/serverless-offline"><strong>serverless-offline</strong></a><strong>:</strong> emulates <a href="https://aws.amazon.com/lambda/">AWS Lambda</a> and <a href="https://aws.amazon.com/api-gateway">API Gateway</a> on your local machine to speed up your development cycles. If you are using serverless this plugin be indispensable during testing on local.</li></ul><p>With the serverless application, we must define a template file for the definition of your AWS resources, configurations, list of plugins, etc.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d68b6546efd81ed476522aad06395d2c/href">https://medium.com/media/d68b6546efd81ed476522aad06395d2c/href</a></iframe><p>In the functions section, we will link to the file that contains code for reading data with pagination. Before implementing code for that function, we have to create a database and datasets for testing purposes (should have more 50 items in the datasets). I will use the MySQL database and you can choose others such as MSSQL or PostgreSQL, etc for creating the database and preparing datasets.</p><p>Continue, to connect to the database we can install this <a href="https://github.com/mysqljs/mysql">package</a>, it is an awesome Node.js module for communicating with the MySQL database. However, the AWS Lambda function scales by creating separate instances for each concurrent request (you can see <a href="https://docs.aws.amazon.com/lambda/latest/dg/scaling.html">here</a> for more details). And this is a serious problem for the RDBS database like MySQL when we can get the maximum connection error anytime with high concurrent requests.</p><p>Luckily, Jeremy Daly has built a <a href="https://github.com/jeremydaly/serverless-mysql">package</a> that is wrapped for <a href="https://github.com/mysqljs/mysql">MySQL</a> to solve the above problem. We implement code for database helper as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c44b5bce60e1e25a725d910187f65967/href">https://medium.com/media/c44b5bce60e1e25a725d910187f65967/href</a></iframe><p>We create a file to build a query for reading data support cursor-based pagination:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ee3dff88257d8f5e0ee7d91f3dd4f5d2/href">https://medium.com/media/ee3dff88257d8f5e0ee7d91f3dd4f5d2/href</a></iframe><p>As you see above code, I use the <a href="https://hiddentao.github.io/squel/index.html">squel</a> to build the query string, you also manual to build the raw query. But I recommend you to use the <strong>squel</strong> by its benefits like:</p><ul><li>Supports parameterized queries for safe value escaping.</li><li>Supports Non-standard SQL.</li><li>Uses method chaining for ease of use.</li></ul><p>Finally, implement code for the function as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d03dc0e0d0d18ef63feb186243627c60/href">https://medium.com/media/d03dc0e0d0d18ef63feb186243627c60/href</a></iframe><p>The API we develop accepts two params:</p><ul><li>limit: a number value to limit records that return from the server.</li><li>cursor: a base64 string that is returned from the previous request. It indicates the starting point to retrieve data for the next page.</li></ul><p>For testing, I will run the following command to start API on local:</p><pre>sls offline</pre><p>Let’s explore our work. Using the <strong>Postman</strong>, we can easier invoke API</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lSbm96ySX3d8HMwTAEQGQQ.png" /></figure><h3><strong>Deploy</strong></h3><p>Deployment is much easier with the <strong>Serverless</strong> framework and can be done with one single command. So let’s deploy and see results by running below command:</p><pre>sls deploy --stage [your-stage] --region [your-region]</pre><p>Feel free to check out your deployment and try to invoke API Gateway on the AWS and compare results. I hope it works for you. If not, please let me know.</p><p>The source code is available on our <a href="https://github.com/innomizetech/pagination-serverless">Github</a></p><h3>Conclusion</h3><p>I hope this guide will be helpful to you and bring to you some ideas to help you build your services with cost-optimized, secured, flexible, high availability.</p><p>In this guide, I only write a simple code to show how to build and deploy. You are free to extend this project with some additional features as below:</p><ul><li>Supports more param options such as <em>fields</em>, <em>sort by</em> …</li><li>Implementing classic pagination (offset-limit pagination).</li><li>Implementing the error handler for handling such as <strong>InvalidCursorError</strong> or <strong>UnexpectedError</strong>.</li><li>Uses other databases such as <a href="https://aws.amazon.com/dynamodb/">Amazon DynamoDB</a> is a great option.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=41c4b6b676a4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/how-to-build-an-api-with-aws-lambda-to-paginate-data-using-serverless-41c4b6b676a4">How to build serverless cursor-based pagination service on the AWS Cloud</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[07 best practices when using AWS SSM Parameter Store]]></title>
            <link>https://medium.com/innomizetech/07-best-practices-when-using-aws-ssm-parameter-store-63c8e7ab0d9b?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/63c8e7ab0d9b</guid>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[security]]></category>
            <category><![CDATA[parameter-store]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[serverless]]></category>
            <dc:creator><![CDATA[Hoang Le]]></dc:creator>
            <pubDate>Tue, 19 Nov 2019 10:09:13 GMT</pubDate>
            <atom:updated>2023-07-28T01:50:53.279Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/692/1*lRVlnGfb09veHQ3Ef8HMkg.jpeg" /><figcaption><a href="https://blog.hubstor.net/cloud-storage-and-data-encryption-how-businesses-can-protect-information-in-the-cloud"><em>Cloud Encryption</em></a></figcaption></figure><p><strong>Security</strong> is one of 5 pillars of the Well-Architected framework, it can archive by applying best practices and principals in <strong>IAM</strong>, <strong>Encryption</strong>, <strong>Complician</strong>, and <strong>Governance</strong>. Of course, best practices aren’t enough, you need to learn more. In this post, I only share our best practices and tip when working with AWS SSM Parameter Store. By sharing our best practices, my hope is to encourage you to build and deploy secure and reliable applications and also giving us your feedback.</p><p>As you know, AWS Lambda supports native environment variables, you can easy to define and add any environment variables you want during deployment or change on the AWS Console Management. But using native environment variables contains some disadvantages:</p><ul><li>It stores plaint-text variables which easy to see its value. You had an option to encrypt variables in the console using KMS, but it still fetching per innovation causes increase your bill.</li><li>Hard to share across projects and teams that add complexity to your applications and services. More complexity requires more time to operate and increase the cost, therefore, you won’t meed the conditional for the <strong>Operational Excellence</strong> pillar of the Well-Architected framework.</li><li>As per Yan Cui, it hards for implementing fine-grained access to sensitive data.</li></ul><h4>What is AWS Systems Manager Parameter Store (aka SSM Parameter Store)?</h4><blockquote><em>AWS Systems Manager Parameter Store provides secure, hierarchical storage for configuration data management and secrets management. You can store data such as passwords, database strings, and license codes as parameter values. You can store values as plain text or encrypted data. You can then reference values by using the unique name that you specified when you created the parameter. Highly scalable, available, and durable, Parameter Store is backed by the AWS Cloud. ~</em><a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html"><em>AWS</em></a></blockquote><h4>What are the benefits?</h4><p>There are a lot of benefits when using AWS SSM Parameter Store, I just copied those from the AWS documentation:</p><ul><li>Use a secure, scalable, hosted secrets management service with no servers to manage.</li><li>Improve your security posture by separating your data from your code.</li><li>Store configuration data and secure strings in hierarchies and track versions.</li><li>Control and audit access at granular levels.</li><li>Configure change notifications and trigger automated actions for both parameters and parameter policies.</li><li>Tag parameters individually, and then secure access from different levels, including operational, parameter, Amazon EC2 tag, and path levels.</li><li>Reference AWS Secrets Manager secrets by using Parameter Store parameters.</li><li>Use Parameter Store parameters with other Systems Manager capabilities and AWS services to retrieve secrets and configuration data from a central store.</li><li>Configure integration with the AWS services for encryption, notification, monitoring, and auditing.</li></ul><p>So now you understand what is the SSM parameter store and its challenges, let talk about how we use it by reviewing the following our best practices and tips:</p><h4>#1 — Organizing parameters into hierarchies</h4><p>AWS provides detailed <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-paramstore-su-organize.html">instructions</a> on how to organize your SSM <strong>Parameter Store</strong> to define and manage parameters easily. Following its best practices can help you and make your life easier. Below are a couple of formats/conventions that our team normally using:</p><ul><li>/environment/service-name/type/application-name/parameter_name i.e. <em>/prod/billing/databases/invoicing-portal/db_connection_string</em></li><li>You also can add your department name as well i.e. <em>/prod/human-resource/employee/user_list</em></li></ul><h4>#2 — Consistent naming convention</h4><p>Using a <strong>well-defined</strong> hierarchy helps you to manage and retrieve parameters more efficiently, but you also need to use a consistent <a href="https://en.wikipedia.org/wiki/Naming_convention_(programming)">naming convention</a> across your AWS account, your departments, and your teams.</p><p>By archiving this best practice, it reduces your reviewing efforts by focusing on critical business logic rather than syntax and naming standards and then increase your productivity and quality which can increase your customer satisfaction.</p><h4>#3 — Restrict IAM permission</h4><p>AWS SSM Parameter Store normally keeps your sensitive information, so restrict permissions are required to improve your security of the application. Each Parameter Store has a unique Resource ARN per account and region, so you can easier to define role and policy base on the hierarchy of the parameter store.</p><p>Below is a sample code from the AWS official document shows how to define a policy to restrict access to the Parameter Store</p><pre>{<br>    &quot;Version&quot;: &quot;2012-10-17&quot;,<br>    &quot;Statement&quot;: [<br>        {<br>            &quot;Effect&quot;: &quot;Allow&quot;,<br>            &quot;Action&quot;: [<br>                &quot;ssm:*&quot;<br>            ],<br>            &quot;Resource&quot;: &quot;arn:aws:ssm:us-east-2::parameter/*&quot;<br>        },<br>        {<br>            &quot;Effect&quot;: &quot;Deny&quot;,<br>            &quot;Action&quot;: [<br>                &quot;ssm:GetParametersByPath&quot;<br>            ],<br>            &quot;Condition&quot;: {<br>                &quot;StringEquals&quot;: {<br>                    &quot;ssm:Recursive&quot;: [<br>                        &quot;true&quot;<br>                    ]<br>                }<br>            },<br>            &quot;Resource&quot;: &quot;arn:aws:ssm:us-east-2:123456789012:parameter/Dev/ERP/Oracle/*&quot;<br>        },<br>        {<br>            &quot;Effect&quot;: &quot;Deny&quot;,<br>            &quot;Action&quot;: [<br>                &quot;ssm:PutParameter&quot;<br>            ],<br>            &quot;Condition&quot;: {<br>                &quot;StringEquals&quot;: {<br>                    &quot;ssm:Overwrite&quot;: [<br>                        &quot;false&quot;<br>                    ]<br>                }<br>            },<br>            &quot;Resource&quot;: &quot;arn:aws:ssm:us-east-2:123456789012:parameter/*&quot;<br>        }<br>    ]<br>}</pre><h4>#4 — Combine into a single parameter likes database connection string and keep it all together (co-location)</h4><p>By using consistency hierarchies and naming convention you can archive this idea. Keep all related parameters all together makes easy to find and retrieve. Using fewer parameters can reduce your bills.</p><p>Instead of using 4 separated parameters for the database connection string as below:</p><pre>/{env}/{service}/databases/master/host = db.domain.com<br>                               /user = username<br>                               /password = password<br>                               /port = 3306</pre><p>We combine into a single parameter using a standard connection string format:</p><pre>/{env}/{service}/databases/master/db_connection = jdbc://username:password@db_host:port/database_name</pre><p>Using community library such as <em>connection-string-parser</em>, you can easy to parse the parameter values and use to open connection, see below code snippet:</p><pre>import { createConnection as createConnectionPromise, Connection } from &#39;promise-mysql&#39;;<br>import { ConnectionStringParser } from &#39;connection-string-parser&#39;;</pre><pre>const parseConnectionString = (dialect: string, connectionUri: string) =&gt; {<br>  const connectionParser = new ConnectionStringParser({<br>    scheme: dialect || &#39;mysql&#39;,<br>    hosts: []<br>  });<br>  const connectionStrParams = connectionParser.parse(connectionUri);</pre><pre>  return {<br>    host: connectionStrParams.hosts[0].host,<br>    port: connectionStrParams.hosts[0].port || 3306,<br>    database: connectionStrParams.endpoint,<br>    user: connectionStrParams.username,<br>    password: connectionStrParams.password<br>  };<br>};</pre><pre>export const createConnection = (connectionUri: string): Promise&lt;Connection&gt; =&gt; {<br>  return createConnectionPromise(parseConnectionString(&#39;mysql&#39;, connectionUri));<br>};</pre><h4>#5 — Use tool/library to fetch, cache, and export to environment variables at runtime</h4><p>You are charged for API integration to SSM parameters, every time you retrieve your parameter from the store, you will increase your bill. What could you do to reduce your billing?</p><p>By default, <strong>max throughput (transactions per second) to retrieve parameter via API is 1000</strong>, how do you manage and avoid exceed throughput error?</p><p><a href="https://twitter.com/theburningmonk">@Yan Cui</a> wrote an <a href="https://hackernoon.com/you-should-use-ssm-parameter-store-over-lambda-env-variables-5197fc6ea45b">article</a> describes reasons why you should use AWS SSM Parameter Store over Lambda environment variables, he also mentioned approaches for caching and cache expiration using his custom client library.</p><p>Our team is using <a href="https://github.com/middyjs/middy">middy</a> middleware to deal with some cross-cutting concerns outside business logic, like input parsing and validation, output serialization, error handling. Application configuration also an aspect that every developer needs to work out and manage to run business logic. Out of the box, middy provides <a href="https://github.com/middyjs/middy/blob/master/docs/middlewares.md#ssm">ssm</a> middleware support fetch and cache parameters from the AWS SSM Parameter Store, it also supports assign parameter values to environment variables.</p><p>Here is a sample code on how to use middy to fetch and cache parameter store</p><pre>const middy = require(&#39;middy&#39;);<br>const { ssm } = require(&#39;middy/middlewares&#39;);</pre><pre>export const handler = middy((event, context, cb) =&gt; {<br>  // You can access the parameter value inside function handler<br>  console.log(process.env.HARVESTAR_PCMSS_DB_CONNECTION);</pre><pre>  // Your business logic here<br>}).use(<br>  ssm({<br>    cache: true,<br>    names: {<br>      // Should have a prefix that include this micro service i.e. pcmss<br>      HARVESTAR_PCMSS_DB_CONNECTION: &#39;/dev/harvestar/pcmss/db_connection&#39;<br>    }<br>  })<br>);</pre><p>There are some alternative open-sourced libraries out there:</p><ul><li><a href="https://www.npmjs.com/package/aws-parameter-cache">aws-parameter-cache</a></li><li><a href="https://github.com/alexcasalboni/ssm-cache-python">ssm-cache-python</a></li></ul><p><strong>Do you really trust the community package?</strong></p><p>I head from some people, basically, they don’t want to assign variables into environment variables (i.e. variables you can access through the <em>process.env</em> global object in Node.js runtime). If you do so, I have some advice as below:</p><ul><li>Instead of assign variables to <em>environment variables</em>, you also have another option to assign the <em>context</em> object of the AWS Lambda when using <strong>middy/ssm</strong> middleware.</li><li>To avoid sending your sensitive information such as data credentials, accessing to the <em>/tmp </em>directory, or running a child process when executing your serverless functions. You can use <a href="https://www.npmjs.com/package/@puresec/function-shield">@puresec/function-shield</a> library. We are also using it in our production environment.</li></ul><blockquote><strong><em>TIPS — Avoid fetching parameters at build/deploy time, fetch it at runtime instead. If you do so, you have to redeploy each time the parameter changed.</em></strong></blockquote><h4>#6 — Using hardcoded environment variables for your local development</h4><p>Do you need to run your function locally that fetches AWS SSM Parameter Store directly? The answer is it is optional, for your local environment, you might not need to use AWS SSM Parameter Store, you can use a .<em>env </em>file to keep your local variables. Below are some approaches you can use to archive that idea, note you still need to test your function with your desired approach on AWS environment:</p><ul><li>Use the <a href="https://www.npmjs.com/package/env-cmd">env-cmd</a> library to load, extract and assign to <em>process.env </em>global object. By running <strong><em>env-cmd serverless offline</em></strong> command, you can access all variables defined in your .env file.</li><li>Using the <a href="https://github.com/serverless/serverless-secrets-plugin">serverless-secrets-plugin</a> to define the environment variable in a secured manner, you can easier to share across the team and commit the encrypted file.</li></ul><p>Using the same code as below with a modification, you can skip fetching parameter store from AWS and reduce your bill:</p><pre>const middy = require(&#39;middy&#39;);<br>const { ssm } = require(&#39;middy/middlewares&#39;);</pre><pre>const isLocalEnv = process.env.IS_OFFLINE || process.env.IS_LOCAL;</pre><pre>export const handler = middy((event, context, cb) =&gt; {<br>  // You can access the parameter value inside function handler<br>  console.log(process.env.HARVESTAR_PCMSS_DB_CONNECTION);</pre><pre>  // Your business logic here<br>}).use(<br>  ssm({<br>    cache: true,<br>    // By setting the paramsLoaded, you tell the middleware to<br>    // not fetch it from AWS SSM<br>    paramsLoaded: isLocalEnv,<br>    names: {<br>      // Should have a prefix that include this micro service i.e. pcmss<br>      HARVESTAR_PCMSS_DB_CONNECTION: &#39;/dev/harvestar/pcmss/db_connection&#39;<br>    }<br>  })<br>);</pre><h4>#7 — Pay attention to services limits</h4><p>Likes other AWS services, AWS SSM Parameter Store also has some limits, such as the maximum number of params per account and region, max param value size, max history. Understanding its limits help us design and build applications with high reliability. For example, avoid storing large items into the SSM parameter because of size limits (4KB for standard and 8KB for the advanced parameter). Refer to <a href="https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html">AWS service limits documentation</a> for more others.</p><h4>Resources</h4><ul><li><a href="https://hackernoon.com/you-should-use-ssm-parameter-store-over-lambda-env-variables-5197fc6ea45b">You should use SSM Parameter Store over Lambda env variables</a></li><li><a href="http://sharing%20secrets%20with%20aws%20lambda%20using%20aws%20systems%20manager%20parameter%20store/">Sharing Secrets with AWS Lambda Using AWS Systems Manager Parameter Store</a></li><li><a href="https://velotio.com/blog/2018/9/2/managing-secrets-using-aws-systems-manager-parameter-store">Managing Secrets Using AWS Systems Manager Parameter Store and IAM Roles</a></li></ul><h4>Conclusion</h4><p>By applying best practices, you can implement your applications with more <strong>reliable</strong>, <strong>secure</strong>, <strong>efficient, and cost-effective</strong> software on the cloud.</p><p>I hope this post brings some ideas to you and saves time. There are more interesting and useful articles, so find and read them to get more information. Feel free to let me know your recommendations or suggestions by adding comments below.</p><p>Thank you for reading!</p><p>This post appears first on <a href="https://innomizetech.com/blog/07-best-practices-when-using-aws-ssm-parameter-store">our blog</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=63c8e7ab0d9b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/07-best-practices-when-using-aws-ssm-parameter-store-63c8e7ab0d9b">07 best practices when using AWS SSM Parameter Store</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My Cloud computing journey]]></title>
            <link>https://medium.com/innomizetech/my-cloud-computing-journey-e6bf9cb84cf2?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/e6bf9cb84cf2</guid>
            <category><![CDATA[cloud-development]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[journey]]></category>
            <dc:creator><![CDATA[Hoang Le]]></dc:creator>
            <pubDate>Sat, 16 Nov 2019 14:31:13 GMT</pubDate>
            <atom:updated>2023-07-28T01:56:47.832Z</atom:updated>
            <content:encoded><![CDATA[<p><strong><em>Cloud computing</em></strong> is a buzzing <em>word nowadays</em>. It appeared as early as 1996, with the first known mention in a Compaq internal document (<a href="https://en.wikipedia.org/wiki/Cloud_computing">per Wiki</a>). Many companies are joining the cloud computing journey and archived a lot of benefits.</p><p>I have been working on various cloud computing projects from start to finish; involved in the full project lifecycle, including design, planning, development, deployment, testing, maintenance, and support. Some clients prefer to use their on-premise data centers, but most of my projects used the cloud — <a href="https://aws.amazon.com/">Amazon Web Services</a>, <a href="https://azure.microsoft.com/en-us/">Microsoft Azure</a>, and <a href="https://www.heroku.com/">Heroku</a>. So, I wanted to write this post to share my <a href="https://en.wikipedia.org/wiki/Cloud_computing">cloud computing</a> journey. My hope is to encourage you to build secure, scalable, highly available, and cost-effective cloud applications. <strong>Learn to share and share to learn </strong>will help us all grow, don’t you agree?</p><p>If you are new to the cloud and wanted to explore more information, check out some articles below:</p><ul><li><a href="https://www.bluesilvershift.com/why-are-so-many-businesses-moving-to-the-cloud-2/">Why are so many businesses are moving to the cloud?</a></li><li><a href="https://www.technologyreview.com/s/425970/who-coined-cloud-computing/">Who Coined ‘Cloud Computing’?</a></li><li><a href="https://cloudcomputing521.wordpress.com/2017/05/01/history-of-cloud-computing/">History of Cloud computing</a></li><li>Check out <a href="https://www.softwaretestinghelp.com/cloud-computing-service-providers/">15 Top Cloud Computing Services Provider Companies</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/0*WWxSUjaeUm7p8xhz.png" /><figcaption>Cloud computing from Wiki</figcaption></figure><p>This is a lengthy article. So, if you prefer to simply view a particular topic, you can use the table of contents below.</p><ul><li><a href="#5ff7">Who am I?</a></li><li><a href="#a839">Starting my career as a software developer</a></li><li><a href="#1947">The beginning of my cloud computing journey</a></li><li><a href="#9a51">My startup journey is just started</a></li><li><a href="#c650">My own company is officially established</a></li><li><a href="#4c1e">We got the first AWS certification</a></li><li><a href="#cd11">A few more serverless projects</a></li><li><a href="#8df4">Our most recent cloud computing projects</a></li><li><a href="#4be7">Other works</a></li><li><a href="#84f6">My future plan</a></li></ul><h4>Who am I?</h4><p>Firstly, I’d like to introduce myself. My name is <strong>Hoang</strong>, I am the <strong>Co-founder and CTO </strong>of <a href="https://www.innomizetech.com/">InnomizeTech</a>. My title is <strong>CTO</strong> but I am a <strong>full-stack developer</strong> <strong>and software architect</strong>, passionate about <strong>Cloud Computing</strong>, <strong>Serverless</strong>, <strong>DevOps</strong>, <strong>Machine Learning</strong>, and <strong>IoT</strong>.</p><p>With 7+ years of experience in software development (web, desktop, and mobile), systems integration, Cloud computing, DevOps engineering, project management, and agile methodology, I thrive working both independently and collaboratively in a team and have strong leadership and communication skills from working directly with both technical and non-technical stakeholders.</p><h4>Starting my career as a software developer</h4><p>Before transitioning to <a href="https://en.wikipedia.org/wiki/Cloud_computing">Cloud computing</a>, I worked for an <a href="https://en.wikipedia.org/wiki/Outsourcing">outsourcing</a> company in Vietnam for four years after I graduated from University.</p><ul><li><strong>For the first two years</strong>, the primary programming language I used was <strong>C# (AWS .NET WebForm and AWS .NET MVC)</strong>.</li><li><strong>For the next year</strong>, I transitioned to another role, leading a team working with system integration stuff using <a href="https://wso2.com/">WSO2</a> and <a href="https://en.wikipedia.org/wiki/Microsoft_BizTalk_Server">BizTalk</a>, among other tools. I had a chance to work with our client’s CTO. We had a lot of fun and we did a great job.</li></ul><h4>The beginning of my cloud computing journey</h4><p><strong>In the third year</strong>, I started my first <strong>Cloud computing</strong> project. We had a project from a US-based client to build an application for activating mobile devices for various carriers. I was the technical lead of that project. After studying the requirements, we selected the following technology stack:</p><ul><li><a href="https://nodejs.org/en/">Node.js</a> for back-end, using the <a href="https://sailsjs.com/">Sails<strong>.</strong>js</a> framework</li><li><a href="https://www.mysql.com/">MySQL</a> database and using <a href="https://sequelize.org/master/manual/getting-started.html">Sequelize</a> for ORM. We used <a href="https://www.liquibase.org/">Liquibase</a> to generate, and migrate the database schema using source control.</li><li><a href="https://angular.io/">Angular</a> for the front-end application</li></ul><p>Actually, it isn’t a real <a href="https://searchcloudcomputing.techtarget.com/definition/cloud-application">cloud-based application</a>, since we used only a few cloud services to build the app. We have built the app and used the <a href="https://aws.amazon.com/elasticbeanstalk/"><strong>Elastic Beanstalk</strong></a> service for hosting. I have studied <a href="https://jenkins.io/">Jenkins</a> and built a Jenkins job for analyzing code, building, testing, and deploying to the Elastic Beanstalk app. Here is the diagram of the CI/CD I built at that time:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/613/0*zpGv2PQkmRu5XQDh" /></figure><p>We initially hosted the application on <strong>Elastic Beanstalk</strong> apps in order to apply our CI/CD script using AWS Beanstalk plugin on Jenkins for deployment. However, our client wanted to host it in their data center. Then we still use Beanstalk for our SIT/UAT environments, but we had to write documentation of around <strong>10 pages</strong> to describe how to set up <strong>Web Servers, App Servers</strong>, <strong>NGINX</strong>, <strong>Node.js,</strong> <strong>RDS</strong>, <strong>etc</strong>. A lot of back-and-forth communication between our <strong>development team</strong> and <strong>infra team</strong> because of issues and errors. But finally, we have successfully deployed, and the app is up and running<strong>.</strong></p><p>We kept working on that project for around a year. While developing new features, I also learned <a href="https://www.ansible.com/">Ansible</a> and built some playbooks to allow my client to deploy the app automatically without manual steps.</p><ul><li>Continuous Deployment — Deploying A Node.Js App To AWS EC2 Using Ansible</li></ul><p>At that time, I and my co-workers established a technical club to study and share about cloud computing. We learning cloud computing concepts and doing some hands-on exercises with <strong>AWS</strong> and <strong>Microsoft Azure</strong>. You can visit our <a href="https://www.facebook.com/groups/992679037443304/">Facebook page</a> to see our activities and great memories.</p><p>Before leaving the company, I studied and shared my CI/CD experiences. I have presented <a href="https://www.slideshare.net/HoangLe84/introduction-to-cicd-190596305">this presentation</a> for my promotion to the <strong>Senior Engineer</strong> position (I have changed a few things to share with everyone).</p><h4>My startup journey is just started</h4><p>In <strong>August 2017</strong>, I started my<strong> own job</strong>. We had a project for building a core/shared backend API for various client applications including <strong>SPA</strong>, <strong>Mobile App</strong>,<strong> and Integration services</strong>. After clarifying requirements with our clients, we have selected the below technology stack:</p><ul><li><a href="https://aws.amazon.com/lambda/">AWS Lambda</a> uses Node.js runtime and <a href="https://aws.amazon.com/api-gateway/">Amazon API Gateway</a> that utilize Auth, Caching, Logging, Monitoring Throttling, and Bursting Elastic features for backend services.</li><li>We use the <a href="https://serverless.com/">Serverless</a> framework for building API, deploying and configuring AWS resources such as S3 bucket, SNS topic, Queue, and DynamoDB. At this time, we used <strong>JavaScript</strong> as the primary programming language.</li><li><a href="https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html">Amazon Cognito User Pool </a>for authentication and authorization.</li><li><a href="https://aws.amazon.com/rds/aurora/">Amazon Aurora</a> for the relational database. We keep using <a href="https://sequelize.org/master/manual/getting-started.html">Sequelize</a> and <a href="https://www.liquibase.org/">Liquibase</a>.</li><li><a href="https://aws.amazon.com/elasticache/">Amazon Elastic Cache (Redis) </a>for in-memory caching.</li><li>Other AWS services we have used such as VPC, S3, SNS, SQS, CloudWatch, Route53, Certification Manager, AWS System Manager, AWS Parameter Store, X-Ray</li><li><a href="https://angular.io/">Angular</a> for the frontend app. Static hosting with<a href="https://blog.innomizetech.com/2019/10/25/how-do-we-host-our-static-website/"> S3 and CloudFront</a>.</li><li><a href="https://jasmine.github.io/">Jasmine</a>, <a href="https://www.protractortest.org/#/">Protractor</a> for unit test, integration test, and E2E test.</li><li>We still use Jenkins for our DevOps server. But instead of defining the job manually on the admin console page, we wrote a Jenkinsfile that used the <a href="https://jenkins.io/doc/tutorials/build-a-multibranch-pipeline-project/https://jenkins.io/doc/tutorials/build-a-multibranch-pipeline-project/">Mutliplebranch pipeline.</a></li><li>And more…</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*IQAzwZV7ldbJkWtw" /></figure><p>We kept applying the same stack to a few projects for other clients and continuously improve and refactored our core modules/libraries. We have delivered and received positive feedback from our clients. The applications were running well, had lower costs, high availability, and were secure.</p><p>In relation to <strong>DevOps</strong>, we have all the stuff scripted and provided CLIs to allow building and deploying applications automatically. We’ve used <a href="https://aws.amazon.com/cloudformation/">CloudFormation</a> to provision and configure infrastructure components such as VPC, RDS. We outlined steps to deploy/remove and send it over to our client, DevOps engineers, they can deploy a new environment using a few commands and then remove it completely without manual steps. <strong>Automation reduces human mistakes and increases productivity and quality.</strong></p><h4>My own company is officially established</h4><p>In <strong>October 2018</strong>, we officially established <a href="https://www.innomizetech.com/">InnomizeTech</a>, our mission is to create awesome products that will make your everyday life easier. <strong>My aim is to build a professional team with passion, enthusiasm, and talent that can help bring more value to our customers and help them move fast and in the right direction.</strong></p><p>The experienced engineering and development team at <strong>Innomize</strong> are committed, and passionate, and continually challenge themselves on the advancements and changes of the technologies we utilize to deliver the most up-to-date and innovative solutions.</p><h4>We got the first AWS certification</h4><p>I and my team have been learning, and building a lot of real-world cloud-based applications for many years. To prove to our clients that we had the experience to do their jobs, we studied and took some AWS exams and finally, our team got AWS certifications:</p><ul><li>02 AWS Certified Solution Architecture — Associate</li><li>02 AWS Cloud Practioner</li><li>01 AWS Certified Developer — Associate</li></ul><p>We have been with <a href="https://www.thecoraledge.com/">The Coral Edge</a> our partner and primary client. Recently, they officially became the <strong>Select Consulting Partner</strong> with <strong>AWS</strong> and we are their Development Team.</p><h4>A few more serverless projects</h4><p><strong>In early 2019</strong>, we had a contract with another client from the US, we will help their development team maintain and build new features for their micro-services (the integration component for their e-commerce system). They used <a href="https://www.scala-lang.org/">Scala</a> as their programming language, and <a href="https://gradle.org/">Gradle</a> as the build tool, their developer implemented some <a href="https://gradle.org/">Gradle</a> tasks to deploy the Lambda function, create the API gateway, and other required AWS resources. Here is the technology stack I can summarize:</p><ul><li>Each microservice has its own <strong>Lambda</strong> function and <strong>API Gateway</strong> as the original design. They had an <a href="https://www.nginx.com/">NGINX</a> server as a <a href="https://en.wikipedia.org/wiki/Reverse_proxy">reserved proxy </a>server that will route traffic to AWS API gateways based on the request path.</li><li><a href="https://github.com/http4s/http4s">http4s</a> as the interface for Restful API.</li><li>They used the <strong>Postgres</strong> database and also using <strong>Liquibase</strong> to manage their database schema and versioning. They used <a href="https://github.com/tpolecat/doobie">Doobie</a> for functional JDBC for Scala.</li><li><a href="https://sentry.io/welcome/">Sentry</a> for error monitoring and reporting.</li><li>They do use <a href="https://aws.amazon.com/codebuild/">AWS CodeBuild</a>, <a href="https://aws.amazon.com/codedeploy/">AWS CodeDeploy</a>, and <a href="https://aws.amazon.com/codepipeline/">AWS CodePipeline</a> to implement CI/CD but it isn’t fully implemented when we join their team.</li></ul><p>When our developers work with their team, we have proposed some approaches to enhance and refactor their design:</p><ul><li>To remove their NGINX server and cost, we suggest they apply the <a href="https://www.jeremydaly.com/serverless-microservice-patterns-for-aws/">Robust API</a> pattern.</li><li>We helped design and built a <strong>project template</strong> in order to add a new microservice easily. Here are some of our ideas:</li><li>Defining a project template that uses AWS CodeStart which will allow us to create <strong>CodeCommit</strong> repositories, and define <strong>CodeBuild</strong> projects, and <strong>CodePipelines</strong> automatically when creating a new project. New microservices can be up and running by using a single command.</li><li>We suggest using the <a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html">AWS SAM</a> framework for building Lambda functions and defining required AWS resources (i.e. Queue, Bucket, Topic, etc.). Previously, they deployed Lambda and other resources by implementing custom Gradle tasks.</li></ul><h4>Our most recent cloud computing projects</h4><p>Recently, we have been working on some projects that apply Micro-service architecture. We continue the above technology stacks with some changes/improvements:</p><ul><li>We used <a href="https://nx.dev/angular">NX Dev Tool</a> to define our workspace on a Monorepo. We built our CI/CD pipeline that supports deploying only affected apps by a change instead of redeploying all services. Thanks to the <strong>NX</strong> team for their idea and awesome tool.</li><li><a href="https://aws.amazon.com/step-functions/">Step Functions</a> for our micro-service communication, automated workflow.</li><li><a href="https://nestjs.com/">NestJS</a> for our Restful API that running on AWS Lambda.</li><li>AWS CDK to provision and configure our infrastructure as code (IoC)</li><li><a href="https://jestjs.io/">Jest</a>, <a href="https://www.cypress.io/">Cypress</a> for unit test, integration test, and E2E testing.</li><li>Along with using <a href="https://aws.amazon.com/cognito/">Cognito</a> we also use <a href="https://www.okta.com/">Okta</a>, <a href="https://auth0.com/">AuthO</a> for authentication and authorization.</li><li>CI/CD with <a href="https://aws.amazon.com/products/developer-tools/">AWS Develop Tools,</a> <a href="https://jenkins.io/">Jenkins</a>, <a href="https://azure.microsoft.com/en-us/services/devops/">Azure DevOps</a>.</li><li>Along with using Node.js runtime, we also use <strong>Java/Scala</strong> and <strong>.NET Core</strong> runtime.</li></ul><h4>Other works</h4><p>We focused on <strong>AWS</strong> as the primary cloud vendor and wanted to become an active development service by partnering with them. Along with cloud computing, our team also has experience in other technologies. We work with the latest technologies specializing in Web Development, Mobile Development, Cloud Computing (AWS, Azure), DevOps, and Automation Testing. Refer to our <a href="https://www.innomizetech.com/#services">Services</a> section on our website for more information.</p><p>We continue working on some other projects such as:</p><ul><li>DevOps using <a href="https://aws.amazon.com/cloudformation/">CloudFormation</a>, <a href="https://docs.aws.amazon.com/cdk/latest/guide/home.html">AWS CDK</a>, <a href="https://www.ansible.com/">Ansible</a></li><li><a href="https://aws-amplify.github.io/">Amplify</a> framework: hosting, authentication, Mobile App with AppSync.</li><li>Ruby on Rails app on AWS ECS.</li><li>Headless upload bills to various sites with AWS ECS and Protractor (<a href="https://www.youtube.com/watch?v=OJ4B81630MI&amp;t=29s">End to end automation test with Protractor</a>).</li><li><a href="https://blog.innomizetech.com/2019/11/01/building-serverless-web-crawler-with-puppeteer-on-aws-fargate/">Serverless web crawler with Puppeteer on AWS Fargate</a> that I recently wrote that post.</li><li>React, Amplify, AppSync.</li><li>Work with other AWS services such as <strong>AWS WAF,</strong> <strong>AWS Shield</strong>, <strong>Glue</strong>, <strong>ElasticSearch</strong>, <strong>Kinesis</strong>, and <strong>Athena</strong>.</li><li>We helped some clients design and define <strong>DevOps</strong>, and CI/CD pipelines using <strong>AWS Developer Tools</strong> and <strong>Azure DevOps</strong>.</li></ul><h4>My future plan</h4><p>My quote is <strong>“Learn to share and share to learn”</strong>, I am continually challenging myself on the advancements and changes of the technologies. I wanted to meet more people, talk, work, and help them. I do have a few things on my list so I am going to do:</p><ul><li>Build <a href="https://www.innomizetech.com/">Innomize</a> stronger, work with more clients, and collaborate with more people.</li><li>Learn more things such as Machine Learning, Deep Learning, Transfer Learning, Convolution Neural Networks, and IoT.</li><li>Build my own product.</li></ul><p>I cannot describe anything about myself in this post, if you wanted to know more about me and our team, then you can get in touch with me via:</p><ul><li><a href="https://twitter.com/hoangleitvn">Twitter</a></li><li><a href="https://www.linkedin.com/in/hoangleitvn/">LinkedIn</a></li><li><a href="https://dev.to/hoangleitvn">DEV Community</a></li><li><a href="https://github.com/hoang-innomizetech">Github</a></li><li><a href="https://medium.com/@hoangleitvn">Medium</a></li><li><a href="mailto:hoang@innomizetech.com">Email</a></li></ul><p>If you are looking for developers, an offshore team, or need consulting about the AWS cloud, Serverless architecture, and so on, then <a href="https://innomizetech/contact-us">get in touch with us</a>, we can help you!</p><p>Thank you for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e6bf9cb84cf2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/my-cloud-computing-journey-e6bf9cb84cf2">My Cloud computing journey</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a CRUD application with Angular using Ngrx (Part 2)]]></title>
            <link>https://medium.com/innomizetech/building-a-crud-application-with-angular-using-ngrx-part-2-d13ad09c86f6?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/d13ad09c86f6</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[angular]]></category>
            <dc:creator><![CDATA[Andy Nguyen]]></dc:creator>
            <pubDate>Sat, 16 Nov 2019 14:01:18 GMT</pubDate>
            <atom:updated>2019-11-19T02:21:16.972Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/953/1*CtXgX7LzUH0EpxN84rntKw.png" /></figure><p>In the <a href="https://medium.com/innomizetech/building-a-crud-application-with-angular-using-ngrx-part-1-725af50f1548">previous part</a>, I have shown how to build a sample mockup API for CRUD application as well as build a sample list page. In this part, we will continue to build CRUD application on creating, updating and deleting an entity using Ngrx.</p><p>Before continuing, I want to introduce to you a special thing is “<strong>Optimistic UI</strong>”.</p><h3>What is O<strong>ptimistic UI?</strong></h3><blockquote>Optimistic UI is a pattern that you can use to simulate the results of a mutation and update the UI even before receiving a response from the server. Once the response is received from the server, the optimistic result is thrown away and replaced with the actual result ~ <a href="https://www.apollographql.com/docs/react/performance/optimistic-ui/">Apollo</a>.</blockquote><p>Let’s remember the previous approach for handling update operation (I call this approach is <strong>Synchronous UI</strong>):</p><ul><li>The end-user click update action.</li><li>The end-user click update action.</li><li>Make an HTTP request for the update operation.</li><li>Displays a spinner (or loading image) for waiting for the success response from the server.</li><li>After the server responses successfully, we continue to refresh data on UI to reflect with the updated result for consistency. Otherwise failed, display an error message.</li></ul><p>And if we apply the <strong>Optimistic UI</strong> approach:</p><ul><li>The end-user click update action.</li><li>Make an HTTP request for updating operation and the UI value is updated immediately assuming the response will be successful.</li><li>After the server responses successfully, we do not anything. Otherwise failed, revert the UI value as the previous state.</li></ul><p>As you see two above approaches, the <strong>Synchronous UI </strong>approach needs a step that showing a spinner for waiting for the server’s response and the UI just is updated after the server is responded. In most cases, there is no reason to wait for a successful response when we assume that all requests are expected to be successful. Like that, the <strong>Optimistic UI</strong> approach brings to the end-user a faster user experience, more smooth and stable.</p><p>Now, we will go dive to implement CRUD application with optimistic interaction.</p><p>As part 1, we have built the CRUD application to read Entity from the server and display it using Ngrx. Before we implement the update Entity feature, we need update code for some files as preparation.</p><p>Update the <em>entity.service.ts</em> file as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1a51e0eee7beb8c69cb6785853780d5c/href">https://medium.com/media/1a51e0eee7beb8c69cb6785853780d5c/href</a></iframe><p>Update <em>entities.page.html</em> to add some action links:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a1abb44404a20481fa68d15164bc14a0/href">https://medium.com/media/a1abb44404a20481fa68d15164bc14a0/href</a></iframe><h3>Update Entity</h3><p>First, we update <em>entity.actions.ts</em> file to add some actions as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7d358ffcda4f4d247b797ccc5e03e706/href">https://medium.com/media/7d358ffcda4f4d247b797ccc5e03e706/href</a></iframe><p>Next, update the <em>entity.reducer.ts</em> file as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a2b614e51e8f4825d4b4e318a0b5685/href">https://medium.com/media/7a2b614e51e8f4825d4b4e318a0b5685/href</a></iframe><p>Update the<em> entity.effects.ts</em> file as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2a5481fa2d870da4875ea51099693a5e/href">https://medium.com/media/2a5481fa2d870da4875ea51099693a5e/href</a></iframe><p>And update the <em>entity.selectors.ts</em> file as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dacf39dc259b510a3abc30e0e13ba585/href">https://medium.com/media/dacf39dc259b510a3abc30e0e13ba585/href</a></iframe><p>As you can see above the action file, we define an additional action is “Load Entity” for reading Entity detail from the server or the available store and display it for the user to edit. If you click edit on List of Entities page, just load data from the store that is loaded before. In case the user pastes the editing Entity page URL direct to the browser’s address, an HTTP request will be called to retrieving Entity detail instead of.</p><p>In the reducer file, you will see the “<strong>updateEntity</strong>” action will update immediately the state reflects with the updated entity even the server does not respond yet. And we need an action to revert the store to the previous state for case unsuccessful response. I used <a href="https://github.com/brechtbilliet/ngrx-undo"><strong>ngrx-undo</strong></a> to handle this case, the <a href="https://github.com/brechtbilliet/ngrx-undo"><strong>ngrx-undo</strong></a> provides a wrapper function to revert a specified action with the simple configuration, you can see I have used this library in the entity.effects.ts file for error handling section. To install this library you can refer to this <a href="https://github.com/brechtbilliet/ngrx-undo">link</a>.</p><p>Ok, we will develop a page for Entity editing as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/720dd2dc464e8bec6d425202c6582e84/href">https://medium.com/media/720dd2dc464e8bec6d425202c6582e84/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/16cacd00be0a0716e0b9ff98a3e186a0/href">https://medium.com/media/16cacd00be0a0716e0b9ff98a3e186a0/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8b89270d11737f6dd7b53718b0858b5c/href">https://medium.com/media/8b89270d11737f6dd7b53718b0858b5c/href</a></iframe><p>And don’t forget to define the route for Entity editing page:</p><pre>{</pre><pre>    path: &quot;edit/:id&quot;,</pre><pre>    component: EntityPage,</pre><pre>    resolve: {</pre><pre>        entity: EntityResolver</pre><pre>    }</pre><pre>}</pre><p>Gives the result as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/1*RFpOiO63rE0PklEwx7X99Q.png" /><figcaption>Entities page</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/1*DVVfHR3qa_e-bJp4t05gEg.png" /><figcaption>Entity editing page</figcaption></figure><h3>Create an Entity</h3><p>Now to create the Entity in the server, we need to perform HTTP POST operation and pass the data that needs to be inserted. We will take a “<strong>createEntity</strong>” action for that.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44530a21645a7bf9e8e618d5ad7264eb/href">https://medium.com/media/44530a21645a7bf9e8e618d5ad7264eb/href</a></iframe><p>Update reducer and effect files to add some code as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1c2fa4e7147d994b0b7dd7a77414872a/href">https://medium.com/media/1c2fa4e7147d994b0b7dd7a77414872a/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0ccaebebc46ba2b3596cfcc286507947/href">https://medium.com/media/0ccaebebc46ba2b3596cfcc286507947/href</a></iframe><p>And we can reuse the Entity editing page for creation operation, update code the entity.page.ts file as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/00f53852234480399d5aeede350480ac/href">https://medium.com/media/00f53852234480399d5aeede350480ac/href</a></iframe><h3>Delete Entity</h3><p>Similarly, we only need to define “<strong>deleteEntity</strong>” action and call the action on the delete method that we have added before:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/83bbcde82706da7b61dfe226d83a4b50/href">https://medium.com/media/83bbcde82706da7b61dfe226d83a4b50/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b3798f5826488f0fc94100386ff8b1a0/href">https://medium.com/media/b3798f5826488f0fc94100386ff8b1a0/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bf5d14eb1a391eefa2453554aee4f356/href">https://medium.com/media/bf5d14eb1a391eefa2453554aee4f356/href</a></iframe><p>Implement the delete method as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1ed6d84a92bf4b92412221e5c4b36d5/href">https://medium.com/media/e1ed6d84a92bf4b92412221e5c4b36d5/href</a></iframe><p>Done, enjoy the result as below:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodesandbox.io%2Fembed%2Fcrud-angular-ngrx-part-2-iczk9%3Ffontsize%3D14&amp;url=https%3A%2F%2Fcodesandbox.io%2Fs%2Fcrud-angular-ngrx-part-2-iczk9%3Ffontsize%3D14&amp;image=https%3A%2F%2Fcodesandbox.io%2Fapi%2Fv1%2Fsandboxes%2Ficzk9%2Fscreenshot.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codesandbox" width="1000" height="500" frameborder="0" scrolling="no"><a href="https://medium.com/media/9091d2acdc1dc46706affed8bdbfb149/href">https://medium.com/media/9091d2acdc1dc46706affed8bdbfb149/href</a></iframe><h3>Summary</h3><p>Coming to the end of this guide, let us have a quick recap of what we did.</p><ul><li>Use <strong>Optimistic UI</strong> approach to make the application faster and smoother.</li><li>Use the <strong>ngrx-undo</strong> library for reverting the store as the previous state on the unsuccessful response case.</li></ul><p>Thank for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d13ad09c86f6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/building-a-crud-application-with-angular-using-ngrx-part-2-d13ad09c86f6">Building a CRUD application with Angular using Ngrx (Part 2)</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build your first Chart using Angular & Ng2-charts]]></title>
            <link>https://medium.com/innomizetech/build-your-first-chart-using-angular-ng2-charts-3517c8aaf5bd?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/3517c8aaf5bd</guid>
            <category><![CDATA[angular]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[ng2-charts]]></category>
            <category><![CDATA[chartjs]]></category>
            <dc:creator><![CDATA[Anh Nguyen Dang]]></dc:creator>
            <pubDate>Wed, 13 Nov 2019 10:54:09 GMT</pubDate>
            <atom:updated>2019-11-13T10:55:58.154Z</atom:updated>
            <content:encoded><![CDATA[<h3>Build your first chart with Angular and Chart.js</h3><p>Chart.js is an open-source JavaScript library which makes it very easy to build charts for your website. On this tutorial, I’d like to provide step by step guide how to combine chart.js with another angular package - ‘ng2-charts’.</p><p><strong>Firstly, we need to understand about some properties of chart.js:</strong></p><ul><li><strong>data: </strong>Set of points of the chart, it should be MultiDataSet only for line, bar, radar and doughnut, otherwise SingleDataSet</li><li><strong>datasets: </strong>Data see about, the label for the dataset which appears in the legend and tooltips</li><li><strong>labels: x-axis labels</strong>. It’s necessary for charts: line, bar, and radar. And just labels (on hover) for charts: <strong>polarArea</strong>, pie, and a doughnut. Label is either a single string, or it may be a string[] representing a multi-line label where each array element is on a new line.</li><li><strong>type: I</strong>ndicates the type of charts, it can be: line, bar, radar, pie…</li><li><strong>options: C</strong>hart options. See <a href="http://www.chartjs.org/docs/"><strong>Chart.js documentation</strong></a> for more details.</li><li>c<strong>olors: Data colors</strong>, will use the default and|or random colors if not specified</li><li><strong>legend:</strong> If true show legend below the chart, otherwise not be shown</li></ul><p><strong>Let’s start to create a sample chart</strong></p><ol><li>We need to create an angular application with Angular CLI:</li></ol><blockquote>$ ng new myChart — routing</blockquote><ul><li>This command is downloading the default Angular project template and all dependencies are being installed.</li></ul><p>2. Install ng2-charts and chart.js dependency. Go to your root project and run commands</p><blockquote>npm install ng2-charts — save</blockquote><blockquote>npm install chart.js — save</blockquote><p>Now, you need to import <strong>ChartsModule</strong> into your app module or feature module. In this example, I will import to AppModule</p><pre>import { BrowserModule } from &quot;@angular/platform-browser&quot;;</pre><pre>import { NgModule } from &quot;@angular/core&quot;;</pre><pre>import { ChartsModule } from &quot;ng2-charts&quot;;</pre><pre>import { AppComponent } from &quot;./app.component&quot;;</pre><pre>@NgModule({</pre><pre>  declarations: [AppComponent],</pre><pre>  imports: [BrowserModule, ChartsModule],</pre><pre>  providers: [],</pre><pre>  bootstrap: [AppComponent]</pre><pre>})</pre><pre>export class AppModule {}</pre><p><strong>ng2-charts</strong> <strong>chart types</strong></p><p>There is one directive for all chart types: baseChart, and 8 types of charts: <a href="https://valor-software.com/ng2-charts/#/LineChart">line</a>, <a href="https://valor-software.com/ng2-charts/#/BarChart">bar</a>, <a href="https://valor-software.com/ng2-charts/#/RadarChart">radar</a>, <a href="https://valor-software.com/ng2-charts/#/PieChart">pie</a>, <a href="https://valor-software.com/ng2-charts/#/PolarAreaChart">polarArea</a>, <a href="https://valor-software.com/ng2-charts/#/DoughnutChart">doughnut</a>, <a href="https://valor-software.com/ng2-charts/#/BubbleChart">bubble</a> and <a href="https://valor-software.com/ng2-charts/#/ScatterChart">scatter</a>.</p><p>Let’s build a sample bar chart using below and update your <em>app.component.html</em></p><pre>&lt;div class=&quot;chart-container&quot; style=&quot;display: block&quot;&gt;</pre><pre>&lt;canvas <strong><em>baseChart</em></strong></pre><pre>   [datasets]=&quot;barChartData&quot;</pre><pre>   [labels]=&quot;barChartLabels&quot;</pre><pre>   [options]=&quot;barChartOptions&quot;</pre><pre>   [legend]=&quot;barChartLegend&quot;</pre><pre>   [chartType]=&quot;barChartType&quot;&gt;</pre><pre>&lt;/canvas&gt;</pre><pre>&lt;/div&gt;</pre><p>And the last step, we need to init chart data for the chart. Update your <em>app.component.ts </em>as below</p><pre>import { Component } from &#39;@angular/core&#39;;</pre><pre>@Component({</pre><pre>  selector: &#39;app-root&#39;,</pre><pre>  templateUrl: &#39;./app.component.html&#39;,</pre><pre>  styleUrls: [&#39;./app.component.scss&#39;]</pre><pre>})</pre><pre>export class AppComponent {</pre><pre>  constructor() {}</pre><pre>  public barChartOptions = {</pre><pre>    scaleShowVerticalLines: false,</pre><pre>    responsive: true</pre><pre>};</pre><pre>  public barChartLabels =[&#39;2006&#39;,&#39;2007&#39;,&#39;2008&#39;,&#39;2009&#39;,&#39;2010&#39;,&#39;2011&#39;,&#39;2012&#39;];</pre><pre>  public barChartType = &#39;bar&#39;;</pre><pre>  public barChartLegend = true;</pre><pre>  public barChartData = [</pre><pre>   { data: [65, 59, 80, 81, 56, 55, 40], label: &#39;Series A&#39; },</pre><pre>   { data: [28, 48, 40, 19, 86, 27, 90], label: &#39;Series B&#39; }</pre><pre>  ];</pre><pre>}</pre><p>Start your application and view your result in <a href="http://localhost:4200">http://localhost:4200</a></p><blockquote>$ ng serve</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qn2-UlscjgeCzYMg73Agqw.png" /></figure><p>Noted: Detecting when the canvas size changes can not be done directly from the canvas element. <strong>Chart.js</strong> uses its parent container to update the canvas <em>render</em> and <em>display</em> sizes.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3517c8aaf5bd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/build-your-first-chart-using-angular-ng2-charts-3517c8aaf5bd">Build your first Chart using Angular &amp; Ng2-charts</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a CRUD application with Angular using Ngrx (Part 1)]]></title>
            <link>https://medium.com/innomizetech/building-a-crud-application-with-angular-using-ngrx-part-1-725af50f1548?source=rss----2b737588f380---4</link>
            <guid isPermaLink="false">https://medium.com/p/725af50f1548</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[angular]]></category>
            <dc:creator><![CDATA[Andy Nguyen]]></dc:creator>
            <pubDate>Wed, 13 Nov 2019 02:29:52 GMT</pubDate>
            <atom:updated>2019-11-19T02:23:38.203Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/953/1*CtXgX7LzUH0EpxN84rntKw.png" /></figure><p>In this guide, we just focus on how to build a CRUD application with Angular (version 8) that has already installed the <a href="https://ngrx.io/">Ngrx</a>, not on setting up an Angular application or installing the Ngrx library. You can follow the following guides to do those task:</p><ul><li>Set up an Angular application: <a href="https://codeburst.io/how-to-build-an-angular-app-with-angular-cli-in-a-couple-of-minutes-43089d3ab272">https://codeburst.io/how-to-build-an-angular-app-with-angular-cli-in-a-couple-of-minutes-43089d3ab272</a></li><li>Install the Ngrx library: <a href="https://ngrx.io/guide/store/install">https://ngrx.io/guide/store/install</a></li></ul><p>If you have no idea what is Ngrx, I recommend you to read <a href="https://ngrx.io/docs">this</a> to explore more about it. And if you have a basic knowledge of <a href="https://redux.js.org/">Redux</a>, I think you will be easy to approach this library.</p><p>In this part, we will learn how to define actions, reducer, selectors and build a page to display all items that are selected from the store using the <a href="https://ngrx.io/">Ngrx</a>.</p><p>In almost any application that we work with, we all encounter operations such as retrieving data, rendering it as a table view, create/update or delete a row on that view. And this data which is stored on the server is dealt with by the usage of HTTP requests (GET, POST, etc).</p><p>The first thing we need to do in here is where the data is stored that we will get through an HTTP API request. Because this article does not focus on this, I will use a fake backend server for mock. There are different ways to use a fake back-end server are:</p><ul><li>Use Angular In-Memory-Web-API</li><li>Create a local JSON file and use it</li><li>Or hard-code the data, and return this data.</li></ul><p>But I have another easy way, say big thanks to <a href="https://getsandbox.com/">https://getsandbox.com</a>. Just provide some rows of code, we already have a RESTful API for mock or testing. I have created a mock RESTful API on <a href="https://getsandbox.com/">https://getsandbox.com</a> for CRUD on the Entity object as below:</p><pre><strong>Fake RESTful APIs: (CRUD)</strong><br><strong>GET</strong>:    https://entity.getsandbox.com/entities/     (<strong>Get all</strong>)<br><strong>GET</strong>:    https://entity.getsandbox.com/entities/{id} (<strong>Get one</strong>)<br><strong>POST</strong>:   https://entity.getsandbox.com/entities/     (<strong>Create</strong>)<br><strong>PUT</strong>:    https://entity.getsandbox.com/entities/{id} (<strong>Update</strong>)<br><strong>DELETE</strong>: https://entity.getsandbox.com/entities/{id} (<strong>Delete</strong>)</pre><p>Ok, we have done on prerequisite items. Next, we’ll go together to define actions, reducer, and selectors to fetch Entity objects from the fake server I have created before and store it into the Ngrx store. If you have developed with a React Redux application before, all fundamental principles about Redux (action, reducer, selector, etc) will be similar to the Ngrx.</p><p>First, we will define a class that describes all properties of the Entity object we will deal with:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/46878d956ba8b1e3a8ca4fd7d84fb2ad/href">https://medium.com/media/46878d956ba8b1e3a8ca4fd7d84fb2ad/href</a></iframe><p>Let’s define some actions for loading entities as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f49fae10a32e8c4f31bdc53d1f993ea9/href">https://medium.com/media/f49fae10a32e8c4f31bdc53d1f993ea9/href</a></iframe><p>Next, we’ll define the Entity’s reducer. Here, we have to define an initial state and specify how the state is changed for each action is sent to the store.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4cfbc9eb419159b803781db3b805ac05/href">https://medium.com/media/4cfbc9eb419159b803781db3b805ac05/href</a></iframe><p>Continue define selectors:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c42cc7e793effb2de57c5c68dcbb7bf9/href">https://medium.com/media/c42cc7e793effb2de57c5c68dcbb7bf9/href</a></iframe><p>Create a service file to fetch data from the server:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8729b3dce32073ffe7985bf27db9ccae/href">https://medium.com/media/8729b3dce32073ffe7985bf27db9ccae/href</a></iframe><p>To read data from the server, we need to create a side effect to make an HTTP request to the server and store data into the store through Ngrx actions. With React, <a href="https://redux-saga.js.org/">Saga</a> can handle side effects for us. And the Ngrx also has provided the <strong>Effect </strong>concept that is the same as the Saga. As the Ngrx documentation: “Effects are an RxJS powered side effect model for <a href="https://ngrx.io/guide/store">Store</a>. Effects use streams to provide <a href="https://martinfowler.com/eaaDev/EventSourcing.html">new sources</a> of actions to reduce state based on external interactions such as <strong>network requests</strong>, web socket messages and time-based events.” So that we will use it for reading Entity data from the server.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7804b1de8a16095ec05f44f8dc48cce2/href">https://medium.com/media/7804b1de8a16095ec05f44f8dc48cce2/href</a></iframe><p>Finally, creating an Angular page (with route is “/entities”) to display a list of the entity that are fetched from the server. For easy to navigate to entities page, we create a link for quick navigation in app.component.html:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/63fa20b8aa19dfed3167ec9f30fe227c/href">https://medium.com/media/63fa20b8aa19dfed3167ec9f30fe227c/href</a></iframe><p>In entities.page.ts, the store will dispatch loadEntities action and the effect will be triggered to fetch data from server and store data into the store. Since the data is loaded to the store, we only get data from the store and display it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d77d82c1c9d1884e35a35001cafda1df/href">https://medium.com/media/d77d82c1c9d1884e35a35001cafda1df/href</a></iframe><p>The entity template HTML file:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5fe3515b4c682737df88cc8568546571/href">https://medium.com/media/5fe3515b4c682737df88cc8568546571/href</a></iframe><p>Note: Ensure that you have already imported CommonModule to use the async pipe.</p><p>Gives the result as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/798/1*RDuR2K-MBGNfDwI3dzKgxg.png" /><figcaption>Reading Entity data from the server</figcaption></figure><p>The operation for reading Entity data from the server has completed. But you will see the entities page display empty page before render list of Entity objects. This is cause of waiting from the server for reading data and it should be better for the user’s experience if a spinner display instead of. That is a good suggestion since I know Angular <a href="https://angular.io/api/router/Resolve">Resolve</a>. Resolve will wait for the data to be resolved before the page is finally navigated.</p><p>So I will define the resolver for entities page as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bdaf25a1517482f5d95c2b5edd400602/href">https://medium.com/media/bdaf25a1517482f5d95c2b5edd400602/href</a></iframe><p>As above code, the entities page only is activated if the loaded flag is true. Also, I have added a filter operator to dispatch loadEntities action if the loaded flag is false. So the application only makes an HTTP request only the loaded flag is false, this reduces significantly backend traffic during the application navigation.</p><p>Update the entities.page.ts to comment or remove the following code:</p><pre><em>// this.store.dispatch(fromEntityActions.loadEntities());</em></pre><p>Continue to add the resolve to the route configuration:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cf11f76d8eae92a5f90f6ea5513ed4b1/href">https://medium.com/media/cf11f76d8eae92a5f90f6ea5513ed4b1/href</a></iframe><p>Enjoy the result:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodesandbox.io%2Fembed%2Fcrud-angular-ngrx-part-1-0k2ke%3Ffontsize%3D14&amp;url=https%3A%2F%2Fcodesandbox.io%2Fs%2Fcrud-angular-ngrx-part-1-0k2ke%3Ffontsize%3D14&amp;image=https%3A%2F%2Fcodesandbox.io%2Fapi%2Fv1%2Fsandboxes%2F0k2ke%2Fscreenshot.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codesandbox" width="1000" height="500" frameborder="0" scrolling="no"><a href="https://medium.com/media/67169ff59788ce9f7db62a2046802546/href">https://medium.com/media/67169ff59788ce9f7db62a2046802546/href</a></iframe><h3>Summary</h3><p>Coming to the end of this guide, let us have a quick recap of what we did.</p><ul><li>Use <a href="https://getsandbox.com/">https://getsandbox.com/</a> to quick create a fake server for mocking and testing.</li><li>Use <strong>createAction</strong>, <strong>createReducer, </strong>and <strong>createFeatureSelector </strong>for creating actions, reducer, selectors.</li><li>Use <strong>Ngrx Effect</strong> for handle side effects to make an HTTP call for retrieving data from the server.</li><li>Use <strong>Angular Resolver</strong> to ensure that data has already loaded before the page is navigated.</li></ul><p>I hope this tutorial will be helpful to you :D</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=725af50f1548" width="1" height="1" alt=""><hr><p><a href="https://medium.com/innomizetech/building-a-crud-application-with-angular-using-ngrx-part-1-725af50f1548">Building a CRUD application with Angular using Ngrx (Part 1)</a> was originally published in <a href="https://medium.com/innomizetech">INNOMIZE</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>