Our Global Presence
Canada
57 Sherway St,
Stoney Creek, ON
L8J 0J3
India
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
USA
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
Apollo Client 3 offers a few new features, including package rearrange changes and more caching features. Let’s proceed to take a look at how to use the latest features from Apollo Client 3.
The InMemoryCache API has expanded features. They include the eviction of objects and fields, garbage collection, types and fields configuration, and pagination helpers.
Let’s explore these changes by installing the @apollo/client package with its dependencies by running:
npm i @apollo/client graphql react
We can add the InMemoryCache into our Apollo Client by writing:
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; const cache = new InMemoryCache(); const client = new ApolloClient({ uri: "https://graphqlzero.almansi.me/api", cache }); client .query({ query: gql` { user(id: 1) { id name } } ` }) .then(console.log);
The client is created with the cache option, which we set to the InMemoryCache; the cached items will be in memory. Once we’ve done that, we can use the new InMemoryCache features that come with Apollo Client 3.
We can evict the cached items by calling:
cache.evict();
We can optionally pass in the cached object’s ID by writing:
cache.evict({ id: 'user' })
We can also add a field property of the object like so:
cache.evict({ id: 'user', fieldName: 'name' })
The cache.gc method lets us do garbage collection on cached items. The object is determined to be reachable by tracing from the root to all the child references. Normalized objects that aren’t visited are removed.
To clear the unreachable cached items, we just call:
cache.gc();
Garbage collection can also be configured to retain some items. To retain the object with the ID ‘user’, for instance, we can write;
cache.retain({ id: 'user' })
We can configure how to deal with dangling references. When an object is evicted from the cache, it might have objects that have other cached objects. Apollo Client preserves these references because they may still be used later.
We can change how these references are dealt with by using a custom read function. To do so, we would write:
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; const cache = new InMemoryCache({ typePolicies: { Query: { fields: { ruler(existingRuler, { canRead, toReference }) { return canRead(existingRuler) ? existingRuler : toReference({ __typename: "user", name: "Apollo" }); } } }, user: { keyFields: ["name"], fields: { offspring(existingOffspring, { canRead }) { return existingOffspring ? existingOffspring.filter(canRead) : []; } } } } }); const client = new ApolloClient({ uri: "https://graphqlzero.almansi.me/api", cache }); client .query({ query: gql` { user(id: 1) { id name } } ` }) .then(console.log);
We set the ruler of the cache to our own ruler function. We determine what references can be read.
If there’s an existing cache ruler, then we use it; otherwise, we get the item with toReference. The offspring method returns the objects where canRead returns true. This way, we know we can read those items.
We can create our own local field within the InMemoryCache object.
For instance, we can write:
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; const cache = new InMemoryCache({ typePolicies: { User: { fields: { age: { read(_, { variables }) { return Math.random() * 100; } } } } } });
We created a local field with name age. This way, we can include the field in our query like the loading state and the networkStatus. variables have the fields from the query. It also has the caching data.
It’s just a getter that returns a random number:
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; const cache = new InMemoryCache({ typePolicies: { User: { fields: { age: { read(_, { variables }) { return Math.random() * 100; } } } } } }); const client = new ApolloClient({ uri: "https://graphqlzero.almansi.me/api", cache }); client .query({ query: gql` { user(id: 1) { id name age @client } } ` }) .then(console.log);
We get the age field with age @client. The @client keyword distinguishes local fields from fields that are retrieved from the API.
Reactive variables is the new feature from Apollo Client 3.0 onwards. To create one, we use the makeVar method from the @apollo/client package. For instance, to create a children reactive variable, we can write:
import { makeVar } from "@apollo/client"; const children = makeVar(["jane", "mary"]);
It returns a function that has the value of the reactive variable. To call it and get the value, we can write:
console.log(children());
The console log should read:
["jane", "mary"]
Reactive variables are useful for storing local state outside of the Apollo Client cache. This is different from local states and cached items, which are retrieved from the cache. Modifying a reactive variable automatically triggers an update of all active queries that depend on the variable.
We can also store local state with reactive variables. To do that, we can write:
import { ApolloClient, InMemoryCache, gql, makeVar } from "@apollo/client"; const age = makeVar(Math.random() * 100); const cache = new InMemoryCache({ typePolicies: { User: { fields: { age: { read(_, { variables }) { return age(); } } } } } }); const client = new ApolloClient({ uri: "https://graphqlzero.almansi.me/api", cache }); client .query({ query: gql` { user(id: 1) { id name age @client } } ` }) .then(console.log);
Above, we created the age reactive variable, and we read it into the local state by returning it in the read method. Then we can query age like we do with other local states. Now, whenever our query changes, we’ll see a new value of age returned as well.
To update the reactive variable, we just pass in a new value, like so:
import { makeVar } from "@apollo/client"; const age = makeVar(Math.random() * 100); console.log(age()); age(Math.random() * 100); console.log(age());
We pass in a new value to the function returned by makeVar to update the value. Now both console logs should show different values.
We can define our own cache field policy so that we can read them in a way that’s different from what’s in the API.
For instance, we can write:
import { ApolloClient, InMemoryCache, gql } from "@apollo/client"; const cache = new InMemoryCache({ typePolicies: { User: { fields: { name: { read(name) { return name.toUpperCase(); } } } } } }); const client = new ApolloClient({ uri: "https://graphqlzero.almansi.me/api", cache }); client .query({ query: gql` { user(id: 1) { id name } } ` }) .then(console.log);
We created a type policy for the User type. fields has the fields we want to modify when reading, and we want the value of name to be upper-case.
So we make the name’s read method return the upper-case name. Now the console.log call in the then method should have the data field with user.name inside it being upper-case.
We can use this for many other applications, like setting default field values, transforming lists, changing field values, pagination, and much more.
Apollo Client 3 comes with many changes to caching, including the ability to clear cache data. We can also add local fields and change the ways normal fields are retrieved with cache policy.
For more information and to develop web application using Front-End JS, Hire Front-End Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using Front-End JS, please visit our technology page.
Content Source:
It has been two and a half years since React v16 was first released. The dev team promises that update v17 is incredibly important for the future of React but claims that no new features are being added. So what exactly does that mean? And how can React claim to be releasing a major new version without adding new features?
Past React updates have always caused deprecations of older versions. This could make it incredibly difficult for teams to upgrade their React versions, especially when working with large or neglected codebases. So, the React team has decided that v17 will lay the groundwork for a new method of adopting updates. When React v18 is released, developers will be able to choose to only upgrade parts of their app and keep other parts running on v17. React advises against this if you’re application is actively maintained or in large-scale production, but it can help teams who don’t actively maintain their application or who don’t need to migrate certain components to the newer version. In the future, new React versions won’t leave these apps behind or demand massive migrations.
To enable this ability, the React team has spent some time reworking the event system. These updates are what caused React v17 to be a major release since it could potentially break many applications.
Contrary to what you might think, React doesn’t attach events to individual elements. Instead, React binds one handler per event type to the document
node. This approach increases performance in applications with large element trees and also enables features like replaying events.
In the background, React can capture an event and determine which component to call before propagating the event up the component tree. However, in native Javascript, the event has already propagated to the document
level. While this may not sound like an issue, this system breaks when running multiple instances of React. If a React app nested inside of another one has stopped the propagation of the event, the parent React app will still capture the event. This was a major headache for developers looking to nest different versions of React. You may not think that this happens in production, but the Atom code editor encountered this issue four years ago!
React will now attach event handlers to the root node of the React app. This change will allow the safe nesting of React trees within each other. Granted, all React instances will have to be running on version 17 or higher for this to work. This update also means that React apps are easier to embed inside of other frameworks like jQuery. React will now stop events from propagating to jQuery as one would expect.
It is fairly common to return a cleanup function within a useEffect
method to stop any code running within the function. In the past, this cleanup function would run synchronously before the next frame was drawn. In reality, most apps don’t require screen updates to be delayed will running cleanup methods. So they will now run asynchronously after React has rendered the next frame. This should result in faster switch times between components. You can still use the useLayoutEffect
method to run a cleanup method that blocks the render loop.
Event pooling is incredibly confusing and doesn’t provide any optimizations on modern browsers. Instead, it can result in some strange bugs when working with multiple components that receive the same event. One event handler might set the event to be null, and thus the other components using the event would run into a null variable error. In short, newer React version will allow event fields to be accessed whenever you need them.
React v17 may not be the feature-packed update React developers were hoping for. It is instead more of a piece-of-mind update. So while we may not be getting cool new components or hooks, these additions will pay off down the road in later updates. You can try React v17 now by running npm install react@17.0.0-rc.0 react-dom@17.0.0-rc.0
in your React project.
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
React Router is by far the most popular library in the React ecosystem. According to npm, it is downloaded about 3.6 million times a week. This number is almost half of React’s 7.6 million weekly downloads. This means that almost every second project that uses React uses React Router.
That’s huge. Almost half of the React projects out there rely on React Router for routing. Chances are, if you have worked with React, you have worked with React Router.
Now with version six in beta and a new release coming soon, we thought it would be interesting to take a dive into what’s new and what has changed in React Router version 6.
For a library that is so important to the React community, it has gone through a number of iterations and breaking changes. From its first release in 2014, and with every major release, the maintainers of React Router have introduced new features and breaking changes. Some in the React community have complained about the difficulty of upgrading from one version to the next, and have questioned the library’s constant churn.
Many have complained about the difficult upgrades that came with every new major release of the library.
If your application is working correctly, and you don’t need access to the new features promised in version 6, you can stick with your older version. Don’t feel the need to refactor your old applications to use React Router 6. If it ain’t broke, don’t fix it.
npm install react-router@next react-router-dom@next
So without further ado, let’s take a look at what’s new and what has changed in the latest version of React Router
Routes is introduced as a new element in React Router version 6. This new element allows us to easily define nested routes and relative routes, and make it easy to compose complex routes and layouts. In the previous version of the library, we defined Routes inside of a Switch.
The <Routes > is the new <Switch> element now. It is very much similar to <Switch> with some new features.
// old - v5 import { BrowserRouter, Switch, Route } from 'react-router-dom'; const App = () => { return ( <BrowserRouter> <Switch> <Route exact path="/" component={Home} /> <Route path="/users" component={Users} /> </Switch> </BrowserRouter> ); } // new - v6 import { BrowserRouter, Routes, Route } from 'react-router-dom'; const App = () => { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="users" element={<Users />} /> </Routes> </BrowserRouter> ); }
Did that component prop got changed to element?
That brings us to our second highlight.
If you notice in the above example, in the new version we are passing a react element instead of a component. This is so much better, now we can pass props directly to the element.
// old - v5 <Route exact path="/" component={Home} /> <Route path="/users" render={routeProps => ( <Users isCustomLayout={true} /> )} /> // new - v6 <Route path="/" element={<Home />} /> <Route path="users" element={<Users isCustomLayout={true} />} />
Now, all Route and Link children of a Route are relative to their parent. This makes it a lot easier to build applications with many nested routes and makes it easier to reason about your application’s routing logic.
No more exact and strict props
Yes, you read it right. In v6 all the routes match exactly by default.
// old - v5 <Route exact path="/" component={Home} /> // new - v6 <Route path="/" element={<Home />} />
Relative paths and links
In v6, both paths and links are relative to their parent route. This means we can omit the “/” if we want the relative path.
// old - v5 <Route exact path="/" component={Home} /> <Route path="/users" component={Users} /> // new - v6 <Route path="/" element={<Home />} /> <Route path="users" element={<Users />} />
If you have used previous versions of React Router, you will immediately notice that we don’t need to use the exact prop anymore. You will also notice that the Link we defined is relative. Instead of passing /customers/:id, we can just use /:id.
What about nested routes then? They just got better.
Just like your regular react elements we just need to wrap the child route with a parent one.
// old - v5 <Route exact path="/" component={Home} /> <Route path="/users" component={Users} /> // .... users.js import { useRouteMatch } from 'react-router-dom'; const Users = () => { const { path } = useRouteMatch(); return ( <div> // you can do something here <Switch> <Route path={`${path}/:id`} component={UserInfo} /> <Route path={`${path}/profile`} component={UserProfile} /> </Switch> </div> ); } // new - v6 <Route path="/" element={<Home />} /> <Route path="users" element={<Users />}> <Route path=":id" element={<UserInfo />} /> <Route path="profile" element={<UserProfile />} /> </Route> // .... import { Outlet } from 'react-router-dom'; const Users = () => { return ( <div> // you can do something here // Outlet: This element is used as a placholder for the child route. // Which means it will be either <UserInfo /> or <UserProfile /> <Outlet /> </div> ); }
Now we can define our routes using the new useRouter hook. This allows you to build your routes using JavaScript objects. Let’s take a look at our previous application, now defined using useRouter.
import { BrowserRouter, Link, Outlet, useRoutes } from 'react-router-dom'; function App() { let element = useRoutes([ { path: '/', element: <Home /> }, { path: 'customers', element: <Customers />, children: [ { path: '/', element: <CustomersIndex /> }, { path: ':id', element: <CustomerProfile /> }, ] } ]); return element; } function Users() { return ( <div> <nav> <Link to="/1">Customer 1</Link> </nav> <Outlet /> </div> ); }
You might ask yourself, why does it matter? Why would I want to compose my routes using JavaScript objects instead of JSX? One great use case would be to programmatically build routes, let’s say, based on the directory structure of your application. You could loop through all of the files in your pages directory, and build routes from that.
The team behind React Router claims that the new version is a lot smaller than the previous versions. They estimate that it’s about 70% smaller. Smaller bundles mean that your application loads faster, and content to your users faster.
With all these awesome changes, there is also icing on the cake. They have reduced the bundle size by more than 50%.
The old useHistory hook has been removed and replaced with a suspense-ready navigate API. Now you can use useNavigate to programmatically navigate around your application. They also expose a Navigate component that you can use to redirect your users.
No more history, it’s time to navigate. The useHistory hook is now replaced with the suspense-ready useNavigate hook.
// old - v5 import { useHistory } from 'react-router-dom'; const CustomButton = props => { const history = useHistory(); const handleClick = () => { history.push('/users'); } return <button onClick={handleClick}>{props.label}</button>; } // new - v6 import { useNavigate } from 'react-router-dom'; const CustomButton = props => { const navigate = useNavigate(); const handleClick = () => { navigate('/users'); } return <button onClick={handleClick}>{props.label}</button>; }
So that’s it! If you believe that your applications can benefit from smaller bundle sizes, and from suspense ready navigation, we strongly suggest that you upgrade to the latest version.
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
In the frontend development world, we oftentimes need to have up-to-date data on the client. And to achieve that there are several options at our disposal:
While the first to are preferred, polling still is an important tool especially in situations when our backend can’t provide us with WS or SSE. And in this article, we will be reviewing how to use polling with arguably the most widely-used state manager in the JavaScript realm – Redux.
There are two basic types of polling – Short and Long. For the sake of simplicity, we will be reviewing only Short polling. It’s the easiest one to implement – all it does – sends requests from the client-side to the server at a certain fixed interval. For example, let’s say we have a small website that shows the current weather in a selected region. And to keep the client up-to-date we can use the Short polling technique, that is, send client-to-server requests (for weather data) every 30 seconds. And, therefore, approximately (time between responses might differ) every 30 seconds we will be getting new weather data.
Now, let’s see how we can implement polling in React & Redux application. In our examples, we’ll continue working on the weather application and see how it can be realized using different techniques.
The most naive implementation would be by using the “setInterval” function in the “componentDidMount” method (or the “useEffect” hook).
In this implementation, we’re creating the “updateInterval” variable that points to an actual interval function after it’s being initialized in the “componentDidMount” life cycle method. The interval dispatches the “getWeatherData” redux-action every 30 seconds and does so continually while the component is mounted.
class WeatherApp extends Rect.Component { updateInterval; componentDidMount() { this.updateInterval = setInterval(() => { this.props.getWeatherData(); }, 1000 * 30); // 30 seconds } componentWillUnmount() { clearInterval(updateInterval); } render() { return ( <div> {this.props.weatherData} </div> ); } }
The biggest downside of this approach is that business logic (pulling data) is tight to the view. The other problem is that the “setInterval” function doesn’t wait till the previous action call (from the “setInterval” body) is completed. Therefore, this version can be improved by using the “setTimeout” function, with the help of which we can start each next cycle only when the previous one is completed. Thus, we won’t accidentally run into a situation where we have two (or even more) calls simultaneously (might happen in the case with “setInterval” on when we have small delays between cycles).
Here is our improved version with the use of the “setTimeout” function.
class WeatherApp extends React.Component { updateTimeout; componentDidMount() { this.getWeatherData(); } getWeatherData = async () => { await this.props.getWeatherData(); this.updateTimeout = setTimeout(this.getWeatherData, 30 * 1000); } componentWillUnmount() { clearTimeout(updateTimeout); } render() { return ( <div> {this.props.weatherData} </div> ); } }
We would like to point out that it’s not an actual code from production, just an example. And there is a good chance that async/await won’t be a viable option because the “getWeatherData” function most likely won’t be an asynchronous function – in such instances, we can use callbacks.
Nevertheless, even this improved version is still not good enough because we didn’t resolve the main problem – a tight connection between business logic and the presentation layer. And one of the drawbacks of previous solutions is that the update logic is defined in components thus making it hardly reusable.
By creating a custom action that will encapsulate all the “update by timeout” logic in action’s body – we can address the reusability drawback mentioned earlier and untight the connection between layers.
export const initActions = async dispatch => { let updateTimeout; getWeatherDataTimedout = async () => { await dispatch(getWeatherData()); updateTimeout = setTimeout(getWeatherDataTimedout, 30 * 1000); } /** Initialize any other actions */ getWeatherDataTimedout(); } class WeatherApp extends React.Component { componentDidMount() { this.props.initActions(); } render() { return ( <div> {this.props.weatherData} </div> ); } }
Again, it’s a simplified version. And the “initActions” function can be easily extended by adding custom parameters that can be passed from containers and by adding more actions that can be dispatched in the action’s body.
But we should look for another approach if we want to unentangle the “update by timeout” logic from the View as much as possible.
One of the ways to achieve that level of disentanglement is to use Redux middlewares.
The concept is quite straightforward – middleware is some sort of a middleman between dispatching actions and actual execution of those same actions in the reducer.
With all that in mind, we can create a middleware for the “getWeatherData”:
const getWeatherDataTimedout = async dispatch => { await getWeatherData()(dispatch); setTimeout(() => updateMessages(dispatch), 30 * 1000); }; const getWeatherDataMiddleware = ({ dispatch }) => next => { getWeatherDataTimedout(dispatch); return action => next(action); };
But just creating middleware is not enough, it should be “registered” at the global store. To do so we can use the “compose” function inside of the “createStore” as follows:
const store = createStore( rootReducer, compose(applyMiddleware(/** other middlewares */, getWeatherDataMiddleware)) );
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
Version 10.0.0 is here! This is a major release that spans the entire platform, including the framework, Angular Material, and the CLI. This release is smaller than typical; it has only been few months since we released version 9.0 of Angular.
We try to release two major versions each year to keep Angular synchronized with the rest of the JavaScript ecosystem and to have a predictable schedule. We plan to release version 11 this fall.
New Date Range Picker
Angular Material now includes a new date range picker.
To use the new date range picker, you can use the mat-date-range-input
and mat-date-range-picker
components.
Warnings about CommonJS imports
When you use a dependency that is packaged with CommonJS, it can result in larger slower applications.
Starting with version 10, we now warn you when your build pulls in one of these bundles. If you’ve started seeing these warnings for your dependencies, let your dependency know that you’d prefer an ECMAScript module (ESM) bundle.
Optional Stricter Settings
Version 10 offers a more strict project setup when you create a new workspace with ng new
.
ng new --strict
Enabling this flag initializes your new project with a few new settings that improve maintainability, help you catch bugs ahead of time, and allow the CLI to perform advanced optimizations on your app. Specifically, the strict
flag does the following:
any
Keeping Up to Date with the Ecosystem
As usual, we have made a few updates to the dependencies of Angular to stay synchronized with the JavaScript ecosystem.
We’ve also updated our project layout. Starting with version 10 you will see a new tsconfig.base.json
. This additional tsconfig.json
file better supports the way that IDEs and build tooling resolve type and package configurations.
New Default Browser Configuration
We’ve updated the browser configuration for new projects to exclude older and less used browsers.
v9 Defaults
v10 Defaults
This has the side effect of disabling ES5 builds by default for new projects. To enable ES5 builds and differential loading for browsers that require it (such as IE or UC Browser), simply add the browsers you need to support in the .browserslistrc
file.
Angular Team Fixit
We’ve dramatically increased our investment in working with the community. In the last three weeks our open issue count has decreased by over 700 issues across framework, tooling, and components. We’ve touched over 2,000 issues, and we plan to make large investments over the next few months, working with the community to do even more.
Deprecations and Removals
We’ve made several new deprecations and removals from Angular.
The Angular Package Format no longer includes ESM5 or FESM5 bundles, saving you 119MB of download and install time when running yarn
or npm install
for Angular packages and libraries. These formats are no longer needed as any downleveling to support ES5 is done at the end of the build process.
Based on heavy consultation with the community, we are deprecating support for older browsers including IE 9, 10, and Internet Explorer Mobile.
You can read more about our deprecations and removals.
Visit update.angular.io for detailed information and guidance. To have the best update experience, we recommend always upgrading one major release at a time.
To update:
ng update @angular/cli @angular/core
For more information and to develop web application using Angular, Hire Angular Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop web application using Angular, please visit our technology page.
Content Source:
In this article, you’re going to see how to set up Jenkins from scratch and create and run an Angular pipeline — all in about five minutes. Don’t worry if you’re not familiar with Angular. The same principles hold for Vue, React, Python, Java, and other languages. So get comfy because we’re about to start.
The structure of the article will be as follows:
If you’re already familiar with Jenkins, feel free to skip this part.
In this section, we’ll go over the installation steps for macOS and Linux as shown on the Jenkins website. You can also find information on getting started on a Windows machine.
First, let’s create a network for Jenkins:
docker network create jenkins
Add two volumes to share Docker client TLS certificates and persist Jenkins data. This way, no data is lost when you shut down your PC or server, for example. Keep in mind that if you do remove these volumes, data will be lost permanently.
docker volume create jenkins-docker-certs docker volume create jenkins-data
The following four commands bring the Docker container up:
docker image pull docker:dind docker container run --name jenkins-docker \ --restart unless-stopped \ --detach \ --privileged --network jenkins \ --network-alias docker \ --env DOCKER_TLS_CERTDIR=/certs \ --volume jenkins-docker-certs:/certs/client \ --volume jenkins-data:/var/jenkins_home \ --publish 2376:2376\ docker:dind docker image pull jenkinsci/blueocean docker container run --name jenkins-blueocean \ --restart unless-stopped \ --detach \ --network jenkins \ --env DOCKER_HOST=tcp://docker:2376 \ --env DOCKER_CERT_PATH=/certs/client \ --env DOCKER_TLS_VERIFY=1 \ --volume jenkins-data:/var/jenkins_home \ --volume jenkins-docker-certs:/certs/client:ro \ --publish 8080:8080 \ --publish 50000:50000 \ jenkinsci/blueocean
Jenkins is now running on http://localhost:8080, but you have to do one more tricky step: You have to unlock Jenkins. The initial password can be found inside a folder of the Jenkins CI blue ocean Docker container. I’ll show you how to retrieve this. When you try this yourself, make sure you specify the right docker UUID.
docker container ps 4ec29afb280f jenkinsci/blueocean 1ce11b131265 docker:dind docker container exec 4ec29afb280f cat /var/jenkins_home/secrets/initialAdminPassword bd95aa5131a142b690795fa9427287a8
In the next step, you can configure the plug-ins you want to install. I’ll leave that up to you. I installed the Cobertura (for Java) and Locale plug-ins and got rid of Subversion. After they are installed, you have to create an admin user.
In the last step, you have to set a Jenkins URL (e.g. http://localhost:8080), but I did not bother to change it. In the end, Jenkins restarts and is completely installed. That took us literally only a couple of minutes.
Let’s face it, there are tons of possible ways to define a great pipeline. This will only be a simple example. It would be great to hear if you have suggestions for an improved pipeline. Don’t hesitate to leave a comment at the end of the article!
First of all, it’s important to specify a base Docker image to run our commands. At the time of writing, using the latest node Docker image felt like a good choice.
Next, we specify the stages to go over. In this configuration, the most recognizable development stages are specified:
Feel free to add additional steps. At this point, you have so much freedom. Deploy automatically or publish a Docker image that can be rolled out to a limited amount of users. That choice is yours. To conclude this section, let me share the pipeline with you. Put this inside a Jenkinsfile (no extension) in the root folder of your project:
pipeline { agent { docker { image 'node:latest' } } stages { stage('Install') { steps { sh 'npm install' } } stage('Test') { parallel { stage('Static code analysis') { steps { sh 'npm run-script lint' } } stage('Unit tests') { steps { sh 'npm run-script test' } } } } stage('Build') { steps { sh 'npm run-script build' } } } }
Open Jenkins on http://localhost:8080 and create a new item. No need to do a lot here, actually. Let’s create a “Multibranch Pipeline.”
A new menu opens. Here, you can add a description among many other things, but we’ll only cover the most important parts in this article. You should look for the section called “branch sources” and select Git. The next thing to do is pass in a project repository (e.g. https://github.com/user/project-name.git) and your credentials. That is sufficient.
Let’s add one more thing to make it an automatic pipeline. Let’s poll the GitHub repository for changes. Enable “Scan Multibranch Pipeline Triggers” and pass a reasonable interval. This will trigger a build (e.g. every minute) only when there are source code changes. That way, builds get triggered automatically. If one minute is too intensive, you can always lower the interval to check for changes later on.
Now go to http://localhost:8080/blue/organizations/jenkins/pipelines and run your first job if it’s not already running. Let me show you how this looks:
For more information and to develop web application using Angular, Hire Angular Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop web application using Angular, please visit our technology page.
Content Source:
Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone while being compatible with the newest features of React.
While working with react you might have noticed that are different ways to manage the global state management in React. Let’s take look at the options that we have:
Redux is a predictable state container for JavaScript apps.
It is used by a lot of web apps these days, it allows us to have a global state, register components to it and they will re-render by themselves every time a value they registered to will change.
Context API is another approach that devs take for better management of state within the application.
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
Now that we are already using to above two famous ways of adding global state to our application here comes something new i.e Recoil.
Recoil lets you create a data-flow graph that flows from atoms (shared state) through selectors (pure functions) and down into your React components.
React
local component state. If the same atom is used from multiple components, all those components share their state.Let’s try to understand this with a Demo example.
Consider we want to store user data upon login into our application and share between two components,
Let first define an atom which stores the logged-in user Data
In the above example, we have stored the object which has a name in it. It is stored inside our loggedInUserData
atom.
Now consider we need to show this name in our useRecoilState
.
And our component looks something like this, which display the data from the same atom which is used in the header component again with help of useRecoilState
The syntax might look quite similar to useState which we are already used to in react
hooks.
As in the above example since the same state is shared between the
This is one of the important hooks in the Recoil API. This hook will just subscribe to the component to the given Recoil state, it is used to return the value of the given Recoil state.
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
Vue 3 isn’t officially released yet, but the Vue team has released the Alpha version to use some of the features that will be shipped with Vue 3.
We’ll use the WebPack-based setup.
To do this, clone this repository:
git clone https://github.com/vuejs/vue-next-webpack-preview.git vue-next cd vue-next
Now install the packages:
npm install
That’s it. We have a working Vue 3 project set up now.
To spin up the application, just run the following:
npm run dev
Open localhost:8080
in your browser, and you can see a simple counter application.
Open the package.json
file, you can see the Vue version here. At the time of writing this article, the version is 3.0.0-alpha.8
.
Open App.vue
and you’ll see the setup()
method, i.e. the Composition API already being used here. We might see some lint errors from Vue’s official plugin, eslint-plugin-vue
, because the linters are not yet updated to understand the new syntax.
Before we start coding, let’s go over the new features in Vue 3.
Vue 3 is faster, smaller in file size, and equipped with better TypeScript support. Some of the new features that we can discuss and learn to implement in this article include:
Composition API was launched as a plugin a few months back, so there is nothing new there, but in Vue 3 we don’t have to install it like a plugin anymore. Now, it’s built into the package and can be used out of the box without any additional setup.
There are two main advantages to using the Composition API:
If you are new to Composition API, here is how we can use it to implement a component:
<template> <div class="counter"> <p>count: {{ count }}</p> <p>NewVal (count + 2): {{ countDouble }}</p> <button @click="inc">Increment</button> <button @click="dec">Decrement</button> <p> Message: {{ msg }} </p> <button @click="changeMessage()">Change Message</button> </div> </template> <script> import { ref, computed, watch } from 'vue' export default { setup() { /* ---------------------------------------------------- */ let count = ref(0) const countDouble = computed(() => count.value * 2) watch(count, newVal => { console.log('count changed', newVal) }) const inc = () => { count.value += 1 } const dec = () => { if (count.value !== 0) { count.value -= 1 } } /* ---------------------------------------------------- */ let msg= ref('some text') watch(msg, newVal => { console.log('msg changed', newVal) }) const changeMessage = () => { msg.value = "new Message" } /* ---------------------------------------------------- */ return { count, inc, dec, countDouble, msg, changeMessage } } } </script>
And here’s the equivalent code in Options API:
<template> <div class="counter"> <p>count: {{ count }}</p> <p>NewVal (count + 2): {{ countDouble }}</p> <button @click="inc">Increment</button> <button @click="dec">Decrement</button> <p> Message: {{ msg }} </p> <button @click="changeMessage()">Change Message</button> </div> </template> <script> export default { data() { return { count: 0, msg: 'some message' } }, computed: { countDouble() { return this.count*2 } }, watch: { count(newVal) { console.log('count changed', newVal) }, msg(newVal) { console.log('msg changed', newVal) } }, methods: { inc() { this.count += 1 }, dec() { if (this.count !== 0) { this.count -= 1 } }, changeMessage() { msg = "new Message" } } } </script>
We can see that using Composition API allows us better organization by keeping the the code (state, methods, computed properties, watchers etc) of particular features together, which was not possible in Options API.
In the above example, the code for counter
and the code for changing a message
is clearly separated in Composition API.
Using the Composition API makes sharing the code much easier. We can factor out the code for a particular feature and use it in multiple places, as shown below:
//message.js import { ref, watch } from 'vue' export function message() { let msg = ref(123) watch(msg, newVal => { console.log('msg changed', newVal) }) const changeMessage = () => { msg.value = 'new Message' } return { msg, changeMessage } }
Using the shared code in our component
<template> <div class="counter"> <p>count: {{ count }}</p> <p>NewVal (count + 2): {{ countDouble }}</p> <button @click="inc">Increment</button> <button @click="dec">Decrement</button> <p>Message: {{ msg }}</p> <button @click="changeMessage()">change message</button> </div> </template> <script> import { ref, computed, watch } from 'vue' import { message } from './common/message' export default { setup() { let count = ref(0) const countDouble = computed(() => count.value * 2) watch(count, newVal => { console.log('count changed', newVal) }) const inc = () => { count.value += 1 } const dec = () => { if (count.value !== 0) { count.value -= 1 } } let { msg, changeMessage } = message() return { count, msg, changeMessage, inc, dec, countDouble } } } </script>
In Vue 2, the template tag can only take one root element. Even if we had just two <p>
tags, we had to enclose them within a <div>
tag to get it working. Because of this, we had to change the CSS code as well in the parent component so that it looked as expected.
In Vue 3, this restriction is lifted. There is no need for a root element anymore.
We can use any number of tags directly inside the <template></template>
section:
<template> <p> Count: {{ count }} </p> <button @click="increment"> Increment </button> <button @click="decrement"> Decrement</button> </template>
Equivalent code in Vue 2:
<template> <div class="counter"> <p> Count: {{ count }} </p> <button @click="increment"> Increment </button> <button @click="decrement"> Decrement</button> </div> </template>
Suspense is a new feature that renders a default/fallback component until the main component fetches the data.
Sometimes we use async operations to fetch data from the server. Instead of handing the template with v-if and then setting it back when we return the data, Suspense does it for us.
Suspense can be used for both parts of the template, or the whole template:
<template> <Suspense> <template #default> <div v-for="item in articleList" :key="item.id"> <article> <h2>{{ item.title }}</h2> <p>{{ item.body }}</p> </article> </div> </template> <template #fallback> Articles loading... </template> </Suspense> </template> <script> import axios from 'axios' export default { async setup() { let articleList = await axios .get('https://jsonplaceholder.typicode.com/posts') .then(response => { console.log(response) return response.data }) return { articleList } } } </script>
We all know that v-model is used for two-way binding. We mostly use it with form elements. Sometimes, we even use it with custom components.
Vue-2 allowed the use of only one v-model on a component. In Vue-3, we can bind any number of v-models to our custom components:
<template> <survey-form v-model:name="name" v-model:age="age"> </survey-form> </template> //SurveyForm.vue <template> <div> <label>Name: </label> <input :value="name" @input="updateName($event.target.value)" /> <label>Age: </label> <input :value="age" @input="updateAge($event.target.value)" /> </div> </template> <script> export default { props: { name: String, age: Number }, setup(props, { emit }) { const updateName = value => { emit('update:name', value) } const updateAge = value => { emit('update:age', +value) } return { updateName, updateAge } } } </script>
Vue 2 already had great reactivity, and you might not have come across any cases where you found that reactivity was lacking. However, there were a few cases where Vue 2 fell short.
Let’s revisit Vue 2 and see what those limitations were.
To demonstrate reactivity, we’ll use watchers to listen to one of the state variables and then modify it to see if the watchers are triggered:
<template> <div class="hello" @click="test">test {{list }} {{ myObj }}</div> </template> <script> export default { name: "HelloWorld", data() { return { list: [1, 2], myObj: { name: "Preetish" } }; }, watch: { list: { handler: () => { console.log("watcher triggered"); }, deep: true } }, methods: { test() { this.list[2] = 4; this.myObj.last = "HS"; delete this.myObj.name; } } }; </script>
None of the above three modifications — such as adding a new item to an array based on the index, adding a new item to an object, or deleting an item from the object — is reactive in Vue-2. Hence watchers
won’t be triggered, or the DOM would be updated. We had to use the vue.set()
or vue.delete()
methods.
In Vue-3, these work directly without any helper functions:
export default { setup() { let list = ref([1, 2]) let a = ref(0) let myObj = ref({ name: 'Preetish' }) function myFun() { list.value[3] = 3 myObj.value.last = 'HS' delete myObj.value.name } return { myFun, list, myObj } } }
We can see that watcher
was triggered all four times in the Vue 3 setup.
When you open main.js
in the about
project, you’ll notice something different. We no longer use the Global Vue instance to install plugins and other libraries.
Instead, you can see createApp
method:
import { createApp } from 'vue' import App from './App.vue' const myApp = createApp(App) myApp.use(/* plugin name */) myApp.use(/* plugin name */) myApp.use(/* plugin name */) myApp.mount('#app')
The advantage of this feature is that it protects the Vue application from third party libraries/plugins we use which might override or make changes to the global instance — mostly by using Mixins.
Now with the createApp
method, we install those plugins on a particular instance and not the global object.
Portal is a feature where we can render a part of the code which is present in one component into a different component in a different DOM tree. There was a third-party plugin called portal-vue
that achieved this in Vue 2.
In Vue 3, portal will be built in and it is very easy to use.
Vue 3 will have a special tag called <Teleport>
, and any code enclosed within this tag will be ready to be teleported anywhere. The Teleport
tag takes a to
argument.
Let’s see this in action:
<Teleport to="#modal-layer"> <div class="modal"> hello </div> </Teleport>
Any code inside <Portal></Portal>
will be displayed in the target location mentioned.
<div id="modal-target"></div>
At the time of writing this article, <Teleport>
doesn’t work in the Alpha version mentioned above.
For more information and to develop website using Vue.js, Hire Vue.js Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop Website using Vue.js, please visit our technology page.
Content Source:
This is a minor release of the framework and the CLI that is a drop-in replacement for 9.0 containing new features and bug fixes.
Today, the Angular libraries you use are made compatible with the Ivy compiler via our ngcc
tool. Previously, the ngcc
compilation pass covered all of your Angular library dependencies sequentially. In 9.1, we’ve improved the speed of ngcc
, and allowed it to compile multiple packages concurrently.
These changes will help make builds faster and improve reliability for teams with monorepository-style workspace layouts.
We’ve added support for TypeScript 3.8, in addition to our existing support for 3.6 and 3.7.
This release adds many great features to the TypeScript language, including:
Angular components are displayed inline
by default, as that’s the default for most DOM elements. It’s very common for developers to want components to use the display: block
style. When you create a new component, you can now set this up automatically.
ng generate component my-component --displayBlock
To turn this on by default, set the schematics.@schematics/angular:component.displayBlock
key in your angular.json
to true, or use:
ng config schematics.@schematics/angular:component.displayBlock true
When running end-to-end tests, we now pass the grep
and invertGrep
options to the Protractor builder, allowing you to more easily choose the test you want to run.
ng e2e --grep searchTerm
If you use VSCode and our Language Service Extension, starting today our extension will allow your IDE to syntax highlight expressions in your templates, using a TypeScript-like formatter. It will also add syntax highlighting to your inline HTML templates in your components.
Note: We worked with the authors of angular2-inline and vscode-angular-html on these features. If you use either of these extensions, you’ll need to disable them for this functionality to work.
If you build an application with Internationalization, you may be building a single app that supports Right to Left locales. You can now query for the current direction at runtime.
import { getLocaleDirection, registerLocaleData } from '@angular/common'; import { LOCALE_ID } from '@angular/core'; import localeAr from '@angular/common/locales/ar'; ... constructor(@Inject(LOCALE_ID) locale) { getLocaleDirection(locale); // 'rtl' or 'ltr' based on the current locale registerLocaleData(localeAr, 'ar-ae'); getLocaleDirection('ar-ae'); // 'rtl' // Now use the current direction in your app. // You can conditionally specify an image URL for example }
Newly created projects will now use TSLint 6.1 by default. If you want to migrate to the latest version, make sure you are on version 9.1 first, then you can opt-in via:
ng update @angular/cli --migrate-only tslint-version-6
We do not run this migration automatically because there are some minor breaking changes in TSLint 6.1.
This release includes lots of other bug fixes, performance improvements, and minor features. Version 9.1 also improves the compatibility story with our new compiler and runtime. If you previously attempted to enable Ivy with version 9.0 and ran into issues, try again with version 9.1.
Update to the latest version of Angular to get access to these new capabilities and bug fixes.
ng update @angular/cli @angular/core
For more information and to develop web application using Angular, Hire Angular Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop any custom web apps using Angular, please visit our technology page.
Content Source:
Babel is a JavaScript compiler that includes the ability to compile JSX into regular JavaScript.
Array.from
and built-ins like Promise
are only available in ES6+, but they can be used in older environments if a Babel polyfill is.@babel/register is often used in Node.js. It makes the babel run dynamically when the require
code is executed. Since it’s not popular way to run babel in React, we are not going to deal with @babel/register way.
Let’s Create sample project.
— Create a directory and package.json
mkdir test-babel-how cd test-babel-how npm init -y
— Install the necessary packages
npm i @babel/core @babel/cli @babel/plugin-transform-arrow-functions @babel/plugin-transform-template-literals @babel/preset-react
— Create a sample code
src
folder and create code.js
in the src
folder.test-babel-how | -- node_modules -- src | -- code.js -- package-lock.json -- package.json
const element = <div>babel test</div>; // 1 const text = `element type is ${element.type}`; // 2 const add = (a,b)> a + b; // 3
We are going to:
— run the following command in the terminal
npx babel src/code.js // 1 --presets=@babel/preset-react // 2 --plugins=@babel/plugin-transform-template-literals, // 3 @babel/plugin-transform-arrow-functions
src/code.js
.@babel/preset-react
.@babel/plugin-transform-template-literals
& @babel/plugin-transform-arrow-functions
.— Following output in the terminal
const element = /*#__PURE__*/React.createElement("div", null, "babel test" ); // 1 const text = "element type is ".concat(element.type); // 2 const add = (a, b) > a + b; // 3
concat
method.— install packages to use webpack
npm i webpack webpack-cli babel-loader
— create a babel.config.js
file
const presets = ['@babel/preset-react']; const plugins = [ '@babel/plugin-transform-template-literals', '@babel/plugin-transform-arrow-functions' ]; module.exports = { presets, plugins };
babel.config.js
to specify presets & plugins.— create a webpackge.config.js
file
const path = require('path'); module.exports = { entry: './src/code.js', // 1 output: { // 2 path: path.resolve(__dirname, 'dist'), filename: 'code.bundle.js', }, module: { // 3 rules: [{ test: /\.js$/, use: 'babel-loader'}], }, optimization: { minimizer: []} , // 4 }
dist/code.bundle.js
file.babel-loader
to handle JavaScript files.babel.config.js
file.— run webpack
npx webpack
— dist/code.bundle.js
is created with a following output:
/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; // ... // ... /* 0 */ /***/ (function(module, exports) { const element = /*#__PURE__*/React.createElement("div", null, "babel test"); // 1 const text = "element type is ".concat(element.type); // 2 const add = (a, b) > a + b; // 3 /***/ }) /******/ ]);
// ...
part is webpack’s run time code.— create runBabel.js
file
const babel = require('@babel/core'); // 1 const fs = require('fs'); const filename = './src/code.js'; const source = fs.readFileSync(filename, 'utf8'); // 2 const presets = ['@babel/preset-react']; // 3 const plugins = [ '@babel/plugin-transform-template-literals', '@babel/plugin-transform-arrow-functions', ]; const { code } = babel.transformSync(source, { // 4 filename, presets, plugins, configFile: false, // 5 }); console.log(code); // 6
code.js
to compiletransformSync
function— run file
node runBabel.js
const element = /*#__PURE__*/React.createElement("div", null, "babel test" ); // 1 const text = "element type is ".concat(element.type); // 2 const add = (a, b) > a + b; // 3
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop any custom web apps using React JS, please visit our technology page.
Content Source:
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
© 2024 — HK Infosoft. All Rights Reserved.
© 2024 — HK Infosoft. All Rights Reserved.
T&C | Privacy Policy | Sitemap