<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eero Kukko</title>
    <description>The latest articles on DEV Community by Eero Kukko (@pikkue).</description>
    <link>https://dev.to/pikkue</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F984817%2F5991ee71-db75-4f55-919b-062a93a3dead.jpeg</url>
      <title>DEV Community: Eero Kukko</title>
      <link>https://dev.to/pikkue</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pikkue"/>
    <language>en</language>
    <item>
      <title>Create Google (Login) Credentials for Your Web Application</title>
      <dc:creator>Eero Kukko</dc:creator>
      <pubDate>Sun, 27 Oct 2024 17:29:11 +0000</pubDate>
      <link>https://dev.to/pikkue/create-google-login-credentials-for-your-web-application-3dc2</link>
      <guid>https://dev.to/pikkue/create-google-login-credentials-for-your-web-application-3dc2</guid>
      <description>&lt;p&gt;If you want to use Google (federated login) to authenticate users, you need to create a Google project with OAuth authentication screen. Here are the required steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create Google Project or use your existing project&lt;/li&gt;
&lt;li&gt;Create OAuth consent screen&lt;/li&gt;
&lt;li&gt;Create the credentials&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Create Google Project
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://console.cloud.google.com" rel="noopener noreferrer"&gt;Google cloud console&lt;/a&gt; and create a project. This is done by clicking the button circled red in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6edkeqtxmh5cdc06jn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6edkeqtxmh5cdc06jn5.png" alt="Creating the cloud project" width="800" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose "New project" from the top left button. This opens the window to fill the project details. Assign a name to the project. Choose your organization and location. These are based on your Google Cloud account, but unless you have a big project the default settings should be fine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0mucipwtdmtuacs0pg0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0mucipwtdmtuacs0pg0.png" alt="New Project Details" width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create OAuth Consent Screen
&lt;/h2&gt;

&lt;p&gt;In the Google Console, select your project, if not already selected, and then click on "APIs and Services". From this screen choose the OAuth consent screen from the left menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcicpn0kl64igum1lfzfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcicpn0kl64igum1lfzfd.png" alt="Create the OAuth consent screen" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For demo purposes I'm going to choose internal, but you can change this later. In the internal mode, your users are limited to Google Workspace users within your organisation. This is perfect if you're creating apps for internal use in your company.&lt;/p&gt;

&lt;p&gt;Next add the mandatory details such as application name, User support email, and developer contact information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5v0g7yrpss4w7ygksc9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5v0g7yrpss4w7ygksc9o.png" alt="OAuth consent screen configuration" width="800" height="786"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next you will need to choose the API scopes your application requires. Scopes are permissions to access the user information and services. Some of the scopes are more sensitive like access to user's Gmail. For authentication, I'm choosing the email and profile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21ty5z9m0l40cgzir0k4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21ty5z9m0l40cgzir0k4.png" alt="Choosing the OAuth scopes" width="800" height="834"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continue to review the OAuth consent screen creation and  complete this step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Credentials
&lt;/h2&gt;

&lt;p&gt;The last step is to create the credentials for your application or web service. You can add multiple credentials to use with different services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xmriemlwizwsyhbrk6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xmriemlwizwsyhbrk6i.png" alt="Create Credentials" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example Google Login is used with a web service and thus a Web application is chosen from the list. Add a name to the service and then the URLs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorized origin is the URL where the browser is entering the Google Login. For testing, it's easiest to use localhost. If you are using a real domain name, you must have https (SSL/TLS) set-up.&lt;/li&gt;
&lt;li&gt;Authorized redirect is the address the user is re-directed after the authentication. This is typically your server and path that you use to login the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrcz9fzyzcpfelkmlw7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrcz9fzyzcpfelkmlw7r.png" alt="OAuth configuration" width="800" height="1014"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you save the configuration, you should see the Client ID and Client Secret.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1enim6gs6prnfj1mgh37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1enim6gs6prnfj1mgh37.png" alt="Client ID and Secret" width="800" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, you have successfully created the Google Credentials for your application.   &lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the Credentials
&lt;/h2&gt;

&lt;p&gt;The fastest way to test your credentials is to open Google's OAuth login site with the URL below. Copy the URL to your browser and add your Client id to the end of the URL to test your login. If you're interested in the Google OAuth URLs, you can find Google's well-known OpenID configuration from &lt;a href="https://accounts.google.com/.well-known/openid-configuration" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/userinfo.profile&amp;amp;access_type=offline&amp;amp;include_granted_scopes=true&amp;amp;response_type=code&amp;amp;state=optional_parameter_to_track_state_12345&amp;amp;redirect_uri=http://localhost:3000/google&amp;amp;client_id=add_your_id_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you configuration was successful, you should see the Google login screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyofy5lw312s8l1apqzy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyofy5lw312s8l1apqzy1.png" alt="Google Sign-in Screen" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have completed the authentication, you should be re-directed to the Re-direct URL. &lt;/p&gt;

&lt;p&gt;Instead of writing all the logic for user authentication and token verification  yourself, there are many libraries available for this, such as Passport for Node.js. Here is link to their &lt;a href="https://www.passportjs.org/tutorials/google/" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Optimising Node.js and React with Compression</title>
      <dc:creator>Eero Kukko</dc:creator>
      <pubDate>Wed, 07 Dec 2022 08:44:33 +0000</pubDate>
      <link>https://dev.to/pikkue/optimising-nodejs-and-react-with-compression-12em</link>
      <guid>https://dev.to/pikkue/optimising-nodejs-and-react-with-compression-12em</guid>
      <description>&lt;p&gt;If you have a large web page/app, you're already familiar with this issue. Below you'll find few ways to compress data and decrease the page load time with Node.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I have a single page React web application with a large amount of files, imports, css, fonts etc. Before the page is served, all the assets are compiled &amp;amp; bundled with Webpack. In this case, most of the assets (css, html and js) are bundled into a single html file to decrease the amount of network requests.&lt;/p&gt;

&lt;p&gt;If you are sending a large amount of files over HTTP/HTTPS/HTTP/2, there is some overhead from the all the requests that the client needs to make and process. Every request has headers, checksums, authentication and authorisation fields that someone needs to transfer and process. &lt;/p&gt;

&lt;p&gt;In the examples below, the backend is based on Node.js/Fastify, but the same tricks work with Express and on other Node frameworks.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Loading Time...
&lt;/h2&gt;

&lt;p&gt;In the development environment the connection is fast. I didn't even notice that the file had grown to 14,9 MB. Despite the many database requests in the backend, the page load takes less than a second. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffr3o9lime4xvs810d5e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffr3o9lime4xvs810d5e4.png" alt="Image description" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This isn't the case when the network connection is downgraded to "Fast 3G" in Chrome developer tools. It took 1.4 min to load the page! This is not a very good user experience. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayygknp4zcgnwgyggy83.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fayygknp4zcgnwgyggy83.png" alt="Image description" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  On the Fly Compression
&lt;/h2&gt;

&lt;p&gt;With on the fly compression, the server takes the uncompressed data and compresses it before sending it to the browser. There are different tools that you can use to compress the data on the fly. Here are few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fastify/fastify-compress" rel="noopener noreferrer"&gt;fastify/compress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/expressjs/compression#readme" rel="noopener noreferrer"&gt;compression for Express&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With fastify/compress the process is quite simple. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the package npm i @fastify/compress &lt;/li&gt;
&lt;li&gt;Add the compression hook to your Fastify server&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This code will enable global compression on Fastify.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Fastify from 'fastify';

const fastify = Fastify();
fastify.register(import('@fastify/compress'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the default settings, the compressed page is now only 1,7 MB and with the slower network connection it took only 20 seconds to load the page. &lt;/p&gt;

&lt;p&gt;Unfortunately it took over 14 seconds to load the page with the fast connection. The server was too slow to compress the data and made the connection 14 x slower. If you have a powerful server, this might not be an issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6r6eqni5gebl0rloxgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6r6eqni5gebl0rloxgb.png" alt="Image description" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Static Compression
&lt;/h2&gt;

&lt;p&gt;When on the fly compression is too slow, you can configure e.g. Webpack to create an html bundle and  a compressed version of the bundle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new CompressionPlugin({
  algorithm: 'gzip',
  filename: '[path][base].gz',
  test: /\.(html)$/
}),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this Webpack plugin, the server now has two files it can serve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/dist/page.html&lt;/li&gt;
&lt;li&gt;/dist/page.html.gz&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;More information about the Webpack configuration: &lt;a href="https://dev.tourl"&gt;https://webpack.js.org/plugins/compression-webpack-plugin/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're not using a module bundler, you can just manually compress the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// To keep the original file use the -k option
gzip -k filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because some clients might not support compression, the server needs to check which compression algorithms are supported, before sending the compressed data. This is done by checking the client's &lt;strong&gt;"Accept-Encoding"&lt;/strong&gt; HTTP header. Here is an example header from a client that supports gzip, deflate and br (Brotli).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfhm50k09risv761dafi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftfhm50k09risv761dafi.png" alt="Image description" width="660" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The server needs to set &lt;strong&gt;'Content-Encoding'&lt;/strong&gt; HTTP header to the right compression format e.g. gzip or br, otherwise the browser doesn't know it's being served a compressed stream.&lt;/p&gt;

&lt;p&gt;Here's a Node/Fastify example of serving a compressed file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastify.get('/page',
  async (req, res) =&amp;gt; {

    let encoding = req.headers['accept-encoding']
          ? req.headers['accept-encoding'].split(',')
          : [];
    let gzipReply = encoding.find(e =&amp;gt; e == 'gzip') ? true : false;

    if (gzipReply) {
      return res.header('Content-Encoding', 'gzip')
              .send(createReadStream('./dist/page.html.gz'));
    }

    return res.send(createReadStream('./dist/page.html'));
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the fast connection, the load time was typically reduced by 100 - 200 ms. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With the slower "Fast 3G" connection, the load time was reduced from 1.4 min to 11 sec.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;There is one caveat here for development. Brotli file compression increased the Webpack bundling time from 7 seconds to 23 seconds. Fortunately gzip doesn't have the same issue. Because of this, it might be a good idea to enable Brotli for the production build, but not necessarily for the development builds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Webpack Production Mode
&lt;/h2&gt;

&lt;p&gt;By setting Webpack mode to production, the build size can be further reduced. In the case above, the html file size decreased to 7,6 MB and the compressed gzip file to 1,6 MB in production mode.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  mode: 'development',
};

module.exports = {
  mode: 'production',
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;There are multiple ways to decrease the file size with Node. I hope this article helped you to make your next project faster.&lt;/p&gt;

</description>
      <category>node</category>
      <category>react</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
