Latest Tutorials

Learn about the latest technologies from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

Benchmarking a Go and chi RESTful API

The amount of time and effort a developer dedicates towards writing a function depends on the details they choose to focus on: coding conventions, structure, programming style, etc. Suppose a group of developers is presented a high-level prompt to write the same function: given some input, return some output. For example, given a list of numbers, return a sorted list of numbers. The actual implementation of the function is left entirely to the discretion of the developer. A quick, mathematical way to evaluate each developer's implementation of this function, without any additional code, is by its time complexity . Particularly, knowing each implementation's Big-O complexity tells us how it might perform in the worst case scenario, commonly when the size of the input is very large. However, time complexity fails to account for the hardware the function is executed upon, and it does not provide any tangible, quantifiable metrics to base decisions on. Metrics such as operation speed and total execution time assign real numerical values to the performance of a function. By adding benchmarks , developers can leverage these metrics to better inform them on how to improve their code. The Go programming language has a benchmarking utility in its built-in, standard library package testing . To benchmark code in Go, define a function with a name prefixed with Benchmark (followed by a capitalized segment of text) and accepts an argument of struct type B , which contains methods and values for determining the number of iterations to run, running multiple benchmarks in parallel, timing execution times, etc. Example : Note : The structure of a benchmark is similar to the structure of a test. Replace Test with Benchmark and t *testing.T with b *testing.B . This benchmark runs the Sum function for b.N iterations. Here, the benchmark runs for one billion iterations, which allows the benchmark function to reliably time and record each execution. Once the benchmark is completed, the results of this benchmark and the CPU of the machine running this benchmark are outputted to the terminal. On average, each iteration ran 0.6199 ns. Below, I'm going to show you... Clone a copy of the Go and chi RESTful API from GitHub to you machine: This RESTful API specifies five endpoints for performing operations on posts: If you would like to learn how to build this RESTful API, then please visit this blog post . In the basic-tests branch, a simple unit test is already provided in the routes/posts_test.go file. Because benchmarks must be placed in _tests.go files, let's place the benchmarks for the posts sub-router in the routes/posts_test.go file. Run the following command to install the project's dependencies: Note : If you run into installation issues, then verify that the version of Go running on your machine is v1.16 . Run the following command to execute the unit tests within the routes/posts_test.go file: To get started, open the routes/posts_test.go file. Let's name the benchmark function BenchmarkGetPostsHandler : Combine the code snippets together: ( routes/posts_test.go ) Run the benchmark: Here, benchmarks run sequentially. The benchmark ran a total of 97220 iterations with each iteration running, on average, 11439 ns. This represents the average time it took for each handler.ServeHTTP function (and by extension, PostsResource{}.List ) call to complete. Each iteration involved the allocation of, on average, 33299 bytes of memory. Memory was allocated, on average, 8 times per iteration. The for loop forces the benchmark to execute the function handler.ServeHTTP sequentially, one after the other. By running the benchmark with b.RunParallel , the total iterations b.N is divided amongst the machine's available threads (distributed amongst multiple goroutines). Having these iterations run concurrently helps to benchmark code that's inherently concurrent, such as sending requests and receiving responses, and deals with mutexes and/or shared resources. To parallelize benchmarks, wrap the benchmark code in b.RunParallel and replace the for loop with for pb.Next() : ( routes/posts_test.go ) Run the benchmark again. Notice that the benchmark values are similar to when we ran the benchmark sequentially with a for loop. To increase the number of cores (and goroutines) to run this benchmark against, add the cpu flag: Increasing the number of cores increases the number of goroutines running the benchmark iterations, which results in better performance. Click here for a final version of the route handler unit test. Try writing benchmarks for the other route handlers.

Thumbnail Image of Tutorial Benchmarking a Go and chi RESTful API

How to Fix the Error Error:error:0308010C:digital envelope routines::unsupported

If you are running Webpack or a CLI tool that’s built on top of Webpack (e.g., react-scripts for Create React App applications or vue-cli-service for Vue applications) with version 17 of Node.js, then you may have come across the following error: With Node.js v17+ supporting OpenSSL 3.0 , algorithms like MD4 have been relegated to OpenSSL 3.0’s legacy provider. A provider is a collection of cryptographic algorithm implementations. OpenSSL 3.0 comes with five standard providers : default, legacy, FIPS, base and null. The legacy provider consists of algorithms that are considered to be rarely used in today’s world or unsafe security-wise. This provider exists for backwards compatibility purposes (for software that still rely on these algorithms) and is not loaded by default. Webpack creates hashes using the crypto.createHash() method of the Node.js crypto module. This method can only create hashes with algorithms that are available and supported by the version of OpenSSL corresponding to the currently installed Node.js version. Since Webpack specifies to the crypto.createHash() method to use the MD4 algorithm (see below code), and this algorithm is not readily available in Node.js v17+ due to OpenSSL 3.0 not loading legacy providers by default, Webpack errors out and Node.js logs the error message Error: error:0308010C:digital envelope routines::unsupported . ( https://github.com/webpack/webpack/blob/main/lib/util/createHash.js ) To fix this error, you can do one of five things: If you are running Node.js via nvm , then you can install Node.js v16. Once the installation finishes, nvm automatically switches the current version of Node.js to the newly installed version of Node.js. Note : Specifying 16 installs the latest LTS version with a major version of 16, which happens to be, as of the publication of this article, 16.16.0. Note : The Node.js version can be any version less than 17, but it's highly recommended to stick with Node.js versions that are under active or maintenance LTS status . Run node -v && npm -v to verify the versions of Node.js and npm running on your machine. Then, delete the node_modules folder and re-install the project's dependencies. Similarly, if you are running Node.js via Volta , then you can also install Node.js v16 the same way. Note : For convenience, you can save this exact version of Node.js and npm to the project via the volta pin node@16 command. Anytime you enter the project directory and run Node.js, Volta automatically switches the current version of Node.js to the pinned version of Node.js. Run node -v && npm -v to verify the versions of Node.js and npm running on your machine. Then, delete the node_modules folder and re-install the project's dependencies. Introduced in Node.js v17 alongside support for OpenSSL 3.0, the --openssl-legacy-provider flag tells Node.js to revert to OpenSSL 3.0's legacy provider. This allows you to run tools like Webpack that still create hashes with legacy cryptographic algorithms like MD4. Here are some examples of how to pass this flag: If you have multiple CLI tools that depend on legacy cryptographic algorithms, then you can set the NODE_OPTIONS environment variable to --openssl-legacy-provider instead of passing the --openssl-legacy-provider flag to each of these tools. For MacOSX and Unix, run the following command before running anything else: For Windows, run the following command before running anything else: Alternatively, you could set the environment variable directly within an npm script of a package.json file, like so: With npm-run-all , all of the executed npm scripts receive the NODE_OPTIONS environment variable. Note : For cross-platform compatibility, set the environment variable via a CLI tool like cross-env . For an older Create React App project that runs react-script v4.0.3 (the version before v5.0.0 ), there are three files across two dependencies that use the MD4 algorithm for creating hashes: Upon patching these files, the Create React App application runs successfully with Node.js v17+. However, this approach is highly discouraged. You would need to: For a Webpack project, you can apply the following patch to redirect requests for creating hashes with the MD4 algorithm to creating hashes with the MD5 algorithm instead, like so: ( https://github.com/webpack/webpack/blob/main/lib/util/createHash.js ) Note : Overriding the createHash() method of the crypto module via the above solution was originally suggested by Alexander Akait , a core contributor of Webpack. For Create React App projects, check the installed version of react-scripts . If the version is less than v5.0.0, then upgrade the version of react-scripts to v5.0.0 or higher. In v5.0.0 of Create React App, the version of the cached Webpack modules and chunks gets generated using a stringified object of environment variables and MD5 algorithm . ( https://github.com/facebook/create-react-app/blob/main/packages/react-scripts/config/webpack/persistentCache/createEnvironmentHash.js ) Want to learn about Vue 3, the Composition API and building real-world, production-ready applications with Vue 3? Check out our book Fullstack Vue 3 :

Thumbnail Image of Tutorial How to Fix the Error Error:error:0308010C:digital envelope routines::unsupported

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

How to Use Thunks with Redux Toolkit and TypeScript

Last time we used Redux Toolkit to create a todo app. Since RTK is considered to be the standard way to write redux applications, we will use thunks with Redux Toolkit to write asynchronous logic as well. Thunks are a way to manage side effects when working with Redux. For instance, when we want to fetch some data from a server we need to perform an HTTP request. That request is a side effect because it interacts with the “outer world”. Redux itself doesn't know anything about side effects in an app. All the work is done in the redux-thunk middleware. It extends the store's abilities and lets you write async logic that interacts with the store. Redux Toolkit's configureStore function automatically sets up the thunk middleware by default. Right now we have a todo app that works synchronously, so we can only use the runtime storage to store the user data. In real-life applications, we would need to store user's data in some kind of persistent storage, on a server for example. Let's change our app a bit and, as an example, create a method to load todos from the server and show them. First of all, we're going to slightly refactor our previous code. We will extract our useTypedSelector from features/todos/TodoList.tsx to app/store.ts : ...This will help us to re-use this function in another component later. Also, we will extract some todos types into features/todos/types.ts : ...Which will help us to cover the API requests with types. As a backend, we will use JSON-placeholder . It allows us to fetch a list of todo-objects that we can render in our UI. The endpoint we use returns a list of todo-objects RTK provides a function called createAsyncThunk for creating thunks. Let's start with creating one: Let's write the real request logic using our placeholder backend: Cool, now it's working. However, the result we return is not typed. TypeScript yet doesn't know about the structure of data we return. For typing the result , we're going to need Todo type we extracted earlier: Okay, now our fetchTodos function doesn't take any argument. But let's think about a situation when we need to control the amount of fetched todos. We could use a function argument for that: The only thing left to cover is errors. Imagine that the server responded with a status 400. In this case, we would need to tell our users that todos aren't loaded and show the error message. Now, let's add our thunk to todosSlice . For that, we need to slightly change our TodosState : After it's done, let's define a selector for getting the status value: Finally, let's add reducers for handling our fetchTodos actions: The last thing to do is to use the fetchTodos thunk inside a component. Let's create a button, click on which will fetch a list of todos from a server. Now we can use this component to load todos from the server.

Thumbnail Image of Tutorial How to Use Thunks with Redux Toolkit and TypeScript

How to Use Redux Toolkit with TypeScript

The Redux Toolkit package is intended to be the standard way to write Redux logic. It simplifies the store creation and decreases the amount of boilerplate code. Let's rewrite the application we wrote in one of the earlier posts from scratch to see what will change. First of all, we need to create a new app. We can use Create React App with TypeScript template and then add Redux Toolkit or we can use a template that already includes everything we need. Now, if you look in the redux-toolkit-app directory you will see not only App.tsx but also 2 new directories: For now, let's clear the features directory, we won't need anything inside of it. Redux Toolkit introduces a new concept called a slice . It is an object that contains a reducer function as a field named reducer , and action creators inside an object called actions . Basically, a slice is a store part responsible for a single feature. We may think of it as a set of actions, a reducer, and an initial state. Slices allow us to write less code and keep feature-related code closer thus increasing cohesion . For our first slice, we're going to use a createSlice function. Let's start with re-creating typings for our store: Then, we create an initial state: And now, we can start creating a slice: The todosSlice object now contains actions and reducer fields. Let's export everything they have from the module: To use the state in our components, we need to create a state selector. For that, we need to define a RootState type. Let's change the app/store.ts a bit: Now return to todosSlice.ts and create a selector: The code of our component will be almost the same, except for imports and selector usage. Let's review it: And the list: We gain some advantages using RTK, such as: There are however disadvantages as well:

What Happened to the FC Type's Implicit children Prop in @types/react v18?

In @types/react v18, the implicit children prop was removed from the FC type. According to a pull request for @types/react , this prop was supposed to be removed in @types/react v17, but was postponed to @types/react v18 so that developers can easily upgrade their React applications to v17 with few to zero problems . Assuming React v18 and @types/react v18 are both installed within a React project, and given the following code for a component that accept children as a prop... TypeScript raises the following error: The implicit children prop from the FC type ended up being removed for consistency; TypeScript should always reject excess props. Therefore, to resolve this error, manually (and explicitly) define the children prop in the component's props interface, like so: Here's a CodeSandbox demo that demonstrates both the problem and solution: https://codesandbox.io/embed/removal-implicit-children-test-xdfdpl?fontsize=14&hidenavigation=1&theme=dark Note : You may notice that PropsWithChildren still exists within the type definition file, and you may be tempted to use it to resolve this error. However, this prop is kept around for backwards compatibility purposes and for a specific codemod . If you want to learn more advanced techniques with TypeScript and React, then check out our Fullstack React with TypeScript Masterclass :

Thumbnail Image of Tutorial What Happened to the FC Type's Implicit children Prop in @types/react v18?