<?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: Nir Hadassi</title>
    <description>The latest articles on DEV Community by Nir Hadassi (@nirsky).</description>
    <link>https://dev.to/nirsky</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%2F590444%2F53e73feb-0c4a-4849-92f9-277d9be8001a.jpeg</url>
      <title>DEV Community: Nir Hadassi</title>
      <link>https://dev.to/nirsky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nirsky"/>
    <language>en</language>
    <item>
      <title>Make your npm package work on both Node.js and browser</title>
      <dc:creator>Nir Hadassi</dc:creator>
      <pubDate>Wed, 21 Apr 2021 13:34:44 +0000</pubDate>
      <link>https://dev.to/aspecto/make-your-npm-package-work-on-both-node-js-and-browser-30n7</link>
      <guid>https://dev.to/aspecto/make-your-npm-package-work-on-both-node-js-and-browser-30n7</guid>
      <description>&lt;p&gt;I recently worked on an npm package that is supposed to be consumed on both Node.js environment and the browser (using React/Angular/etc..).&lt;/p&gt;

&lt;p&gt;Things started getting complicated when the node branch of the code needed to require native Node.js packages — like &lt;code&gt;fs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Consider the following (simplified) code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// node-handler.js
const fs = require('fs');

export const handle = () =&amp;gt; { 
  fs.readFileSync(…);
  …
};

// browser-handler.js
export const handle = () =&amp;gt; { … };

// index.js
const nodeHandler = require('./node-handler').handle;
const browserHandle = require('./browser-handler').handle;
const isNode = require('./config').isNode;

const handle = isNode ? nodeHandler : browserHandle;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When testing the module on my React + Webpack app, the app crashed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwq7fou7mjg5rbejt1sqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwq7fou7mjg5rbejt1sqm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This happened even though the &lt;code&gt;node-handler&lt;/code&gt; file wasn’t executed, this is due to Webpack nature of creating a bundle containing all the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Postpone your requires
&lt;/h2&gt;

&lt;p&gt;Instead of requiring &lt;code&gt;fs&lt;/code&gt; in the global scope, we can require it only where we actually need it, that way we don’t require it when running in the browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// node-handler.js
export const handle = () =&amp;gt; { 
  require('fs').readFileSync(…);
  …
};

// browser-handler.js
export const handle = () =&amp;gt; { … };

// index.js
const nodeHandler = require('./node-handler').handle;
const browserHandle = require('./browser-handler').handle;
const isNode = require('./config').isNode;

const handle = isNode ? nodeHandler : browserHandle;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool! Our React app is not crashing anymore! But we do get an annoying compilation warning right now:&lt;br&gt;
&lt;a href="https://media.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%2F9ptgfju0o8i9ut8o8dhp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9ptgfju0o8i9ut8o8dhp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While we can live with a warning ⚠️ , our end-users will probably not like this too much and will end up not installing our package.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: eval your require
&lt;/h2&gt;

&lt;p&gt;This is not the most elegant solution (to say the least..), but it’s keeping Webpack quiet and your end-users happy. Instead of using &lt;code&gt;require('fs')&lt;/code&gt;, we’re gonna use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval" rel="noopener noreferrer"&gt;eval&lt;/a&gt;&lt;code&gt;('require')('fs')&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// node-handler.js
export const handle = () =&amp;gt; { 
  eval('require')('fs').readFileSync(…);
  …
};

// browser-handler.js
export const handle = () =&amp;gt; { … };

// index.js
const nodeHandler = require('./node-handler').handle;
const browserHandle = require('./browser-handler').handle;
const isNode = require('./config').isNode;

const handle = isNode ? nodeHandler : browserHandle;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! Just two simple steps to make your npm package work on both Node.js and browser.&lt;/p&gt;

&lt;p&gt;Good luck and may you be blessed with tons of stars 🌟&lt;/p&gt;

</description>
      <category>npm</category>
      <category>node</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Easily deploy TypeScript project to AWS Lambda using Github Actions</title>
      <dc:creator>Nir Hadassi</dc:creator>
      <pubDate>Wed, 07 Apr 2021 13:43:15 +0000</pubDate>
      <link>https://dev.to/aspecto/easily-deploy-typescript-project-to-aws-lambda-using-github-actions-10g1</link>
      <guid>https://dev.to/aspecto/easily-deploy-typescript-project-to-aws-lambda-using-github-actions-10g1</guid>
      <description>&lt;p&gt;I recently worked on a small TypeScript project which I wanted to deploy as a Lambda to AWS.&lt;/p&gt;

&lt;p&gt;My project had &lt;strong&gt;multiple files&lt;/strong&gt; and some &lt;strong&gt;npm dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I found some resources online, but none of them really hit the spot.&lt;/p&gt;

&lt;p&gt;Some didn’t explain how to include the &lt;code&gt;node_modules&lt;/code&gt;, some didn’t explain how to do it with TypeScript and some just handled a single file.&lt;/p&gt;

&lt;p&gt;In this post, I’ll describe how to prepare the project for deployment and show a detailed example of doing it using Github Actions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Project Structure
&lt;/h1&gt;

&lt;p&gt;Let’s assume our project structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ├── package.json
 ├── tsconfig.json
 ├── node_modules
 │    ├── module_1
 │    ├── module_2
 │    └── etc..
 └── src
      ├── index.ts
      └── utils.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "module": "commonjs",
    "target": "ES2017",
    "lib": ["ES2019"],
    "rootDir": "src",
    "outDir": "dist",
    "declaration": false, 
    "sourceMap": false,
    "inlineSources": false,
    "types": ["node"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;index.ts&lt;/code&gt; contains as the main &lt;code&gt;handler&lt;/code&gt;, and uses &lt;code&gt;utils.ts&lt;/code&gt;, something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { APIGatewayEvent, Context } from 'aws-lambda';
import { doSomething } from './utils';

export const handler = async (event: APIGatewayEvent, context: Context) =&amp;gt; { 
    doSomething();
    // Do some other stuff…
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Problem
&lt;/h1&gt;

&lt;p&gt;AWS Lamda can only run &lt;strong&gt;js&lt;/strong&gt; files!&lt;/p&gt;

&lt;p&gt;Also, AWS Lambda can’t install &lt;code&gt;node_modules&lt;/code&gt; for us.&lt;/p&gt;

&lt;p&gt;With the default settings, AWS Lambda supports either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying a single &lt;code&gt;index.js&lt;/code&gt; file directly.&lt;/li&gt;
&lt;li&gt;Upload a &lt;strong&gt;zip&lt;/strong&gt; file containing all the project files, which has the &lt;code&gt;index.js&lt;/code&gt; in the zip root. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we need to zip the project correctly, without including the parent directory.&lt;/p&gt;

&lt;p&gt;We also need to make sure the &lt;code&gt;node_modules&lt;/code&gt; are part of this zip file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fndo6g3lq3dersqz30j2n.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fndo6g3lq3dersqz30j2n.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Prepare for deployment
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Build the project
&lt;/h2&gt;

&lt;p&gt;We will use TypeScript’s &lt;code&gt;tsc&lt;/code&gt; command to transpile the project into js files.&lt;/p&gt;

&lt;p&gt;After building, this will be our project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── package.json
├── tsconfig.json
├── node_modules
├── dist
│    ├── index.js
│    └── utils.js
└── src
     ├── index.ts
     └── utils.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Move node_modules to dist folder
&lt;/h2&gt;

&lt;p&gt;As mentioned before, AWS Lambda can’t install the node_modules for us, so we need to assure they are located correctly before creating our zip file.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. ZIP
&lt;/h1&gt;

&lt;p&gt;The project needs to be zipped in the required structure, &lt;strong&gt;without the parent directory&lt;/strong&gt;. The easiest way I found to do it, is to run the following command from the project root:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ (cd dist &amp;amp;&amp;amp; zip -r ../function.zip .)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The zip is now ready for deployment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deploy using Github Actions
&lt;/h1&gt;

&lt;p&gt;The deployment part will be done using &lt;a href="https://github.com/marketplace/actions/aws-lambda-deploy" rel="noopener noreferrer"&gt;appleboy/lambda-action&lt;/a&gt;, and can be easily substituted with a corresponding AWS CLI command, which comes preinstalled on Github Actions CI machines.&lt;/p&gt;

&lt;p&gt;Here’s a detailed example of a Github action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy

on:
  push:
    branches: [ master ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v2

      - name: Install Dependencies
        run: yarn

        # build command should be set in your package.json scripts as: "build": "tsc"
      - name: Build
        run: yarn build

      - name: Move node_modules to dist
        run: mv node_modules dist/node_modules

      - name: Zip
        run: (cd dist &amp;amp;&amp;amp; zip -r ../function.zip .)

      - name: Deploy to AWS
        uses: appleboy/lambda-action@master
        with:
          aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws_region: ${{ secrets.AWS_REGION }}
          function_name: my-cool-function
          zip_file: function.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! Your Lambda is now ready for work.&lt;/p&gt;

&lt;p&gt;We post tutorials like this weekly on Aspecto &lt;a href="https://www.aspecto.io/blog/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=deploy-typescript-to-aws-lambda"&gt;blog&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Check out one of our latest tutorials - &lt;strong&gt;&lt;a href="https://www.aspecto.io/blog/how-to-send-large-sqs-sns-messages-with-node-js/?utm_source=dev.to&amp;amp;utm_medium=referral&amp;amp;utm_campaign=deploy-typescript-to-aws-lambda"&gt;How to Send Large SQS/SNS Messages with Node.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>tutorial</category>
      <category>aws</category>
      <category>github</category>
    </item>
  </channel>
</rss>
